JetPack Compose - FlowLayout + Chip

안드로이드 앱을 사용하다보면, 

다음과 같은 UI를 만날 때가 있다.

해당 UI를 FlowLayout Chip을 이용하여 구현해보겠다.

 

관련 학습은 아래의 구글 공식문서를 참고하여 만들었다.

https://developer.android.com/jetpack/compose/layouts/flow

 

Flow layouts in Compose  |  Jetpack Compose  |  Android Developers

Flow layouts in Compose Stay organized with collections Save and categorize content based on your preferences. Beta: FlowRow and FlowColumn are experimental. This document is for the beta version of the API. File any feedback on the issue tracker. FlowRow

developer.android.com

 

FlowLayout

FlowLayout은 간단하게 설명하면, 화면에 순서대로 표시되는 것이다. 

주요 특징은 다음과 같다.

  1. 순차적 배치 : 정해진 방향으로 순차적으로 배치가 된다.
  2. 자동 줄바꿈 : 페이지의 화면의 너비를 벗어나는 경우에 자동으로 줄바꿈을 한다.

FlowLayout의 요소는 다음과 같다.

가장 먼저 Arrangement이다. 각 속성 값 별 결과는 다음과 같다.

Arrangement의 속성

다음은 Alignment로 어떠한 기준으로 정렬을 할 것인지 정하는 것이다.

다음은 maxItemsInEachRow로 한줄에 최대 몇개의 아이템이 들어갈 것인지 결정하는 것이다.

 

Chip

Chip은 필터링이나 태그를 표시하기 위해 주로 사용된다. 위의 사진에 각각의 과목 선택하는 버튼이다.

 

코드

ChipFlowLayout을 이용하여 제작한 코드는 다음과 같다

 

가장 먼저 과목들을 담을 데이터 클래스를 생성해준다. 과목명과 아이콘 색상이 담겨진다.

그리고 과목들을 담아둔 배열을 생성한다. 

data class subject(
    val text : String,
    val pointColor : Color
)

val subjects = mutableListOf<subject>(
    subject(text = "English", pointColor = Color.Red.copy(alpha = 0.4f)),
    subject(text = "Math", pointColor = Color.Blue.copy(alpha = 0.4f)),
    subject(text = "Science", pointColor = Color.Green.copy(alpha = 0.5f)),
    subject(text = "Dancing", pointColor = Color.Yellow.copy(alpha = 0.5f)),
    subject(text = "Culture", pointColor = Color.Cyan.copy(alpha = 0.5f)),
    subject(text = "Yoga", pointColor = Color.Red.copy(alpha = 0.8f)),
    subject(text = "Adventure", pointColor = Color.Blue.copy(alpha = 0.8f)),
    subject(text = "Soccer", pointColor = Color.Black.copy(alpha = 0.5f)),
)

 

그 다음에는 Chip을 구현해준다.

ElevatedFilterChip을 사용해서 작성하였다. leadingIcon을 통해 해당 칩이 선택되면 아이콘이 사라지도록 했다.

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FilterChip(subject: subject) {
    var selected by remember { mutableStateOf(false) }

    ElevatedFilterChip(
        onClick = { selected = !selected },
        label = {
            Text(subject.text)
        },
        selected = selected,
        leadingIcon = if (!selected) {
            {
                Icon(
                    imageVector = Icons.Filled.Add,
                    contentDescription = "icon",
                    tint = subject.pointColor,
                    modifier = Modifier.size(FilterChipDefaults.IconSize)
                )
            }
        } else {
            null
        },
    )
}

만들어진 Chip을 FlowLayout에 적용하면, 다음과 같다.

@OptIn(ExperimentalLayoutApi::class)
@Composable
fun FlowLayout(){
    FlowRow(horizontalArrangement = Arrangement.SpaceAround,modifier = Modifier.padding(8.dp)) {
        subjects.forEach { subject ->
            FilterChip(subject)
        }
    }
}

 

결과

아이템들을 선택했을 때 결과