[안드로이드스튜디오_문화][Material3_Checkbox]

기말 지하기포·2024년 1월 7일
0

#Material3 Checkbox 공식 문서
=>https://m3.material.io/components/checkbox/guidelines

Google이 말하는 Checkbox

-여러 관련 옵션을 목록에서 선택하고자 할 때는 스위치 대신에 체크박스를 사용해야 한다. 이는 유사한 항목을 시각적으로 효과적이게 그룹화하고 스위치 보다 공간을 덜 차지하기 때문이다.

-구글에서는 체크박스를 사용 할때 텍스트 라벨과 함께 사용하여 선택 옵션을 명확하게 사용자에게 전달하도록 권장하고 있다.

-체크박스는 사용자에게 하나 또는 그 이상의 옵션을 리스트에서 선택 할 수 있게 해준다. 부모 체크박스를 사용해서 자식 체크박스들을 전체 체크 또는 전체 체크 해제 할 수 있게 해준다. 즉, 부모 체크박스의 체크여부를 모든 자식 체크박스들이 받아들여야 한다. 즉, 체크박스들은 다른 체크박스들과 부모-자식 관계를 맺을 수 있다는 의미이다.

-위에 대한 내용을 구글에서는 이렇게 사진으로 표현해주고 있다.

-체크박스 이외에 선택을 가능하게 해주는 UI는 radio buttons , switches가 있다 이 세가지의 공통점은 사용자에게 선택기능을 줄 수 있다는 것이다. 하지만 각기 다른 경우에 상황에 알맞게 사용해야 한다. [1.체크박스는 관련있는 선택지들의 리스트 내부에서 선택지들을 선택하도록 유도하고자 할 때] , [2.라디오버튼은 관련있는 선택지들의 리스트 내부에서 선택지를 단 하나만 선택하도록 유도하고자 할 때] , [3.스위치는 목록에서 설정과 같은 독립형 옵션 또는 더 자세한 옵션을 선택하도록 유도하고자 할 때] 이렇게 3가지의 경우에 사용한다.

코드로 구현하기

1

-체크박스의 구성요소를 담을 데이터 클래스 선언 : 이 데이터 클래스의 객체를 체크 박스 한개라고 생각하면 된다.

data class CheckInfo(
    val isChecked: Boolean,
    val text: String
)

2

@Composable
fun Checkboxes() {
    
    val checkboxes = remember {
        mutableStateListOf(
            CheckInfo(
                isChecked = false,
                text = "1"
            ),
            CheckInfo(
                isChecked = false,
                text = "2"
            ),
            CheckInfo(
                isChecked = false,
                text = "3"
            ),
        )
    }
    
  • remember 함수는 컴포저블이 다시 호출 될 때(리컴포지션) 상태를 기억하게 해준다.
  • 따라서 mutableStateListOf()를 활용해서 변경 가능한 리스트를 생성해서 컴포즈가 리스트의 요소들을 추적할 수 있게 해준다.
  • 또한 위에서 생성한 데이터 클래스의 객체를 만들어서 체크박스 객체를 생성한 듯한 효과를 만들어준다.
    var allState by remember {
        mutableStateOf(ToggleableState.Indeterminate)
    }
  • allState에 ToggleableState.Indeterminate 를 초기값으로 넣어준다.
  • Toggle이란 두 가지 상태 사이를 왔다 갔다 하는 것을 의미한다.
  • ToggleableState는 enum class로 변수의 상태를 상수로 정의하였다. : On(활성화) Off(비활성화) Indeterminate(어중간)
    val toggleTriState = {
        allState = when (allState) {
            ToggleableState.Indeterminate -> ToggleableState.On
            ToggleableState.On -> ToggleableState.Off
            else -> ToggleableState.On
        }
        
  • toggleTriState라는 람다함수를 선언하였다.
        checkboxes.indices.forEach { index ->
          > .copy()를 사용해서 기존의 checkbox의 isChecked 값만 변경된 새로운 객체를 반환한다.
            checkboxes[index] = checkboxes[index].copy(
                isChecked = allState == ToggleableState.On
            )
        }
    }
    
    
  • indices는 컬렉션의 인덱스 범위를 반환하는 함수이다.
  • 따라서 indices.ferEach{}를 사용하면 , 반환된 인덱스 범위의 처음부터 끝까지 순회하면서 {} 블락 내부의 코드를 실행한다.
    Row(
        verticalAlignment = Alignment.CenterVertically,
        modifier = Modifier
            .clickable {
                toggleTriState()
            }
            .padding(end = 16.dp)
    ) {
        TriStateCheckbox(
            state = allState,
            onClick = toggleTriState
        )
        Text("전체 클릭")
    }
    
    
  • Row를 클릭해도 toggleTriState()가 실행되고 , TriStateCheckbox를 클릭해도 toggleTriState()가 실행된다.
    checkboxes.forEachIndexed { index, info ->
        Row(
            verticalAlignment = Alignment.CenterVertically,
            modifier = Modifier
                .padding(start = 32.dp)
                .clickable {
                    checkboxes[index] = info.copy(
                        isChecked = !info.isChecked
                    )
                }
                .padding(end = 16.dp)

        ) {
            Checkbox(
                checked = info.isChecked,
                onCheckedChange = { isChecked ->
                    checkboxes[index] = info.copy(
                        isChecked = isChecked
                    )

                })
            Text(text = info.text)
        }
    }

}
  • index는 checkboxes의 index 번호를 의미한다.
  • info는 checkboxes 객체 하나 하나에 대한 정보를 의미한다.

위 코드는 전체 코드를 파편화해서 설명한 코드이다. 전체코드는 하단에 있다.


class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            VelogSelectionUiComponentTheme {
                Column(
                    modifier = Modifier
                        .fillMaxSize()
                        .padding()
                ) {
                    Checkboxes()
                }
            }
        }
    }
}


data class CheckInfo(
    val isChecked: Boolean,
    val text: String
)

@Composable
fun Checkboxes() {
    val checkboxes = remember {
        mutableStateListOf(
            CheckInfo(
                isChecked = false,
                text = "1"
            ),
            CheckInfo(
                isChecked = false,
                text = "2"
            ),
            CheckInfo(
                isChecked = false,
                text = "3"
            ),
        )
    }

    var allState by remember {
        mutableStateOf(ToggleableState.Indeterminate)
    }

    val toggleTriState = {
        allState = when (allState) {
            ToggleableState.Indeterminate -> ToggleableState.On
            ToggleableState.On -> ToggleableState.Off
            else -> ToggleableState.On
        }
        
        checkboxes.indices.forEach { index ->
            checkboxes[index] = checkboxes[index].copy(
                isChecked = allState == ToggleableState.On
            )
        }
    }

    Row(
        verticalAlignment = Alignment.CenterVertically,
        modifier = Modifier
            .clickable {
                toggleTriState()
            }
            .padding(end = 16.dp)
    ) {
        TriStateCheckbox(
            state = allState,
            onClick = toggleTriState
        )
        Text("전체 클릭")
    }

    checkboxes.forEachIndexed { index, info ->
        Row(
            verticalAlignment = Alignment.CenterVertically,
            modifier = Modifier
                .padding(start = 32.dp)
                .clickable {
                    checkboxes[index] = info.copy(
                        isChecked = !info.isChecked
                    )
                }
                .padding(end = 16.dp)

        ) {
            Checkbox(
                checked = info.isChecked,
                onCheckedChange = { isChecked ->
                    checkboxes[index] = info.copy(
                        isChecked = isChecked
                    )

                })
            Text(text = info.text)
        }
    }

}

-

profile
포기하지 말기

0개의 댓글