안드로이드/기능구현

커스텀다이얼로그 + RadioButton with Kotlin

우선 CustomDialog를 디자인 할 XML을 만들어줍니다.

저는 Dialog에 RadioButton이 있고, 이 RadioButton으로 선택한 다음 확인을 누르면 그 값을 전달하게끔 설계했습니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:background="@drawable/round10_white" <!-- 둥근 모서리 xml -->
    android:orientation="vertical">

    <TextView
        android:id="@+id/dialog_title"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_gravity="center_horizontal"
        android:ellipsize="end"
        android:gravity="center"
        android:letterSpacing="@dimen/letter_spacing" <!-- 간격 설정 -->
        android:maxLines="1"
        android:paddingStart="15dp"
        android:paddingEnd="15dp"
        android:text="커스텀 다이얼로그"
        android:textColor="@color/black"
        android:textSize="17dp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@+id/view"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/black"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/dialog_title" />


    <RadioGroup
        android:id="@+id/radio_group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="25dp"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="20dp"
        app:layout_constraintBottom_toTopOf="@+id/dialog_button"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/dialog_title"></RadioGroup>

    <LinearLayout
        android:id="@+id/dialog_button"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/gift_radio_group">

        <TextView
            android:id="@+id/dialog_cancel"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:layout_weight="1"
            android:background="@drawable/button_round10" <!-- 둥근 모서리 버튼 xml -->
            android:gravity="center"
            android:letterSpacing="@dimen/letter_spacing"
            android:text="취소"
            android:textColor="@color/greyish_brown"
            android:textSize="18dp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/dialog_confirm"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:layout_weight="1"
            android:background="@drawable/button_round10_redpink" <!-- 둥근 모서리 버튼 xml -->
            android:gravity="center"
            android:letterSpacing="@dimen/letter_spacing"
            android:text="확인"
            android:textColor="@color/white"
            android:textSize="18dp"
            android:textStyle="bold" />

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

RadioGroup만 생성해주고 RadioButton은 동적으로 생성할 것입니다.

 

저는 Fragment에서 Dialog를 생성해서 Interface를 활용한 Listener로 값을 주고받게끔 할 것입니다.

우선 CustomDialog Class를 작성합니다.

private class CustomDialog(
    context: Context,
    private var curPos: Int,
) : AppCompatDialog(context, R.style.CustomDialog), DialogInterface {
    private lateinit var binding: CustomDialogBinding
    private var confirmListener: ((Int) -> Unit)? = null
    private var cancelListener: (() -> Unit)? = null
    var pos = curPos

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = CustomDialogBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)

        // 로컬에서 선택할 값 배열 생성
        val selectArray: ArrayList<String> = arrayListOf("택1", "택2", "택3", "택4")
        val radioGroup = binding.radioGroup
        for (i in 0..selectArray.size-1) {

            var radio = RadioButton(view.context).apply {
                id = i
                text = selectArray[i]
                setTextColor(Color.BLACK)
                setPadding(pxToDp(5),0,0,0)

                val layoutParam = RadioGroup.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT,
                    pxToDp(30)
                )
                layoutParam.setMargins(0,pxToDp(15),0,0)
                layoutParams = layoutParam
            }

            radioGroup.addView(radio)
        }

        radioGroup.check(pos)

        binding.dialogConfirm.setOnClickListener {
            pos = radioGroup.checkedRadioButtonId
            this.confirmListener?.invoke(pos)
        }
        binding.dialogCancel.setOnClickListener {
            this.cancelListener?.invoke()
        }

    }

    fun setConfirmListener(confirmListener: ((Int) -> Unit)? = null) {
        this.confirmListener = confirmListener
    }

    fun setCancelListener(cancelListener: (() -> Unit)? = null) {
        this.cancelListener = cancelListener
    }

    fun pxToDp(value: Int) : Int {
        return TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            value.toFloat(),
            context.resources.displayMetrics
        ).toInt()
    }
}

setConfirmListener와 setCancelListener를 통해 리스너를 등록할 수 있습니다.

 

배열을 생성하여 Radio Button을 동적으로 생성할 수 있습니다.

마진같은 경우는 LayoutParam을 통해 설정해줍니다.

확인버튼을 눌렀을 때 체크되어 있는 값을 invoke해줍니다.

 

object DialogBuilder {

    fun showCustomDialog(context: Context, curPos: Int, confirmListener: ((Int) -> Unit)? = null, cancelListener: (() -> Unit)? = null) {

            val dialog = CustomDialog(
                context = context,
                curPos = curPos ?: 0,
            )

            dialog.setConfirmListener {
                confirmListener?.invoke(dialog.pos)
                dialog.dismiss()
            }

            dialog.setCancelListener {
                cancelListener?.invoke()
                dialog.dismiss()
            }

            dialog.show()
        }
}

다이얼로그 빌더를 object로 하여 만들어줍니다.

앞으로 다이얼로그를 생성할 때 이 빌더를 통해 만들어줄 수 있습니다.

 

이제 Activity 또는 Fragment에서 다이얼로그를 만들어 표현할 수 있습니다.

private fun showCustomDialog(pos: Int) {
        DialogBuilder.showCustomDialog(requireContext(),
            curPos = pos,
            confirmListener = {
                Log.d("TEST", "selected $it")
            },
            cancelListener = {
                null
            }
        )
    }

showCustomDialog에 현재의 pos를 넣어주면, 다이얼로그 빌더를 통해 CustomDialog를 생성하고 RadioGroup에서 RadioButton이 동적으로 생성되며 현재의 pos가 체크되어 있게끔 생성될 것입니다.

그리고 확인을 눌렀을 때 체크되어 있는 곳의 pos가 confirmListener를 통해 돌아와 Log를 찍어냅니다.

이를 활용하면 무궁무진한 다이얼로그 활동을 할 수 있겠죠? ㅎㅎ