2021. 10. 29. 22:09ㆍ개발을 파헤치다/Android
알림 창(Dialog)은 안드로이드 앱 개발 시 상당히 많이 쓰이는 요소인데요.
오늘은 내가 원하는 레이아웃을 적용한 Custom Dialog를 어떻게 구현하는지 살펴보도록 하겠습니다.
Builder 패턴 이해
Dialog에는 다양한 속성들이 있습니다.
Custom Dialog를 만들 때에도 기존 Dialog의 다양한 속성과 더불어 개발자가 새로운 속성 값들을 설정하도록 구현할 수 있습니다. 이렇게 다양한 설정을 효율적으로 하기 위해서 Custom Dialog를 구현할 때에 Builder 패턴을 적용하는 것이 좋습니다.
안드로이드에서 흔하게 쓰는 Alert Dialog를 사용할 때에도 Builder 패턴을 사용하게됩니다.
이 디자인 패턴은 속성 값이 많은 객체를 생성할 때 사용되는데요. 많은 속성 값을 가진 객체를 생성할 때 일부 속성만 선택적으로 초기화해서 만들 수 있다는 점과 새로운 속성 추가나 제거 시 코드 변경이 용이하다는 장점이 있습니다.
예를 들어, 아래의 Custom Dialog에는 다양한 속성 값들이 있습니다.
class CommentUpdateDialog(context: Context) : Dialog(context) {
var commentMessage: String? = null
var positiveButtonMsg: String? = null
var negativeButtonMsg: String? = null
var positiveButtonCallback: CommentUpdateDialog.CommentUpdateDialogCallback ?= null
var negativeButtonCallback: CommentUpdateDialog.CommentUpdateDialogCallback ?= null
}
위 Comment Update Dialog 객체를 생성하려면 모든 데이터를 초기화해주던지 아니면
속성 값 별로 초기화할 수 있도록 생성자를 여러 개를 만들어주어야 합니다.
이렇게 되면 노가다 작업이 늘어나겠죠. 효율적이지 못합니다.
Builder 패턴을 활용하면 아래와 같이 필요한 데이터만 초기화가 가능하고 새로운 속성이 추가됐을 때에도 기존 코드 변경 없이 사용이 가능합니다.
CommentUpdateDialog(this).setCommentMessage()
.setPositiveButtonMsg()
.setNegativeButtonMsg()
// 새롭게 속성이 추가되어도 기존 코드는 영향받지 않는다
.setNewMethod()
Custom Dialog 클래스 구현
class CommentUpdateDialog(context: Context) : Dialog(context) {
var commentMessage: String? = null
var positiveButtonMsg: String? = null
var negativeButtonMsg: String? = null
var positiveButtonCallback: CommentUpdateDialog.CommentUpdateDialogCallback ?= null
var negativeButtonCallback: CommentUpdateDialog.CommentUpdateDialogCallback ?= null
var mBinding: DialogCommentUpdateBinding? = null
// Dialog의 show() 메서드가 호출되고 나서야 onCreate 메서드가 실행된다
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setCanceledOnTouchOutside(true)
mBinding = DialogCommentUpdateBinding.inflate(layoutInflater)
setContentView(mBinding!!.root)
// Dialog 레이아웃 크기 및 위치 설정
// setContentView 실행 후에 적용되어야 제대로 반영이된다
window?.setGravity(Gravity.CENTER)
// 기기 가로 너비의 85% 크기로 적용하겠다는 의미
val width = (context.resources.displayMetrics.widthPixels * 0.85).toInt()
window?.setLayout(width, ViewGroup.LayoutParams.WRAP_CONTENT)
initView()
}
// Activity 종료시 Dialog를 종료시킨다
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
this.dismiss()
}
// Builder를 통해 받은 설정값들을 초기화하는 메서드
private fun initView(){
mBinding!!.commentUpdateDialogEditText.setText(commentMessage!!)
mBinding!!.commentUpdateDialogPositiveButton.text = positiveButtonMsg
mBinding!!.commentUpdateDialogPositiveButton.setOnClickListener(View.OnClickListener {
val updatedMsg = mBinding!!.commentUpdateDialogEditText.text.toString()
positiveButtonCallback!!.onClick(this, updatedMsg)
})
mBinding!!.commentUpdateDialogNegativeButton.text = negativeButtonMsg
mBinding!!.commentUpdateDialogNegativeButton.setOnClickListener(View.OnClickListener {
val updatedMsg = mBinding!!.commentUpdateDialogEditText.text.toString()
negativeButtonCallback!!.onClick(this, updatedMsg)
})
}
// Builder 클래스 구현
class Builder(val context: Context){
private var dialog = CommentUpdateDialog(context)
fun setCommentMessage(message: String): Builder{
dialog.commentMessage = message
return this
}
fun setPositiveButton(msg: String, callback: CommentUpdateDialog.CommentUpdateDialogCallback)
:Builder{
dialog.positiveButtonMsg = msg
dialog.positiveButtonCallback = callback
return this
}
fun setNegativeButton(msg: String, callback: CommentUpdateDialogCallback): Builder{
dialog.negativeButtonMsg = msg
dialog.negativeButtonCallback = callback
return this
}
fun show(): CommentUpdateDialog{
dialog.show()
return dialog
}
}
// Button 클릭 이벤트 처리를 위해 호출할 콜백 함수
interface CommentUpdateDialogCallback{
fun onClick(dialog: CommentUpdateDialog, message: String)
}
}
Custom Dialog 사용하기
// 사용하기
CommentUpdateDialog.Builder(context)
.setTitle(AppUtils.getString(R.string.menu_comment_update))
.setCommentMessage(item.comment)
.setPositiveButton(dialogOkMsg, object:CommentUpdateDialog.CommentUpdateDialogCallback{
override fun onClick(dialog: CommentUpdateDialog, message: String) {
// API를 호출한다
presenter.updateParentComment(commentId = item.id,
message = message, position = position)
dialog.dismiss()
}
})
.setNegativeButton(dialogNoMsg, object:CommentUpdateDialog.CommentUpdateDialogCallback{
override fun onClick(dialog: CommentUpdateDialog, message: String) {
// Dialog를 내린다
dialog.dismiss()
}
})
.show()
'개발을 파헤치다 > Android' 카테고리의 다른 글
[Kotiln] 안드로이드 커스텀 액션바(toolbar) 완벽 가이드 (0) | 2021.11.24 |
---|---|
안드로이드 권한 요청 이거 하나로 끝낸다 (0) | 2021.11.04 |
앱 수익을 위한 필수! Firebase Dynamic Link 사용법 총정리 (1) | 2021.10.20 |
[안드로이드] Groupie로 확장 가능한 RecyclerView 만들기 (0) | 2021.06.21 |
Circular Progress bar 구현하기 (0) | 2021.06.15 |