Android/Compose

[Android Compose] LazyColumn에서 CheckBox의 체크 상태 유지하는 법

참깨빵위에참깨빵_ 2023. 7. 8. 23:25
728x90
반응형

리사이클러뷰에서 아이템에 체크박스를 넣어 사용했듯 Compose에서도 같은 경우가 당연히 발생할 수 있다.

그러나 Compose에는 리사이클러뷰 대신 LazyColumn이 존재하고, 어댑터가 따로 존재하지 않는다. 이 상황에서 어떻게 체크박스를 만들고 체크 상태를 유지하게 할 수 있을까?

코드로는 아래와 같이 작성하면 스크롤하더라도 체크 상태가 유지되는 체크박스를 만들 수 있다.

 

@Composable
fun TodoCard(
    modifier: Modifier = Modifier,
    title: String,
    content: String
) {
    var checked by rememberSaveable { mutableStateOf(false) }
    Card(modifier = modifier) {
        Column(
            modifier = Modifier.padding(start = 8.dp, top = 5.dp, bottom = 5.dp, end = 8.dp)
        ) {
            Checkbox(
                checked = checked,
                onCheckedChange = {
                    checked = it
                    if (checked) {
                        Log.e("TodoCard", "체크박스 상태 : true")
                    } else {
                        Log.e("TodoCard", "체크박스 상태 : false")
                    }
                }
            )
            Text(
                text = title,
                fontSize = 28.sp
            )
            Spacer(modifier = Modifier.height(2.dp))
            Text(
                text = content,
                fontSize = 20.sp
            )
        }
    }
}

 

그리고 이걸 사용하는 컴포저블 함수를 아래와 같이 예시로 작성한다.

 

@Composable
    fun MyScreenContent() {
        val scaffoldState = rememberScaffoldState()
        Scaffold(
            scaffoldState = scaffoldState,
            topBar = {},
            floatingActionButton = {
                FloatingActionButton(
                    onClick = {
                        lifecycleScope.launch {
                            //
                        }
                    }
                ) {
                    Icon(imageVector = Icons.Filled.Add, contentDescription = "")
                }
            }) { paddingValues ->
            LazyColumn(contentPadding = paddingValues) {
                items(100) {
                    TodoCard(
                        modifier = Modifier.fillMaxWidth().padding(start = 8.dp, top = 10.dp, bottom = 10.dp, end = 8.dp),
                        title = "제목 $it",
                        content = "내용 $it"
                    )
                }
            }
        }
    }

 

이제 onCreate()에 위 컴포저블 함수를 추가하고 앱을 실행하면 아래 카드들이 리스트로 표시될 것이다.

 

 

체크한 다음 스크롤해서 해당 체크박스가 안 보이게 했다가, 다시 스크롤을 올리면 체크된 상태로 남아있는 걸 볼 수 있다.

이제 어떻게 이게 가능한지 확인해 본다. 핵심은 TodoCard 컴포저블 함수에 있다.

 

@Composable
fun TodoCard(
    modifier: Modifier = Modifier,
    title: String,
    content: String
) {
    var checked by rememberSaveable { mutableStateOf(false) }
    Card(modifier = modifier) {
        Column(
            modifier = Modifier.padding(start = 8.dp, top = 5.dp, bottom = 5.dp, end = 8.dp)
        ) {
            Checkbox(
                checked = checked,
                onCheckedChange = {
                    checked = it
                    if (checked) {
                        Log.e("TodoCard", "체크박스 상태 : true")
                    } else {
                        Log.e("TodoCard", "체크박스 상태 : false")
                    }
                }
            )
            Text(
                text = title,
                fontSize = 28.sp
            )
            Spacer(modifier = Modifier.height(2.dp))
            Text(
                text = content,
                fontSize = 20.sp
            )
        }
    }
}

 

TodoCard() 함수의 첫 코드에 주목해야 한다.

 

var checked by rememberSaveable { mutableStateOf(false) }

 

rememberSaveable 키워드에 대해선 이전에 작성한 적이 있다.

 

https://onlyfor-me-blog.tistory.com/731

 

[Android Compose] Compose에서 상태 저장하기(remember)

Compose를 사용하기 전의 XML로 뷰를 짤 경우 상태는 다양한 방법으로 정의한다. boolean 변수에 값을 저장한다거나 객체를 활용한다거나, 또는 다른 소스들을 찾아보면 아주 낮은 확률로 보이는 Atomi

onlyfor-me-blog.tistory.com

 

그러나 체크박스와 연관지어서 포스팅한 적은 없기 때문에 이번 기회에 작성한다. 공식문서에서 설명하는 rememberSaveable은 아래와 같다.

 

https://developer.android.com/jetpack/compose/state?hl=ko

 

상태 및 Jetpack Compose  |  Android Developers

상태 및 Jetpack Compose 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 앱의 상태는 시간이 지남에 따라 변할 수 있는 값을 의미합니다. 이는 매우 광범위한 정

developer.android.com

remember가 재구성 과정 전체에서 상태를 유지하는 데 도움은 되지만 구성 변경 전반에선 상태가 유지되지 않는다. 이 경우 rememberSaveable을 써야 한다. rememberSaveable은 Bundle에 저장할 수 있는 모든 값을 자동 저장한다

 

https://developer.android.com/codelabs/jetpack-compose-state?hl=ko#9 

 

Jetpack Compose의 상태  |  Android Developers

이 Codelab에서는 상태를 관리하여 다양한 기능의 대화형 Compose 애플리케이션을 빌드하는 방법을 알아봅니다.

developer.android.com

...(중략) 항목이 컴포지션을 종료하면 기억된 상태가 삭제된다는 문제가 있다. LazyColumn에 있는 항목의 경우 스크롤하면서 항목을 지나치면 항목이 컴포지션을 완전 종료하므로 더 이상 항목이 표시되지 않는다. rememberSaveable을 사용하라. 저장된 인스턴스 상태 매커니즘을 써서 액티비티 또는 프로세스 재생성 후에도 상태가 유지된다. rememberSaveable이 LazyList와 함께 작동하는 방식 덕분에 항목은 컴포지션을 종료해도 유지될 수 있다

 

LazyColumn을 스크롤하는 것이 구성 변경에 포함되지는 않는다. 하지만 0번 아이템에 체크 후 스크롤해서 0번 아이템이 사라지게 되면 해당 컴포저블의 컴포지션이 종료되면서 이것이 기억하고 있던 상태가 사라지게 된다.

그래서 이 경우에는 위처럼 rememberSaveable을 사용하면 체크박스에 체크 후 스크롤을 하더라도 저장된 상태는 사라지지 않고 유지된다.

반응형