안드로이드 컴포즈에는 SwipeToDismiss 라는게 이미 만들어져 있다.
레이아웃을 옆으로 밀면 밀어낸 반대 방향에 버튼이 생기는 레이아웃 같은걸 만들때 쓴다.
하지만? 나는 또 다른 디자인으로 만들고 싶었다. 찾아보면 이걸 사용해서도 방법은 있겠지만
그냥 내가 생각나는대로 만드는게 빠를거 같아서 만들어봤다.
혹시나 구글이 준비해준 SwipeToDismiss 가 맘에 안드는 사람들에게 귀찮음을 덜어줄 수 있었으면 한다.
만드려는 레이아웃은 이렇다.
순서는 아래와 같다.
1. 스와이프 했음을 인지하는 방법
2. 스와이프한 값을 이용해서 컴포넌트를 스와이프 한 방향으로 옮기는 방법
3. 삭제 버튼을 나오게 하는 방법
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun IntroduceComponent(
isDimmed : (Boolean)->Unit
) {
var isDim by remember { mutableStateOf(false) }
var offsetX by remember { mutableStateOf(0.dp) }
Box(
modifier = Modifier
.fillMaxWidth()
.padding(start = 22.dp)
.pointerInput(Unit) {
detectTransformGestures { _, pan, _, _ ->
val translationX = pan.x
onLeftSwipe(translationX) { it ->
if ((offsetX * -1) > 80.dp) {
offsetX = (offsetX + it).coerceAtLeast((-81).dp)
isDimmed(true)
isDim = true
} else {
offsetX = (offsetX + it).coerceAtMost(0.dp)
isDimmed(false)
isDim = false
}
}
}
}
) {
// 내용물 (가장 마지막에 제공된 코드 참고)
}
}
위 코드에서 핵심적으로 볼건 아래와 같다. 설명은 주석으로 대신했다.
// isDim 이라고 표현했지만 삭제버튼이 나올정도로 스와이프를 했을때 true , 다시 원래로 돌아갔을때 false
//로 체크하는 변수다.
var isDim by remember { mutableStateOf(false) }
//스와이프한 만큼 레이아웃을 옮겨주기 위해 offset 값을 담는 변수다.
var offsetX by remember { mutableStateOf(0.dp) }
// 스와이프할 내용과 등장시킬 버튼을 모두 담고있는 레이아웃의modifier 에 붙여서
//x 값이 얼마나 변화했는지 체크한다.
.pointerInput(Unit) {
detectTransformGestures { _, pan, _, _ ->
val translationX = pan.x
onLeftSwipe(translationX) { it ->
//80으로 값을 비교하고 있는 이유는 스와이프 되는 최대 위치를 제한하고 싶어서다.
if ((offsetX * -1) > 80.dp) {
offsetX = (offsetX + it).coerceAtLeast((-81).dp)
isDimmed(true)
isDim = true
} else {
//원래 위치로 돌아오는 로직
offsetX = (offsetX + it).coerceAtMost(0.dp)
isDimmed(false)
isDim = false
}
}
}
}
//translationX < 0으로 한 이유는 왼쪽으로 이동하는 경우만 체크했기 때문이고
//0.8을 곱한건 스와이프를 할때 레이아웃이 이동하는 속도를 감속하고 싶어서 적어줬다.
//값은 원하는대로 조절해서 쓰면 된다.
private fun onLeftSwipe(translationX: Float,callback : (Dp)->Unit) {
if (translationX < 0) {
callback((translationX * 0.8).dp)
}else{
callback((translationX * 0.8).dp)
}
}
그리고 실제로 버튼과 스와이프 할 내용물의 코드는 이렇게 작성했다.
//이 컴포넌트는 본인이 작성한 걸로 대체하면 된다.
LinkGroupComponent(
"만나서 반가워요\n링크zip을 소개할게요!",
R.drawable.guide_image,
LinkZipTheme.color.orangeFFE6C1,
1L,
modifier = Modifier.offset(x = offsetX) //offsetX을 이용해서 이동시킨다.
) {}
//버튼이 등장해야함을 알려주는 isDim이 true 가 됐을때
//삭제 버튼이 등장한다.
if (isDim) {
Box(
modifier = Modifier.width(80.dp).height(80.dp).offset(x = -24.dp).align(Alignment.CenterEnd)
.clip(RoundedCornerShape(12.dp))
.background(color = LinkZipTheme.color.redFB5B63)
.padding(
vertical = 10.dp
)
.clickable {
},
) {
Image(
painter = painterResource(id = R.drawable.delete),
contentDescription = "delete",
modifier = Modifier.align(Alignment.Center)
)
}
}
아직 미완성 코드긴 하지만 이런식으로 스와이프시 삭제버튼이 등장하는 기능을 만들었다.
삭제 버튼이 등장하는게 너무 딱딱해보인다면
AnimatedVisibility() 를 이용해보는것도 괜찮을거 같다.
반응형
'Android > Android Compose' 카테고리의 다른 글
컴포즈의 Side-Effect 형제들에 대해서 알아보자 - 2 (0) | 2024.04.28 |
---|---|
컴포즈의 Side-Effect 형제들에 대해서 알아보자 - 1 (0) | 2024.04.21 |
Jetpack Compose CompositionLocal 에 대해 알아봅시다 (0) | 2024.03.31 |
스와이프 삭제 구현 (0) | 2024.03.10 |
안드로이드 컴포즈 dialog 커스텀 하기 (0) | 2023.12.20 |
Jetpack Compose 에서 Lifecycle 관리하기 (0) | 2023.05.11 |
안드로이드 컴포즈 1주차 정리 (0) | 2021.11.07 |
안드로이드 컴포즈 - GDG DevFest2021 참여하다. (0) | 2021.11.02 |