본문 바로가기
⛏️ | 개발 기록/⏰ | Schedule Planner

[Android, Kotlin] SwipeToDismiss을 이용한 밀어서 삭제하는 기능 구현하기 (15)

by immgga 2024. 4. 16.

 

이번 포스팅에서는 LazyColumn 안에 SwipeToDismiss을 이용해 옆으로 밀어서 일정을 삭제할 수 있도록 하는 기능을 구현해 보겠다.

SwipeToDismiss는 생각보다 많이 어렵지는 않았기에 이 글을 보고 나서 쉽게 사용할 수 있을 것이라고 생각한다.

그러면 바로 어떻게 사용하는지 알아보자.

 

참고로 따로 dependency를 설치할 필요는 없다. compose 기본 dependency에서 모두 지원되는 기능들이다.

 

1. dismissState 생성

SwipeToDismiss를 이용하기 위해서는 dismissState 데이터가 필요하다.

dismissState는 사용자가 item을 옆으로 밀었을 때를 감지하는 역할을 한다.

val dismissState = rememberDismissState(
    confirmValueChange = { value ->
        if (value == DismissValue.DismissedToStart) {
            planViewModel.deletePlan(
                uid = uid!!,
                documentId = it.createdTime.toString()
            )
            true
        } else false
    }
)

나는 dismissState 코드를 다음과 같이 작성해 주었다.

rememberDismissState안에는 confirmValueChange가 필수적으로 들어가는데, 이 부분의 value값이 사용자의 행동에 따라서 변하게 된다.

일단 나는 변경된 value가 DismissedToStart일 때(item이 start 쪽으로 밀렸을 때), 일정 삭제 로직을 넣고 true를 반환해 주었다. 자신이 원하는 대로 DismissedToStart(DismissedToEnd)를 변경해서 조건을 설정하고 조건이 만족했을 때, 특정 기능을 수행하도록 만들 수 있다.

아닌 경우에는 false를 return 해주면 끝이다.

 

2. LazyColumn item에 SwipeToDismiss 연결

이제 본격적으로 SwipeToDismiss을 알아보자.

SwipeToDismiss는 이렇게 구성되어 있다.

SwipeToDismiss 구조

여기에서 파라미터들이 어떤 역할을 하나면,

  • state: 위에서 생성한 dismissState를 연결해 준다.
  • background: 사용자가 item을 옆으로 swipe 했을 때, 나타나는 화면
  • dismissContent: 기존 item 레이아웃 코드를 이 부분에 넣어준다.
  • directions: 어떤 방향으로 swipe가 가능하게 할지 설정할 수 있다(기본값은 EndToStart, StartToEnd 둘 다 가능)

이 파라미터들을 적절히 사용해서 자신만의 swipe item을 만들어보자.

나는 다음과 같이 구현했다.

SwipeToDismiss(
    state = dismissState,
    background = {
        PlanCardBackground(swipeDismissState = dismissState)
    },
    dismissContent = {
        ScheduleItem(
            planData = it,
            onCheckBoxClick = { isCheck ->
                planViewModel.changePlanCompleteAtIndex(position, isCheck)
                planViewModel.planCheck(
                    uid = uid!!,
                    documentId = it.createdTime.toString()
                )
            }
        )
    },
    directions = setOf(DismissDirection.EndToStart)     // 닫을 수 있는 방향을 왼쪽 -> 오른쪽만 가능하게 설정
)

state에는 1번 과정에서 생성한 dismissState를 넣어주었다.

background에서는 내가 직접 만든 CardBackground를 만들어서 넣어주었다(코드는 아래에 추가해 놓겠다).

dismissContent에서는 기존에 쓰던 item 코드를 복붙 해주었고,

directions에 왼쪽에서 오른쪽으로만 swipe가 되도록 설정해 주었다(자신이 원하는 방향으로 setOf을 통해 설정해 주자.)

 

PlanCardBackground 코드

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PlanCardBackground(swipeDismissState: DismissState) {
    val color = if (swipeDismissState.dismissDirection == DismissDirection.EndToStart) Color.Red
    else Color.Transparent

    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(color)
            .padding(16.dp),
        contentAlignment = Alignment.CenterEnd
    ) {
        Icon(
            imageVector = Icons.Default.Delete,
            contentDescription = "delete plan icon",
            tint = Color.White
        )
    }
}

 

3. 구현 결과 및 정리

 

swipe 방향도 이전에 설정한 EndToStart로만 되고, 삭제도 정상적으로 되는 것을 알 수 있다.

 

이렇게 일정 삭제 기능을 구현해 보았는데 나중에도 알고 있으면 요긴하게 써먹을 좋은 Composable을 하나 알아간 것 같아서 좋았다 일단 쓰기 편해서 더 좋았던 것 같다 ㅎㅎ

그리고 이제 슬슬 배포 작업도 시작하려고 한다.

728x90