Android/Compose

[Android Compose] Material3 SnackBar 사용법

참깨빵위에참깨빵_ 2024. 8. 26. 22:48
728x90
반응형

XML 뷰에선 간단하게 쓸 수 있던 스낵바가 Compose에선 좀 번거롭다. 아래는 스낵바를 사용하는 예시 컴포저블이다.

 

@Composable
fun SnackBarExample() {
    val snackBarHostState = remember { SnackbarHostState() }
    val coroutineScope = rememberCoroutineScope()

    Scaffold(
        snackbarHost = { SnackbarHost(hostState = snackBarHostState) }
    ) { innerPadding ->
        Column(
            modifier = Modifier
                .padding(innerPadding)
                .fillMaxSize(),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally,
        ) {
            Button(
                onClick = {
                    coroutineScope.launch {
                        snackBarHostState.showSnackbar(
                            message = "Hello SnackBar",
                            duration = SnackbarDuration.Short,
                            actionLabel = "label"
                        )
                    }
                }
            ) {
                Text("스낵바 표시")
            }
        }
    }
}

 

프리뷰에서 확인하면 아래와 같다.

 

 

인터랙트 모드로 들어와서 버튼을 누르면 하단에 스낵바가 표시된다. 다크모드인 경우 스낵바 배경색과 글자색이 그에 맞춰 변한다.

아래는 디벨로퍼의 스낵바 공식문서다.

 

https://developer.android.com/develop/ui/compose/components/snackbar?hl=ko

 

스낵바(snackbar)  |  Jetpack Compose  |  Android Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 스낵바(snackbar) 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 스낵바 구성요소는 화면 하단에 위치합

developer.android.com

스낵바를 구현하려면 먼저 SnackBarHostState 타입의 SnackBarHost를 만든다. SnackBarHostState는 showSnackbar()를 호출하는 데 사용할 수 있다. 이 정지 함수는 CoroutineScope가 필요하다(rememberCoroutineScope)

 

컴포즈에서 showSnackbar()는 정지 함수로 구현돼 있다. 그래서 코루틴 스코프를 만들어야 하고, SnackBarHostState를 remember로 기억시키는 처리가 필요하다.

 

val snackBarHostState = remember { SnackbarHostState() }
val coroutineScope = rememberCoroutineScope()

 

그리고 Column 안에 Button을 두고 onClick에서 스낵바를 표시한다.

 

Button(
    onClick = {
        coroutineScope.launch {
            snackBarHostState.showSnackbar(
                message = "Hello SnackBar",
                duration = SnackbarDuration.Short,
                actionLabel = "label"
            )
        }
    }
)

 

message는 보다시피 스낵바에 표시할 메시지고 duration은 스낵바의 표시 시간이다. Short, Long, Indefinite 3가지 중 하나를 쓸 수 있다.

actionLabel에는 스낵바 안에서 오른쪽에 표시할 텍스트를 넣을 수 있다. 옵셔널이라 아예 안 쓰거나 null, 공백을 넣으면 표시되지 않는다. 참고로 showSnackbar()의 구현은 아래와 같다.

 

suspend fun showSnackbar(
    message: String,
    actionLabel: String? = null,
    withDismissAction: Boolean = false,
    duration: SnackbarDuration =
        if (actionLabel == null) SnackbarDuration.Short else SnackbarDuration.Indefinite
): SnackbarResult

 

리턴타입이 SnackbarResult인 걸 볼 수 있다. 이 말은 showSnackbar()의 결과를 변수에 담아서 활용할 수도 있단 뜻이다.

 

Button(
    onClick = {
        coroutineScope.launch {
            val result = snackBarHostState.showSnackbar(
                message = "Hello SnackBar",
                duration = SnackbarDuration.Short,
                actionLabel = "label"
            )
            when (result) {
                SnackbarResult.ActionPerformed -> {
                    Log.e("snackbar", "actionPerformed")
                }
                SnackbarResult.Dismissed -> {
                    Log.e("snackbar", "dismissed")
                }
            }
        }
    }
)

 

ActionPerformed, Dismissed 2종류가 있는데 아래 경우에 호출된다.

 

  • ActionPerformed : actionLabel 버튼 클릭 시 호출
  • Dismissed : 스낵바가 자연적으로 사라졌을 때 호출

 

ActionPerformed에는 undo를 넣어서 뭔가를 삭제한 다음 스낵바를 띄우고 undo 클릭 시 되돌리는 처리를 넣을 수 있겠다. Dismissed에도 필요한 처리를 넣으면 될 것이다.

반응형