[Android] Compose Swipeable

th.k·2022년 5월 11일
0

Android

목록 보기
6/8

LazyColumn의 아이템을 옆으로 스와이프하면 지워지는 기능을 구현하고 싶었다.
관련 정보를 찾아보다가 Modifier에 swipeable이라는 것이 있길래 이것을 설정하여 스와이프를 구현하기로 했다.

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun TodoRow(
    todo: Todo,
    onCheckCompleted: (Todo) -> Unit
) {
	// swipe 상태 저장할 State 변수 
    val swipeableState = androidx.compose.material.rememberSwipeableState(initialValue = 0)
    // 앵커로 사용할 위치
    val point = LocalDensity.current.run { LocalConfiguration.current.screenWidthDp.dp.toPx() }
    // 위치 to 상태
    val anchors = mapOf(0f to 0, -point to 1)

    if (swipeableState.isAnimationRunning) {
        DisposableEffect(Unit) {
            onDispose {
            	// -point로 설정한 앵커에 도달하면 currentValue가 1이 됨
                if (swipeableState.currentValue == 1) {
                    // 애니메이션이 끝나고 실행될 코드 
                }
            }
        }
    }

	// Box 안의 Content가 Swipe 됨 
    Box(
        Modifier
            .fillMaxWidth()
            .swipeable(
                state = swipeableState,
                orientation = Orientation.Horizontal,
                anchors = anchors,
                thresholds = { _, _ -> FractionalThreshold(0.8f) },
                velocityThreshold = 1000.dp
            )
    ) {
    	// Content 
        Card(
            modifier = Modifier
                .offset { 
                	// swipe했을 때 위치가 움직이도록 offset 설정 
                	IntOffset(swipeableState.offset.value.roundToInt(), 0) 
              	}
                .fillMaxWidth()
                .padding(vertical = 4.dp),
            shape = RoundedCornerShape(16.dp)
        ) {
			// Card 위에 표시될 Composable들...
        }
    }
}

코드 정리가 필요할 것 같지만 일단 되는대로 구현했다.

스와이프 되었으면 하는 컴포저블을 Box로 감싸고, 해당 Box에 Modifier.swipeable을 적용했다.
swipeable의 인자는 차례대로 다음과 같다(이 외에도 더 존재함).

  • state - rememberSwipeableState로 얻은 SwipeableState를 넘긴다.
  • orientation - 스와이프 할 방향 지정.
  • anchors - 앵커로 지정할 화면 위치(px값)와 해당 위치에 도달했을 때의 상태를 묶은 Map을 넘긴다.
  • thresholds - 특정한 위치까지 스와이프 하지 않으면 원래 상태로 돌아오는 위치를 지정할 수 있다.
  • velocityThreshold - 지정한 위치까지 스와이프 하지 않아도 특정 빠르기만큼 스와이프하면 스와이프되도록 하는 속도값(dp)을 지정할 수 있다.

그리고 swipeable에 사용할 변수들을 상단에 정의했다.
swipeableStateinitialValueanchors에 저장하고 있는 상태에 해당하는 값은 꼭 Int값으로 하지 않고 원하는 타입으로 지정할 수 있다.
본인은 스와이프 했을 때 화면 밖까지 이동해서 사라졌으면 해서 현재 화면의 크기를 음수로 바꾼 값을 앵커로 사용하고, 해당 위치에서 swipeableStatecurrentValue가 1이 되도록 저장했다.

변수들 밑의 if문은 애니메이션이 끝났을 때 동작되는 코드이다.. (참고한 글)

마지막으로 스와이프 되었으면 하는 컴포저블의 offsetswipeableStateoffset으로 설정해주면 된다.


여담: 얼레벌레 얼추 구현해놓고 SwipeToDismiss라는 컴포저블이 있다는걸 발견했다... 구현한게 아까워서 글로 남김...


참조한 글

profile
고생끝에롹이온다

0개의 댓글