Android/Android Compose

안드로이드 컴포즈 dialog 커스텀 하기

최데브 2023. 12. 20. 00:22

안드로이드 컴포즈에서 제공하는 AlertDialog 를 사용하면

간단하게 뚝딱 dialog 를 만들 수 있지만 정해진 틀에 맞춰서 사용해야하는 문제가 있다.

 

나는 역시나 고집을 부려서 커스텀을 하고 싶었는데 어떻게 만들었는지 간단히 정리하려한다.

 

먼저 Dialog의 기본 형태를 잡아보자. 아래 코드를 살펴보자.

@Composable
fun DialogComponent(
    onDismissRequest: () -> Unit,
    visible: Boolean,
    height : Dp,
    content: @Composable () -> Unit
) {
    if (visible) {
    	//커스텀하려면 AlertDialog 말고 Dialog를 써준다.
        Dialog(
            onDismissRequest = { onDismissRequest() },//dialog 가 닫기는 조건을 받음
            properties = DialogProperties( //dialog 와 관련된 속성을 정의할 수 있다
                dismissOnBackPress = true, //뒤로가기 버튼을 눌렀을때 닫김을 설정
                dismissOnClickOutside = true,//밖 화면을 눌렀을때 닫김을 설정
                securePolicy = SecureFlagPolicy.Inherit
            )
        ) {
        	//기본적으로 Dialog 는 화면 중앙에 표기되는데 나는 화면 아래에 위치하게 만들고 싶었다.
            //Dialog 자체에는 위치를 설정해주는 속성이 없는데 아래와 같은 방식으로 BOTTOM 정렬을
            //할 수 있다.
            val dialogWindowProvider = LocalView.current.parent as DialogWindowProvider
            dialogWindowProvider.window.setGravity(Gravity.BOTTOM)

            Card(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(height)
                    .offset(y = (-30).dp),
                shape = RoundedCornerShape(16.dp),
            ) {
                Column(
                    modifier = Modifier
                        .fillMaxWidth()
                        .fillMaxHeight()
                ) {
                    Image(
                        painter = painterResource(id = R.drawable.bottom_dialog_top),
                        contentDescription = "bottom_dialog_top")
                    Box(modifier = Modifier
                        .padding(horizontal = 20.dp)
                        .padding(vertical = 30.dp)
                        .fillMaxWidth()
                        .fillMaxHeight()){
                        content()// Dialog 내부에 들어갈 내용 컴포저블
                    }
                }
            }
        }
    }
}

 

주석으로 설명을 해두긴 했는데 이 부분을 제외하면 일반적으로 구현하는것과 다르지 않다.

 val dialogWindowProvider = LocalView.current.parent as DialogWindowProvider
dialogWindowProvider.window.setGravity(Gravity.BOTTOM)

 

실제로 불러와서 사용하는 쪽 코드도 살펴보자.

                
                //특정 이벤트가 발생하거나 버튼을 클릭할때 showDialog 를 변경해주면서
                //dialog를 껐다가 켰다가 한다.
                
                var showDialog by remember { mutableStateOf(false) }
                // .. 중략
                DialogComponent(
                    onDismissRequest = { showDialog = false },
                    visible = showDialog,
                    height = 150.dp
                ) {
                	//위 쪽 코드에서 살펴본 content 의 내용이다.
                    //껍데기는 유지한채 content 에 해당하는 내용은 바꿔 끼울 수 있도록 만들었다.
                    LazyColumn(
                        verticalArrangement = Arrangement.spacedBy(29.dp)
                    ) {
                        items(menuItems.size) { it ->
                            BottomDialogMenuComponent(
                                menuImage = R.drawable.guide_image,
                                menuTitle = menuItems[it]
                            ) {
                                mainViewModel.updateMenuState(it)
                                showDialog = false
                            }
                        }
                    }
                }
            }

 

 

 

반응형