Development/Android

[Android / Compose] Expandable 메뉴 레이아웃 구현

SeungYong.Lee 2024. 12. 18. 21:55
반응형
Expandable menu

위처럼 클릭할 때마다 열렸다 닫혔다를 반복하는 메뉴 레이아웃 구성 방법입니다.

Compose의 AnimatedVisibility를 활용하여 간단하게 Expand 효과를 적용할 수 있습니다.

기본 작동 방식

  • visible: Boolean 값을 통해 콘텐츠의 표시 여부를 결정합니다.
  • 애니메이션 효과: 요소가 보이거나 사라질 때 애니메이션 효과를 자동으로 적용합니다.
@Composable
fun ColumnScope.AnimatedVisibility(
    visible: Boolean,
    modifier: Modifier = Modifier,
    enter: EnterTransition = fadeIn() + expandVertically(),
    exit: ExitTransition = fadeOut() + shrinkVertically(),
    label: String = "AnimatedVisibility",
    content: @Composable AnimatedVisibilityScope.() -> Unit
) {
    val transition = updateTransition(visible, label)
    AnimatedVisibilityImpl(transition, { it }, modifier, enter, exit, content = content)
}

주요 옵션 및 속성

  1. visible:
    • Boolean 값으로 콘텐츠의 표시 여부를 설정.
    • true: 요소가 애니메이션과 함께 나타남.
    • false: 요소가 애니메이션과 함께 사라짐.
  2. enter:
    • 요소가 나타날 때 적용할 애니메이션을 설정.
    • 기본값은 fadeIn()
  3. exit:
  • 요소가 사라질 때 적용할 애니메이션을 설정.
  • 기본값은 fadeOut()

content 안에는 열렸을 때 보여줄 내용들을 구성해 주면 됩니다.

@Composable
fun SettingsItem(title: String, onClick: () -> Unit) {
    var expand by remember { mutableStateOf(false) }

    Column(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = { expand = !expand })
            .padding(horizontal = 16.dp, vertical = 12.dp)
    ) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .height(48.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.SpaceBetween
        ) {
            Text(
                text = title,
                color = Color.Black,
                fontSize = 18.sp
            )

            Icon(
                imageVector = Icons.Default.ArrowForward,
                contentDescription = "Go to $title",
                tint = Color.Gray
            )
        }
        AnimatedVisibility(visible = expand) {
            Column(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(vertical = 8.dp)
            ) {
                Button(
                    onClick = { onClick() },
                    colors = ButtonDefaults.buttonColors(containerColor = Color.Red),
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(48.dp)
                ) {
                    Text(
                        text = "Delete",
                        color = Color.White,
                        fontSize = 16.sp
                    )
                }
            }
        }
        Spacer(modifier = Modifier.height(8.dp))
        Divider(color = Color.LightGray, thickness = 1.dp)
    }
}

expand state 변수를 통해 메뉴가 열릴 지 닫힐지가 갱신됩니다.

반응형