본문 바로가기
Android/Kotlin

Android Custom Dialog 만들기

by wannagohome97 2024. 1. 4.

간단하게 만들 수 있는 AlertDialog 와 아쉬운 점

보통 Android 에서 간단한 Dialog 를 구현하려면 AlertDialog class 를 이용하여 구현 할 수 있다.

val dialog = AlertDialog.Builder(this)
            .setTitle("제목")
            .setIcon(R.mipmap.ic_launcher)
            .setMessage("뭘 해볼까?")
            .setPositiveButton("OK"
            ) { dialog, which ->
                // TODO: do something! 
            }
            .setNegativeButton("Cancel") {
                dialog, which ->
                // TODO: do something! 
            }
            .create()
        dialog.show()

 

이 코드를 실행하면

사실 기본 AlertDialog 의 레이아웃도 나쁘진 않다. AlertDialog.Builder의 setItems 메서드로 유사 리스트뷰도 보여줄 수 있고..

 

이런 화면을 Dialog 로 띄울 수가 있는데.

레이아웃 자체가 어느정도 Fix 되어있기 때문에 뭔가 유저에게 노티하는 간단한 상황이 아닌 이상 잘 사용하지 않았다.

주관적인 의견입니다..!

 

 

 

Dialog Customizing

그래서 나는 자체적으로 Dialog 를 커스터마이징 해서 사용하는 편인데 일단 코드부터 살펴보면

class DialogHelper(context: Context) {

    private val mDialog: Dialog

    init {
        mDialog = Dialog(context)
        mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        mDialog.setCancelable(true)
        mDialog.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
    }

    // 사용할 layout 파일 지정하고
    fun setContentView(resId: Int){
        mDialog.setContentView(resId)

    }
    // Dialog 의 사이즈를 지정할 수 있다.
    fun setSize(width: Int, height: Int){
        val params = mDialog.window?.attributes
        params?.width = width
        params?.height = height
        mDialog.window?.attributes = params
    }
    fun build(): Dialog{
        return mDialog
    }
}

 

아주 간단한 기본 형태만 보자면 이렇다.

Dialog 로 화면에 띄울 레이아웃을 지정하고, 사이즈를 커스터마이징 할 수 있다.(Theme 쪽을 상속받아서 수정할 수도 있지만 그렇게 되면 앱 전체에 영향을 주기 때문에 일단 나는 선호하지 않는다.)

이걸 Activity 나 Fragment 에서 사용하는 예시로

 

...
        val dialogHelper = DialogHelper(this)
        dialogHelper.setContentView(R.layout.dialog_custom)
        dialogHelper.setSize(resources.getDimensionPixelSize(R.dimen.dialog_width),
            resources.getDimensionPixelSize(R.dimen.dialog_height))
        val dialog = dialogHelper.build()
        dialog.show()
...

 

이런 식으로 사용 가능하다.

 

일단 결과물과 레이아웃 리소스를 보여드리자면

나름 EditText 가 추가됐다. 대충 비밀번호 입력하라고 튀어나오는 Dialog 를 생각하면 편하다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    tools:layout_width="250dp"
    tools:layout_height="150dp"
    app:cardBackgroundColor="#C8BEB4"
    app:cardCornerRadius="10dp"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <TextView
        android:id="@+id/custom_dialog_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        android:text = "지금 가장 하고싶은건?"
        android:padding="15dp"
        />
    <EditText
        android:id="@+id/custom_dialog_textbox"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginHorizontal="15dp"
        android:paddingHorizontal="5dp"
        />

    <androidx.appcompat.widget.AppCompatButton
        android:id="@+id/custom_dialog_positive"
        android:layout_width="75dp"
        android:layout_height="40dp"
        android:text="Go"
        android:layout_gravity="bottom|start"
        android:layout_margin="10dp"
        android:color = "#FFFFFF"
        android:background = "@drawable/button_background"
        />
    <androidx.appcompat.widget.AppCompatButton
        android:id="@+id/custom_dialog_negative"
        android:layout_width="75dp"
        android:layout_height="40dp"
        android:text="Nope"
        android:layout_gravity="bottom|end"
        android:layout_margin="10dp"
        android:background = "@drawable/button_background"
        />

</androidx.cardview.widget.CardView>

 

코너 부분을 다듬고 색상도 자연스럽게 입히면서 화면 위에 떠있는 입체감을 살리기 위해 나는 보통 최상위 레이아웃으로 카드뷰를 많이 사용한다.

그리고 Button 대신 AppCompatButton 을 사용한 이유라 하면 Button 은 background 속성이 안 먹는다..(정확히는 Theme 쪽에서 수정해야하는데 AppCompat을 사용하는 상황에서 굳이..?)

 

그리고 추가적으로 저 버튼에 Click Listener를 설정하고싶으면 

class DialogHelper(context: Context) {

	...
    
    fun setOnClickListener(resId: Int, listener: View.OnClickListener){
        val view: View = mDialog.findViewById(resId)
        view.setOnClickListener(listener)
    }

    ...
}
...
dialogHelper.setSize(resources.getDimensionPixelSize(R.dimen.dialog_width),
    resources.getDimensionPixelSize(R.dimen.dialog_height))
dialogHelper.setOnClickListener(R.id.custom_dialog_positive
) { println("좋았어!") }
...
val dialog = dialogHelper.build()

 

2024-01-04 18:13:16.595 8700-8700/com.hi.dialogsample I/System.out: 좋았어!

 

이런식으로 구현될 수 있다.