다이얼로그?
다이얼로그는 기존의 화면 위에 떠서 유저에게 간단한 알림을 보내고 싶을 때 사용한다. 안드로이드에서는 AlertDialog라는 다이얼로그를 제공해주지만, 이 경우 기본적인 모양에서 다른 기능을 추가하거나 디자인 변경이 어렵다. 따라서 나에게 필요한 기능과 디자인을 xml으로 생성하고, DialogFragment으로 커스텀 다이얼로그를 만드는 방법에 대해 알아보도록 하자.
예제는 코드는 코틀린으로 작성되었으며, 기본적인 동작을 보여 주기 위해 Data Binding이나 Observer, ViewModel 등을 사용하지 않았다.
다이얼로그 코드(xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="20dp">
<TextView
android:id="@+id/text_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:textAlignment="center"
android:textColor="#000000"
android:textSize="24sp"
tools:text="타이틀" />
<TextView
android:id="@+id/text_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="40dp"
android:textAlignment="center"
android:paddingHorizontal="10dp"
android:textColor="#000000"
android:textSize="16sp"
tools:text="설명" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_negative"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#cccccc"
android:textStyle="bold"
tools:text="취소" />
<Button
android:id="@+id/btn_positive"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#189ae0"
android:textColor="@android:color/white"
android:textStyle="bold"
tools:text="확인" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
위의 예제 완성본과 동일한 xml 코드이다. 이때 최상위 layout은 Relative Layout으로 지정해주어야 한다.
tools: 는 미리 보기에서 해당 속성 값을 변경하는 키워드이므로, 동적으로 데이터가 연결될 때나, 특정 케이스의 디자인을 확인할 때 상당히 유용하다.
xml을 inflate 하는 클래스에서 text값과 onClickListener를 직접 연결해줄 것이므로, 모든 요소에 id 값을 부여하자.
다이얼로그 코드(Kotlin)
class CustomDialog : DialogFragment() {
var title: String? = null
var description: String? = null
var positiveBtnText: String? = null
var negativeBtnText: String? = null
var listener: CustomDialogListener? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
super.onCreateView(inflater, container, savedInstanceState)
val view = inflater.inflate(R.layout.dialog_custom, container, false)
return view.rootView
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
view?.apply {
findViewById<TextView>(R.id.text_title)?.text = title
findViewById<TextView>(R.id.text_description)?.text = description
findViewById<Button>(R.id.btn_negative)?.text = negativeBtnText
findViewById<Button>(R.id.btn_negative)?.setOnClickListener {
dismiss()
listener?.onClickPositiveBtn()
}
findViewById<Button>(R.id.btn_positive)?.text = positiveBtnText
findViewById<Button>(R.id.btn_positive)?.setOnClickListener {
dismiss()
listener?.onClickNegativeBtn()
}
}
}
class CustomDialogBuilder {
private val dialog = CustomDialog()
fun setTitle(title: String): CustomDialogBuilder {
dialog.title = title
return this
}
fun setDescription(description: String): CustomDialogBuilder {
dialog.description = description
return this
}
fun setPositiveBtnText(text: String): CustomDialogBuilder {
dialog.positiveBtnText = text
return this
}
fun setNegativeBtnText(text: String): CustomDialogBuilder {
dialog.negativeBtnText = text
return this
}
fun setBtnClickListener(listener: CustomDialogListener): CustomDialogBuilder {
dialog.listener = listener
return this
}
fun create(): CustomDialog {
return dialog
}
}
}
다음과 같은 5개의 요소가 들어간다.
- Title
- Description
- Negative button
- Positive button
- Button click listener
다이얼로그를 만드는 생성자에서 모든 파라미터를 받아올 수도 있지만, 예제는 빌더 패턴을 사용했다.
빌더 패턴은 객체를 만드는 요소를 하나씩 받아 최종적으로 목표 객체의 인스턴스를 빌더가 반환하는 패턴이다. 예제에는 반영되지 않았지만, 불필요한 파라미터를 받지 않을 수 있으며, 파라미터의 추가 변경이 용이하고, 외부에서 목표 객체에 대한 접근이 제한적인 것 등이 장점이다.
Main Activity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click" />
</LinearLayout>
메인 화면 xml에서는 단순하게 테스트를 위한 버튼 하나만 넣었다. 마찬가지로 Main Activity에서 해당 버튼의 onClickListner를 연결해 줄 것이므로 id를 부여하자.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.button).setOnClickListener {
val dialog = CustomDialog.CustomDialogBuilder()
.setTitle("환영합니다")
.setDescription("안녕하세요. 회원님의 접속을 환영합니다.")
.setPositiveBtnText("확인")
.setNegativeBtnText("취소")
.setBtnClickListener(object : CustomDialogListener {
override fun onClickPositiveBtn() {
// 확인 버튼 클릭 시
}
override fun onClickNegativeBtn() {
// 취소 버튼 클릭 시
}
})
.create()
dialog.show(supportFragmentManager, dialog.tag)
}
}
}
그리고 MainActivity에서는 CustomDialogBuilder를 사용하여 자신이 원하는 문구와 리스너 로직을 직접 넣어서 다이얼로그를 생성할 수 있다. set 함수로 파라미터를 전달하고 create를 호출하면 내가 넣은 파라미터를 기반으로 CustomDialog 인스턴스가 생성된다.
앱 실행
'개발' 카테고리의 다른 글
안드로이드 TextView 글자수 초과 시 말 줄임표 처리 (0) | 2020.06.16 |
---|---|
안드로이드 Bottom Sheet Dialog 만들기 (1) | 2020.06.15 |
코틀린 코드 작성 규칙 (Coding Convention) (2) | 2020.01.20 |
안드로이드 스튜디오 Heap 사이즈 늘리기 (0) | 2020.01.16 |
안드로이드 스튜디오에서 Lombok을 사용해보자 (0) | 2019.07.02 |
댓글