Dialog
상속 관계 : Dialog >> AlertDialog >> DatePickerDialog
대화상자는 사용자의 주의를 끌고 입력을 받는데 사용되며 사용자의 선택을 받거나 중요한 정보를 보여줄 때도 유용하다.
DialogFragment to Fragment with Data
프래그먼트에서 다이얼로그
DatePickerDialog 는 사용자에게 날짜를 선택하게 유도하는 대화상자이다. 프래그먼트에서는 Fragment의 서브 클래스인 DialogFragment 인스턴스에 포함시키는 것이 좋다.FragmentManger로 DatePickerDialog를 관리하는 것이 유연성이 좋다. 또한, 화면회전시 화면을 유지해주기 때문에 DialogFragment를 사용하는게 좋다.
FragmentManger VS FragmentTransaction DialogFragment를 상속하는 클래스를 만들었다면, 이제 이 프래그먼트에서 어떤 방법으로 달력 대화상자를 띄울지 생각한다.DialogFragment에는 onCreateDialog () 함수가 있다. 이 함수 안에 달력을 상징하는 객체를 만들어준다.
override fun onCreateDialog(savedInstanceState : Bundle? ) : Dialog {
val calender = Calendar.getInstance()
val initYear = calender.get(Calender.YEAR)
...
return DatePickerDialog(
requireContext(),
null,
initYear,
initMonth,
initDay)
}
위와 같이 calender 객체를 만들어준뒤, 원하는 날짜의 양식을 정해서 initYear , initMonth, initDay 등으로 나눠서 담아준다. 그리고 반환 Return을 이 뷰에서 필요한 리소스를 사용하려 지정한 컨텍스트 객체를 선정한다. 그리고 날짜 리스너부분, 나머지는 초깃값 (년,월,일) 이 파라미터로 사용되어 DatePickerDialog ()를 반환해준다.
show(manager: FragmentManager , tag : String)
show(transaction : FragmentTransaction , tag: String )
show() 함수는 위의 DialogFragment를 띄울 장소에서 사용된다. 즉, 어떠한 버튼을 눌렀을 때, 날짜 선택 대화상자가 뜨도록 하는 직접적인 실행 함수라고 할 수 있다.
이 함수는 사용할 프래그먼트에서 보통 onClickListener() 을 통해 구현하는데,
...
dataButton.setOnClickListener{
DatePickerFragment().apply{
show(this@blahFragment.parentFragmentManager(), DIALOG_DATE)
}
}
...
위 와 같이 원하는 이벤트 리스너에서 생성한 프래그먼트에 apply 하는 것이다.
show()함수는 여기서 사용하는데, 해당 프래그먼트.parentFragmentManager()을 통해 매니저를 부르고(null값이 허용안된다.), Tag를 통해 식별을 해주는 것이다.
그렇다면, FragmentManager 와 FragmentTransaction의 차이는 무엇일까? 둘 중 어느것을 사용해도 상관없지만, 트랙잭션은 직접 트랜잭션을 생성한 후 커밋을 해야 하는 것이다. 매니저는 트랜잭션이 자동으로 생성되어 커밋되는 차이점이 있다.
데이터를 전달해보자
대화상자 프래그먼트와 화면이 보여지는 프래그먼트 간의 연결이 필요한데, 이 작업을 newInstance() 함수를 생성하여 서로 데이터를 주고 받게 해주는 다리를 놓아준다.
1. DB 데이터를 대화상자에 반영해주자 먼저 대화상자 프래그먼트에서 동반객체(companion object)를 만들어서 그 안에 newInstance()를 정의 해준다.
private const val ARG_DATE = "date"
class DatePickerFragment : DialogFragment(){
...
override fun onCreateDialog(savedInstanceState: Bundle?) : Dialog {
val date = arguments?.getSerializable(ARG_DATE) as Date
val calender = Calender.getInstance()
calender.time = date
....
}
companion object{
fun newInstance(date:Date) : DatePickerFragment{
// 프래그먼트에서 실행되므로 그 상태의 정보를 받아온 것이 date이다.
// 이 Date를 Bundle로 구성된 Args 에 넣어주고, 이 값을 다시 날짜선택 대화상자 프래그먼트에 반영해주는 것이다.
val args = Bundle().apply {
putSerializable(ARG_DATE, date)
}
return DatePickerFragment().apply {
arguments = args
}
}
}
...
}
위의 코드를 보면, Args 라는 bundle() 객체 바구니에 newinstance에서 받아온 인자 Date를 넣어주는 부분이 보인다.
그리고 나서, Return 에서 다시 대화상자 프래그먼트로 apply를 Arguments에 넣어주는 것을 볼 수 있다.
이 부분의 의미는 데이터베이스에 있던 기존 날짜의 값을 대화상자에 로드 되도록 해주는 것이다.
그리고 상당 onCreateDialog 에서 이전 프래그먼트에서 준 Date 타입의 객체를 형변환하여 Calendar 안에 넣어줘야 한다.
위의 방식대로 타입을 As Date로 하여 받아온뒤 그 값을 calendar.time 에 반영해주면 날짜값의 초기화가 가능하다.
2. 사용자가 새로 설정한 날짜를 반환해주자
'Programming > Android' 카테고리의 다른 글
Take Photo with Intent (0) | 2021.08.03 |
---|---|
Frag to Frag with Data (0) | 2021.07.28 |
JetPack AAC: LiveData (0) | 2021.07.27 |