일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 플러터 설치 2022
- 클래스
- 안드로이드 레트로핏 사용법
- ar vr 차이
- 안드로이드 유닛테스트란
- Rxjava Observable
- 안드로이드 유닛 테스트
- rxjava cold observable
- 안드로이드 유닛 테스트 예시
- 안드로이드 os 구조
- rxjava disposable
- 객체
- android retrofit login
- 자바 다형성
- rxjava hot observable
- jvm이란
- 스택 큐 차이
- 큐 자바 코드
- jvm 작동 원리
- android ar 개발
- 2022 플러터 설치
- 스택 자바 코드
- 2022 플러터 안드로이드 스튜디오
- 안드로이드 라이선스
- ANR이란
- 안드로이드 레트로핏 crud
- 서비스 vs 쓰레드
- 안드로이드 라이선스 종류
- 서비스 쓰레드 차이
- 멤버변수
- Today
- Total
나만을 위한 블로그
[Android] 데이터 바인딩, 콜백을 사용해 BottomSheetDialog에서 액티비티로 값 전달하는 방법 본문
사용자가 BottomSheetDialog에서 어떤 값을 선택 or 입력하면 그 값을 액티비티 또는 프래그먼트로 받아와야 할 때가 있다. 값을 받은 다음의 후속 처리는 나중 일이고, BottomSheetDialog에서 어떻게 액티비티 or 프래그먼트로 값을 보낼 수 있을까?
해결법이야 다양하겠지만 내 기준으로 가장 간단한 방법은 콜백이다. 어떻게 만드는지 확인해보자.
먼저 BottomSheetDialog의 XML을 대충 만든다. 이름은 test_bottom_sheet.xml로 만들었다. 커스텀은 각자 알아서
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white">
<TextView
android:id="@+id/tvBottomSheetTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="BottomSheetDialog"
android:textColor="@color/black"
android:textSize="30sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvBottomSheetSubTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:gravity="center"
android:text="제목 밑 글자"
android:textColor="@color/black"
android:textSize="24sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvBottomSheetTitle" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnBottomSheetCancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginStart="40dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvBottomSheetSubTitle"
android:text="취소"/>
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnBottomSheetOk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginEnd="40dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvBottomSheetSubTitle"
android:text="확인"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
그리고 BottomSheetDialog 파일도 만들어준다.
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.view.Gravity
import android.view.LayoutInflater
import android.view.ViewGroup
import android.view.Window
import com.example.kotlinprac.databinding.TestBottomSheetBinding
class TestBottomSheet(context: Context, layoutId: Int): Dialog(context, layoutId) {
private lateinit var binding: TestBottomSheetBinding
private lateinit var dialog: Dialog
private var listener: OnSendFromBottomSheetDialog? = null
fun showDialog() {
binding = TestBottomSheetBinding.inflate(LayoutInflater.from(context))
dialog = setDialogOptions()
binding.run {
btnBottomSheetCancel.setOnClickListener {
if (listener == null) return@setOnClickListener
listener?.sendValue("BottomSheetDialog에서 취소 버튼 클릭함!")
dialog.dismiss()
}
btnBottomSheetOk.setOnClickListener {
if (listener == null) return@setOnClickListener
listener?.sendValue("BottomSheetDialog에서 확인 버튼 클릭함!")
dialog.dismiss()
}
}
}
private fun setDialogOptions(): Dialog = Dialog(context).apply {
requestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(binding.root)
setCanceledOnTouchOutside(true)
window?.run {
setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
setGravity(Gravity.BOTTOM)
}
show()
}
interface OnSendFromBottomSheetDialog {
fun sendValue(value: String)
}
fun setCallback(listener: OnSendFromBottomSheetDialog) {
this.listener = listener
}
}
자잘한 건 다 치우고 인터페이스와 setCallback(), 각 버튼의 클릭 리스너 안을 잘 봐야 한다.
먼저 인터페이스를 만들고 전역변수로 이 인터페이스의 참조변수를 만든 다음, setCallback()으로 어딘가에서 이 인터페이스의 구현을 보내면 BottomSheetDialog 안의 인터페이스를 이것으로 초기화한다.
그리고 버튼을 누르면 내가 정의해둔 임의의 문자열을 추상 함수를 통해 호출된 곳으로 쏜다. 여기서 호출된 곳은 액티비티 or 프래그먼트가 될 것이다.
이제 액티비티도 만들어준다. XML은 데이터바인딩 처리하고 버튼 하나 대충 만들어두면 된다.
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.example.kotlinprac.R
import com.example.kotlinprac.databinding.ActivityCallbackSecondBinding
class CallbackSecondActivity : AppCompatActivity() {
private val TAG = this.javaClass.simpleName
private val binding by lazy {
ActivityCallbackSecondBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.run {
btnCallBottomSheet.setOnClickListener {
val dialog = TestBottomSheet(this@CallbackSecondActivity, R.layout.test_bottom_sheet)
dialog.apply {
showDialog()
setCallback(object : TestBottomSheet.OnSendFromBottomSheetDialog {
override fun sendValue(value: String) {
Log.e(TAG, "BottomSheetDialog -> 액티비티로 전달된 값 : $value")
}
})
}
}
}
}
}
화면의 버튼을 클릭하면 showDialog()의 영향으로 BottomSheetDialog가 생길 것이다. 그 후 이어서 setCallback()으로 TestBottomSheet 안에 있는 인터페이스를 구현한다. 그럼 OnSendFromBottomSheetDialog 인터페이스를 구현한 이 액티비티가 인터페이스 안에 있는 함수의 호출자가 되는 것이므로, BottomSheetDialog 안의 취소 또는 확인 버튼을 누르면 그 값이 이 액티비티로 전달된다. showDialog()와 setCallback()의 호출 순서는 상관없다.
확인을 위해 로그로 BottomSheetDialog에서 날아온 값을 출력하는데 로그캣을 보면 아래와 같이 나온다.
프래그먼트를 사용한다면 매개변수인 context와 this@CallbackSecondActivity 대신 requireActivity()를 넣으면 액티비티에서처럼 똑같이 작동할 것이다.
기능 구현을 우선으로 해서 리팩토링할 부분이 많다. 각자 프로젝트에 맞게 구현한 다음 리팩토링하면 될 것이다.
또한 이 포스팅에선 버튼을 사용했지만 라디오그룹+라디오버튼, 체크박스, 리사이클러뷰 등 어떤 뷰를 사용하더라도 로직 흐름만 파악된다면 곧바로 응용 가능할 것이다.
'Android' 카테고리의 다른 글
[Android] targetSdkVersion 33 이후 onBackPressed() deprecated 이슈와 onBackPressedCallback() 사용법 (0) | 2022.08.01 |
---|---|
[Android] DataStore란? DataStore 예제 (0) | 2022.07.24 |
[Android] 데이터바인딩, 리사이클러뷰, 콜백을 사용해 클릭 이벤트 구현하기 (0) | 2022.07.18 |
[Android] Room 사용 시 To use Coroutine features, you must add `ktx` artifact from Room as a dependency 에러 해결 (0) | 2022.06.29 |
[Android] 레트로핏 함수를 단위 테스트하는 법 (Kotlin) (0) | 2022.06.28 |