[안드로이드 Compose 5] UI 2 - Dialog, Snackbar

이영준·2023년 8월 25일
0

안드로이드_Compose

목록 보기
5/6

📌 Dialog

Dialog는 AlertDialog를 통해 Material 디자인의 다이얼로그를 띄울 수 있다.
아래의 코드를 보자

@Composable
fun DialogEx() {
    var openDialog by remember {
        mutableStateOf(false)
    }
    var counter by remember {
        mutableStateOf(0)
    }

    Column {
        Button(onClick = { openDialog = true }) {
            Text("다이얼로그 열기")
        }
        Text("카운터 $counter")
    }

    if (openDialog) {
        AlertDialog(
            onDismissRequest = { openDialog = false },
            confirmButton = {
                Button(
                    onClick = { counter++ }
                ) {
                Text("더하기")
                }
            },
            dismissButton = {
                Button(onClick = {openDialog = false}){
                    Text(text = "끄기")
                }
            },
            title = {Text("title!")},
            text = {Text("text!!!")}
        )
    }
}

보면 Dialog를 dismiss하거나 끄는 코드가 따로 존재하지 않는다.
다만 state를 변경시켜, 리 렌더링 과정에서 이 state가 false면 dialog를 띄우지 않게 되므로, 사실상 dismiss와 같은 역할을 한다.

onDissmissRequest는 모달 창 밖 영역 화면을 누를 때 발생할 동작을 넣는 곳이다.
Material이 아닌 순수한 형태의 Dialog를 원하면 AlertDialog 대신 그냥 Dialog를 띄우면 된다.

참고로 Dialog를 쓴다면 내부의 요소들을 넣을 때 꼭 Surface 안에 넣어줘야 dialog 배경이 딤 처리 되지 않는다.

📌 Snackbar

Snackbar composable이 존재한다. 하지만 이를 띄우고, 애니메이션 효과를 주고, 하는 등의 작업이 우리 몫이 되기 때문에, 게다가 snackbar는 suspend 하게 동작하기 때문에 이렇게 하지 않고

ScaffoldState.snackbarHostState를 사용하여 구현한다.

fun SnackbarEx(){
    val snackbarHostState = remember { SnackbarHostState() }
    val scope = rememberCoroutineScope()
    Scaffold(
        snackbarHost = {SnackbarHost(hostState = snackbarHostState)},
        content = {
            Modifier.padding(paddingValues = it)
            scope.launch {
            snackbarHostState.showSnackbar(
                message = "ddd",
                actionLabel = "닫기",
                duration = SnackbarDuration.Short
            )
        }}
    ) 
}

rememberCoroutineScope는 컴포지션 인식 범위를 확보하여 컴포저블 외부에서 코루틴 실행을 위한 코루틴 스코프이다. 즉, recomposition이 일어날 때 coroutine을 삭제해준다.

SnackbarHostState 현재 snackbar의 state를 관리하기 위해 만들어주는 것이 snackbarHostState이다. 이를 통해 snackbar가 시간이 지났을 때 dismiss가 될 수 있다.

사실 위의 코드와 같이 composition에서 직접적으로 coroutine을 호출하면 안된다. LauncedEffect를 통해 값이 바뀔 때에만 호출하도록 제어를 해줘야 한다.

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SnackbarEx() {
    val snackbarHostState = remember { SnackbarHostState() }
    val scope = rememberCoroutineScope()
    Scaffold(
        snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
        content = {
            Modifier.padding(paddingValues = it)
            LaunchedEffect(snackbarHostState) {
                scope.launch {
                    snackbarHostState.showSnackbar(
                        message = "ddd",
                        actionLabel = "닫기",
                        duration = SnackbarDuration.Short
                    )
                }
            }
        }
    )
}
profile
컴퓨터와 교육 그사이 어딘가

0개의 댓글