Skip to content

Instantly share code, notes, and snippets.

@n0m0r3pa1n
Last active Oct 4, 2021
Embed
What would you like to do?
import android.app.Dialog
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.DatePicker
import androidx.appcompat.app.AlertDialog
import androidx.core.os.bundleOf
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import dagger.hilt.android.AndroidEntryPoint
import java.time.LocalDate
import java.time.ZoneOffset
@AndroidEntryPoint
class DatePickerDialogFragment private constructor() : DialogFragment(), DatePicker.OnDateChangedListener {
private val preselectedDate: LocalDate by lazy { (requireArguments().getSerializable(ARG_PRESELECTED_DATE) as? LocalDate) ?: LocalDate.now() }
private val minDate: LocalDate? by lazy { (requireArguments().getSerializable(ARG_MIN_DATE) as? LocalDate) }
private val maxDate: LocalDate? by lazy { (requireArguments().getSerializable(ARG_MAX_DATE) as? LocalDate) }
private val caller: String by lazy { requireNotNull(requireArguments().getString(ARG_REQUEST_KEY)) }
private val viewModel: DatePickerDialogViewModel by activityViewModels()
private var selectedDate: LocalDate? = null
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialogView = View.inflate(requireContext(), R.layout.view_date_picker, null)
val datePicker = dialogView.findViewById<DatePicker>(R.id.date_picker)
val alertDialog = AlertDialog.Builder(requireContext()).create()
datePicker.init(preselectedDate.year, preselectedDate.legacyCalendarMonth, preselectedDate.dayOfMonth, this)
minDate?.let { datePicker.minDate = it.toEpochMilli(ZoneOffset.UTC) }
maxDate?.let { datePicker.maxDate = it.toEpochMilli(ZoneOffset.UTC) }
dialogView.findViewById<View>(R.id.btn_ok).setOnClickListener {
selectedDate?.let { viewModel.onDateSelected(requestKey = caller, date = it) }
alertDialog.dismiss()
}
dialogView.findViewById<View>(R.id.btn_cancel).setOnClickListener {
alertDialog.dismiss()
}
alertDialog.setView(dialogView)
alertDialog.window?.decorView?.addOnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
if (doesDatePickerTakeAllScreenSpace(datePicker, dialogView)) {
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
}
}
return alertDialog
}
private fun doesDatePickerTakeAllScreenSpace(datePicker: DatePicker, dialogView: View) = datePicker.height >= dialogView.height
override fun onDateChanged(view: DatePicker?, year: Int, monthOfYear: Int, dayOfMonth: Int) {
selectedDate = localDateOfCalendar(year, monthOfYear, dayOfMonth)
}
companion object {
private const val ARG_PRESELECTED_DATE = "preselectedDate"
private const val ARG_MIN_DATE = "minDate"
private const val ARG_MAX_DATE = "maxDate"
private const val ARG_REQUEST_KEY = "requestKey"
fun newInstance(preselectedDate: LocalDate?, requestKey: String, minDate: LocalDate? = null, maxDate: LocalDate? = null) =
DatePickerDialogFragment().apply {
arguments = bundleOf(
ARG_PRESELECTED_DATE to preselectedDate,
ARG_MIN_DATE to minDate,
ARG_MAX_DATE to maxDate,
ARG_REQUEST_KEY to requestKey,
)
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<DatePicker
android:id="@+id/date_picker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:calendarViewShown="true"
android:spinnersShown="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/btn_ok"
style="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:text="@string/ok"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/date_picker" />
<TextView
android:id="@+id/btn_cancel"
style="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:text="@string/cancel"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/btn_ok"
app:layout_constraintTop_toBottomOf="@id/date_picker" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment