Grusie 안드로이드 개발 기술 블로그

[Android] 안드로이드 컴포즈 Snackbar 사용하기 본문

안드로이드 개발/컴포즈

[Android] 안드로이드 컴포즈 Snackbar 사용하기

grusie 2024. 4. 2. 18:01
728x90
반응형
SMALL

메세지를 띄우는 방법은 여러 가지가 있다. 토스트로 띄우는 방법, 다이얼로그로 띄우는 방법 등 여러가지가 있겠지만, 이번에는 SnackBar를 활용해서 띄워보도록 하자.

 

SnackBar는 하단에 간단한 메세지를 표현하는데에 사용되는 메세지로, 화면에 국한되어 있다고 생각하는 게 편하다.

Toast와 다르게 콜백을 받아 처리할 수 있으며, 간단한 Action을 구현하는 것도 가능하다.

 

기본 사용법

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

스낵바를 사용하기 위해선, 스낵바의 상태를 확인 할 수 있는 SnackbarHostState가 필요하다.

coroutine.launch {
    snackBarHostState.showSnackbar(
        message = TextUtils.getErrorMsg(
            context,
            error = errorCode!!
        )
    )

 

또한 스낵바의 showSnackbar는 suspend 함수이기 때문에, 코루틴에서 실행되어야 한다.

 

콜백 받기

if (errorCode != null) {
    coroutine.launch {
        val result = snackBarHostState.showSnackbar(
            message = TextUtils.getErrorMsg(
                context,
                error = errorCode!!
            )
        )
        when (result) {
            SnackbarResult.Dismissed -> {
            	//닫힐 경우
                errorCode = null
            }

            SnackbarResult.ActionPerformed -> {
            	//액션에 대한 처리
            }
        }
    }
}

SnackBarHostState의 showSnackbar는 정지함수이면서, SnackbarResult를 리턴해주는 함수이다.

그렇기에 사용 할 때의 결과값을 반환 받아, Dismissed일 때 상태를 변경해주는 코드를 작성했다.

/**
 * Possible results of the [SnackbarHostState.showSnackbar] call
 */
enum class SnackbarResult {
    /**
     * [Snackbar] that is shown has been dismissed either by timeout of by user
     */
    Dismissed,

    /**
     * Action on the [Snackbar] has been clicked before the time out passed
     */
    ActionPerformed,
}

SnackbarResult는 이렇게 생겼다.

액션 넣기

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

showSnackbar의 구조를 보면 이런식으로 생겼다.

액션을 넣기 위해서는 actionLabelString값을 넣으면 된다.

if (errorCode != null) {
    coroutine.launch {
        val result = snackBarHostState.showSnackbar(
            message = TextUtils.getErrorMsg(
                context,
                error = errorCode!!
            ),
            actionLabel = "닫기"
        )
        when (result) {
            SnackbarResult.Dismissed -> {
                errorCode = null
            }

            SnackbarResult.ActionPerformed -> {
                errorCode = null
            }
        }
    }
}

닫기라는 액션 라벨을 넣고, 클릭 시 닫히도록 구현하였다.

 

Scaffold와 함께 사용

Scaffold와 함께 사용할 때에는 따로 처리해주어야 하는 것이 있는 것 같다.

이전 버전에서는 scaffoldState를 생성하여, 거기에서 Snackbar를 사용해야 하는 것 같으나, 필자가 사용하는 마테리얼3(1.6.2) 에서는 snackbarHost를 넣는 곳이 따로 있었다.

Scaffold(
    modifier = modifier,
    ...
    snackbarHost = { SnackbarHost(hostState = snackBarHostState) }
    ...
)

snackbarHosthostState를 파라미터로 가지는 SnackBarHost를 생성해 넣어주면 된다.

 

실제 동작 화면

컴포즈 snackbar 처리

 

후기

토스트메세지에 비해서 익숙하지 않아 어렵다고 생각했으나, 오히려 Dialog를 띄우는 것 보다 간단하고, Action으로 기능도 쉽게 넣을 수 있는 것 같아 애용 해야겠다고 생각한다. 특히 SnackBar가 디자인이 예뻐서 다이얼로그를 띄우는 것 보다 나은 것 같다. 추가로 토스트메세지에 비해, 화면에 종속되어 있어, 화면을 벗어났을 때 남아있지 않기에 사용자에게 좋은 경험을 줄 수 있을 것이라고 생각한다.

아쉬운 점이 있다면, 키보드가 띄워져있을 때에는 가려진다는 점이다. 그래서 SnackBar를 띄울 때 키보드를 강제로 닫는식으로 처리해야 할 것 같다.

반응형
LIST