안드로이드 커스텀 다이얼로그(Custom Dialog) 만들기, ClickListener로 클릭 이벤트 정의까지

임현주·2022년 4월 1일
7
post-thumbnail


나는 개인적으로 안드로이드 기본 다이얼로그 디자인을 선호하지 않는다..💦 저 상태에서 기본 색상을 변경하더라도 알림창 하나로 APP 전체적인 디자인 컨셉을 흩트릴 수도 있다는 생각에 기본 알림창 다이얼로그를 전부 커스텀하기로 결정했다.

만들어 볼 커스텀 다이얼로그이다. 여러 페이지(activity, fragment)에 쓰일 수 있도록 TextView는 고정 문구가 아니라 파라미터로 전달 받은 문구를 넣어줄 예정이다 ❗

🎈 디자인하기 - xml 작성

먼저 dialog_confirm.xml 파일을 작성한다. Button 스타일은 필자가 따로 정의해놓은거라서 원하는 스타일로 디자인해주면 된다.

dialog_confirm.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/view_round_white_6"
    android:gravity="center"
    android:minWidth="300dp"
    android:orientation="vertical"
    android:padding="20dp">

    <TextView
        android:id="@+id/confirmTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:minHeight="50dp"
        android:textSize="14sp"
        tools:text="확인창입니다." />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:orientation="horizontal">

        <Button
            android:id="@+id/noButton"
            style="@style/MainOutlineButton"
            android:layout_width="0dp"
            android:layout_height="40dp"
            android:layout_marginEnd="7dp"
            android:layout_weight="1"
            android:text="취소"
            android:textSize="14sp" />

        <Button
            android:id="@+id/yesButton"
            style="@style/MainFillButton"
            android:layout_width="0dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:text="확인"
            android:textSize="14sp" />

    </LinearLayout>
    
</LinearLayout>

만약 테두리를 둥글게 하고 싶다면 drawable에 아래 파일을 작성해 dialog_confirm.xml의 최상위 레이아웃 background로 적용시켜주면 된다.

view_round_white_6.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/white" />
    <corners android:radius="6dp" />
</shape>

🎈 Custom Dialog class 작성

필자는 삭제할 id 값을 넘겨주어야 했기 때문에 파라미터로 id 값을 넣어주었지만, 간단히 activity 종료를 한다거나 dismiss() 정도만 원한다면 파라미터를 받을 필요 없다.

단순히 다이얼로그 종료 dismiss()만 원한다면 아래 Dialog 클래스 내의 정의로 끝낼 수 있지만, activity 종료 finish()를 원한다면 인터페이스를 통해 해당 activity에 액션을 정의해주어야한다.

class ConfirmDialog(
    confirmDialogInterface: ConfirmDialogInterface,
    text: String, id: Int
) : DialogFragment() {

    // 뷰 바인딩 정의
    private var _binding: DialogPackageDeleteBinding? = null
    private val binding get() = _binding!!

    private var confirmDialogInterface: ConfirmDialogInterface? = null
    
    private var text: String? = null
    private var id: Int? = null

    init {
        this.text = text
        this.id = id
        this.confirmDialogInterface = confirmDialogInterface
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = DialogPackageDeleteBinding.inflate(inflater, container, false)
        val view = binding.root
        
        // 레이아웃 배경을 투명하게 해줌, 필수 아님
        dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))

        binding.confirmTextView.text = text

        // 취소 버튼 클릭
        binding.noButton.setOnClickListener {
            dismiss()
        }
        
        // 확인 버튼 클릭
        binding.yesButton.setOnClickListener {
            this.confirmDialogInterface?.onYesButtonClick(id!!)
            dismiss()
        }

        return view
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

interface ConfirmDialogInterface {
    fun onYesButtonClick(id: Int)
}

🎈 사용할 activity 또는 fragment에서 호출하기

원하는 activity 또는 fragment에서 커스텀한 다이얼로그 및 인터페이스를 정의해주면 끝!

여기서 하나 짚고 넘어갈 것 🙋🏻‍♀️

dialog.show(manager: FragmentManager, tag: String) 호출 시, manager로 넘겨줄 값 !

  • activity ➡ this.supportFragmentManager
  • fragment ➡ activity?.supportFragmentManager!!
class MainActivity : AppCompatActivity(), ConfirmDialogInterface {

    private lateinit var binding: ActivityMainBinding
    
    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        clickViewEvents()
    }
    
    // 뷰 클릭 이벤트 정의
    private fun clickViewEvents() {
        // 삭제 버튼 클릭
        binding.deleteButton.setOnClickListener {
            val dialog = ConfirmDialog(this, "패키지를 삭제하시겠습니까?", pkgId)
            // 알림창이 띄워져있는 동안 배경 클릭 막기
            dialog.isCancelable = false
            dialog.show(this.supportFragmentManager, "ConfirmDialog")
        }
    }
    
    override fun onYesButtonClick(id: Int) {
        // 액티비티 종료를 원한다면 finish()를 호출해주면 되겠죵 :)
        deletePackageApiCall(id)
    }
}
profile
🐰 피드백은 언제나 환영합니다

0개의 댓글