Compose checkbox - 전체 선택 기능까지

Checkbox

체크 박스는 라디오 버튼이나 메뉴 박스와 같이 사용자에게 옵션을 선택할 수 있도록 제시하는 UI 이다.

체크 박스만의 특징을 말하면, 제시한 하나의 물음에 사용자가 여러가지 답을 선택할 수 있도록 하는 것이다.

만약 좋아하는 음식을 묻는다면 그에 대한 대답이 여럿일 수 있기 때문에 체크 박스를 사용하면 된다.

그림1. Checkbox

특히 체크 박스는 라디오 버튼과 유사한데 라디오 버튼은 하나의 옵션만 선택이 가능하므로

하나의 답 만을 얻어야 한다면 라디오 버튼을 다수의 답을 얻어도 된다면 체크 박스를 구분하여 사용하면 된다.



Checkbox 구현

해당 예시에서는 기본적인 체크 박스 뿐만 아니라 체크 박스를 사용할 때 흔히 많이 사용되는 전체 체크 기능까지 알아보도록 하겠다.

먼저 사용할 변수들을 살펴보면

val sample = listOf("Meat", "Bread", "Snack", "Drink")
val checkList = remember { mutableStateListOf(false, false, false, false) }
val allChecked = when {
checkList.all { it } -> ToggleableState.On
checkList.none { it } -> ToggleableState.Off
else -> ToggleableState.Indeterminate
}

  • sample : Checkbox 옵션들
  • checkList : Checkbox 각 옵션 체크 여부
  • allChecked : 전체 선택의 상태 값

여기서 allChecked 보면 checkList 값에 따라 즉, 모든 체크 박스들의 체크 여부에 따라서

값이 초기화되어 전체 체크의 대한 상태 값을 갖게 된다.



다음으로 체크 박스 구현한 부분을 살펴보면

sample 리스트를 forEachIndexed문으로 Checkbox와 ClickableText를 포함한 Row들이 만들어지게 된다.

여기서 ClickableText를 사용하는 이유는 텍스트를 클릭하였을 때도 해당 체크 박스가 체크 되도록 하기 위해서 이며

여기서 클릭 이벤트로 현재 index에 checkList 원소 값을 변경해주도록 한다.

// Checkbox Rows
sample.forEachIndexed { index, s ->
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Checkbox(checked = checkList[index], onCheckedChange = {
checkList[index] = it
})
Spacer(modifier = Modifier.width(8.dp))
ClickableText(text = AnnotatedString(s, SpanStyle(fontSize = 18.sp))) {
checkList[index] = !checkList[index]
}
}
}
Spacer(modifier = Modifier.height(16.dp))

// Checked Items
Text("checked : ${checkList.withIndex().filter { it.value }.map { sample[it.index] }}",
fontSize = 18.sp
)

그림2. 실행화면


전체 선택 기능

마지막으로 모든 체크 박스를 선택하고 해제 가능한 체크 박스를 구현해보면

이 부분에서는 Checkbox 컴포넌트를 사용하지 않고 TriStateCheckbox 컴포넌트를 사용한다.

TriStateCheckbox는 Checkbox들의 부모 같은 것으로, 이곳에서는 전체 선택의 여부를 위한 상태 값을 가져야 하기 때문이다.

// All Select
Spacer(modifier = Modifier.height(8.dp))
Row(verticalAlignment = Alignment.CenterVertically) {
Text(text = "All Select", fontSize = 20.sp)
TriStateCheckbox(state = allChecked, onClick = {
val newState = allChecked != ToggleableState.On
checkList.forEachIndexed { index, _ ->
checkList[index] = newState
}
})
}

앞서 선언하였던 allChecked 변수의 값에 따라서 현재 체크 박스들이 체크 된 상태를 구하면

상태 값에 따라서 클릭하였을 때 체크 박스들이 전체 선택/해제 하도록 동작한다.



참고

전체 코드 | Github



댓글

이 블로그의 인기 게시물

Compose 스크롤 시 AppBar 처리 - TopAppBarScrollBehavior

Compose status bar transparent - 상태 바 색 변경

Compose Toast message - 토스트 메시지 사용