Archived
Fixed TimePickerFragment.kt crashing on configuration change by parcelising OnTimeSetListener interface - I didn't even know that that was possible tbh; fragments now use childFragmentManager instead of the activity's supportFragmentManager to instantiate bottom sheets
This commit is contained in:
@@ -4,21 +4,29 @@ import android.app.Dialog
|
|||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import android.app.TimePickerDialog
|
import android.app.TimePickerDialog
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Parcelable
|
||||||
import android.widget.TimePicker
|
import android.widget.TimePicker
|
||||||
|
import com.denizk0461.studip.data.getParcelableCompat
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialogue used for letting the user pick a timestamp. TODO crashes on config change (multitask)
|
* Dialogue used for letting the user pick a timestamp.
|
||||||
*
|
|
||||||
* @param listener listener for when the user finishes setting a time
|
|
||||||
* @param isEventStart whether the timestamp to be edited is the start of the event
|
|
||||||
*/
|
*/
|
||||||
class TimePickerFragment(
|
class TimePickerFragment : DialogFragment(), TimePickerDialog.OnTimeSetListener {
|
||||||
private val listener: OnTimeSetListener,
|
|
||||||
private val isEventStart: Boolean,
|
private lateinit var listener: OnTimeSetListener
|
||||||
) : DialogFragment(), TimePickerDialog.OnTimeSetListener {
|
private var isEventStart: Boolean = false
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
|
||||||
|
// Retrieve listener for when the user finishes setting a time
|
||||||
|
listener = arguments.getParcelableCompat("interface")
|
||||||
|
|
||||||
|
// Retrieve whether the timestamp to be edited is the start of the event
|
||||||
|
isEventStart = arguments?.getBoolean("isEventStart") == true
|
||||||
|
|
||||||
|
// Retrieve timestamp to edit
|
||||||
val timestampSplit = (arguments?.getString("timestamp") ?: "").split(":")
|
val timestampSplit = (arguments?.getString("timestamp") ?: "").split(":")
|
||||||
|
|
||||||
return TimePickerDialog(
|
return TimePickerDialog(
|
||||||
activity,
|
activity,
|
||||||
this,
|
this,
|
||||||
@@ -28,11 +36,19 @@ class TimePickerFragment(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the implementation of TimePickerDialog#OnTimeSetListener.
|
||||||
|
*/
|
||||||
|
override fun onTimeSet(picker: TimePicker?, hours: Int, minutes: Int) {
|
||||||
|
// Use custom implementation of OnTimeSetListener
|
||||||
|
listener.onTimeSet(hours, minutes, isEventStart)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom implementation of TimePickerDialog#OnTimeSetListener that includes a boolean to find
|
* Custom implementation of TimePickerDialog#OnTimeSetListener that includes a boolean to find
|
||||||
* out whether the start or the end timestamp has been edited.
|
* out whether the start or the end timestamp has been edited.
|
||||||
*/
|
*/
|
||||||
interface OnTimeSetListener {
|
interface OnTimeSetListener : Parcelable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timestamp has been edited by the user.
|
* Timestamp has been edited by the user.
|
||||||
@@ -43,12 +59,4 @@ class TimePickerFragment(
|
|||||||
*/
|
*/
|
||||||
fun onTimeSet(hours: Int, minutes: Int, isEventStart: Boolean)
|
fun onTimeSet(hours: Int, minutes: Int, isEventStart: Boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Override the implementation of TimePickerDialog#OnTimeSetListener.
|
|
||||||
*/
|
|
||||||
override fun onTimeSet(picker: TimePicker?, hours: Int, minutes: Int) {
|
|
||||||
// Use custom implementation of OnTimeSetListener
|
|
||||||
listener.onTimeSet(hours, minutes, isEventStart)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,6 @@ package com.denizk0461.studip.fragment
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentActivity
|
|
||||||
import com.denizk0461.studip.sheet.AppSheet
|
import com.denizk0461.studip.sheet.AppSheet
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,6 +29,6 @@ open class AppFragment : Fragment() {
|
|||||||
* @param sheet element that will be displayed
|
* @param sheet element that will be displayed
|
||||||
*/
|
*/
|
||||||
protected fun openBottomSheet(sheet: AppSheet) {
|
protected fun openBottomSheet(sheet: AppSheet) {
|
||||||
sheet.show((context as FragmentActivity).supportFragmentManager, sheet.javaClass.simpleName)
|
sheet.show(childFragmentManager, sheet.javaClass.simpleName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.denizk0461.studip.sheet
|
package com.denizk0461.studip.sheet
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Parcel
|
||||||
|
import android.os.Parcelable
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
@@ -26,7 +28,7 @@ import com.denizk0461.studip.viewmodel.ScheduleUpdateViewModel
|
|||||||
/**
|
/**
|
||||||
* Update sheet to allow the user to edit attributes for a specific schedule event.
|
* Update sheet to allow the user to edit attributes for a specific schedule event.
|
||||||
*/
|
*/
|
||||||
class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update), TimePickerFragment.OnTimeSetListener {
|
class ScheduleUpdateSheet() : AppSheet(R.layout.sheet_schedule_update), TimePickerFragment.OnTimeSetListener {
|
||||||
|
|
||||||
// Editable fields
|
// Editable fields
|
||||||
private var timeslotStart = "12:00"
|
private var timeslotStart = "12:00"
|
||||||
@@ -48,6 +50,15 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update), TimePicker
|
|||||||
// Day the event is scheduled for, default is Monday
|
// Day the event is scheduled for, default is Monday
|
||||||
private var selectedDay = 0
|
private var selectedDay = 0
|
||||||
|
|
||||||
|
constructor(parcel: Parcel) : this() {
|
||||||
|
timeslotStart = parcel.readString() ?: ""
|
||||||
|
timeslotEnd = parcel.readString() ?: ""
|
||||||
|
colour = parcel.readInt()
|
||||||
|
hasClickedDelete = parcel.readByte() != 0.toByte()
|
||||||
|
isEditing = parcel.readByte() != 0.toByte()
|
||||||
|
selectedDay = parcel.readInt()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
@@ -274,11 +285,10 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update), TimePicker
|
|||||||
binding.buttonTimeStart.text = timeslotStart
|
binding.buttonTimeStart.text = timeslotStart
|
||||||
binding.buttonTimeStart.setOnClickListener {
|
binding.buttonTimeStart.setOnClickListener {
|
||||||
// Launch a time picker dialogue to pick a new start timestamp
|
// Launch a time picker dialogue to pick a new start timestamp
|
||||||
TimePickerFragment(
|
TimePickerFragment().also { sheet ->
|
||||||
this,
|
|
||||||
true,
|
|
||||||
).also { sheet ->
|
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
|
bundle.putParcelable("interface", this)
|
||||||
|
bundle.putBoolean("isEventStart", true)
|
||||||
bundle.putString("timestamp", binding.buttonTimeStart.text.toString())
|
bundle.putString("timestamp", binding.buttonTimeStart.text.toString())
|
||||||
sheet.arguments = bundle
|
sheet.arguments = bundle
|
||||||
}.show((context as FragmentActivity).supportFragmentManager, "timePicker")
|
}.show((context as FragmentActivity).supportFragmentManager, "timePicker")
|
||||||
@@ -286,11 +296,10 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update), TimePicker
|
|||||||
binding.buttonTimeEnd.text = timeslotEnd
|
binding.buttonTimeEnd.text = timeslotEnd
|
||||||
binding.buttonTimeEnd.setOnClickListener {
|
binding.buttonTimeEnd.setOnClickListener {
|
||||||
// Launch a time picker dialogue to pick a new end timestamp
|
// Launch a time picker dialogue to pick a new end timestamp
|
||||||
TimePickerFragment(
|
TimePickerFragment().also { sheet ->
|
||||||
this,
|
|
||||||
false,
|
|
||||||
).also { sheet ->
|
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
|
bundle.putParcelable("interface", this)
|
||||||
|
bundle.putBoolean("isEventStart", false)
|
||||||
bundle.putString("timestamp", binding.buttonTimeEnd.text.toString())
|
bundle.putString("timestamp", binding.buttonTimeEnd.text.toString())
|
||||||
sheet.arguments = bundle
|
sheet.arguments = bundle
|
||||||
}.show((context as FragmentActivity).supportFragmentManager, "timePicker")
|
}.show((context as FragmentActivity).supportFragmentManager, "timePicker")
|
||||||
@@ -398,4 +407,27 @@ class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update), TimePicker
|
|||||||
} else {
|
} else {
|
||||||
View.GONE
|
View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||||
|
parcel.writeString(timeslotStart)
|
||||||
|
parcel.writeString(timeslotEnd)
|
||||||
|
parcel.writeInt(colour)
|
||||||
|
parcel.writeByte(if (hasClickedDelete) 1 else 0)
|
||||||
|
parcel.writeByte(if (isEditing) 1 else 0)
|
||||||
|
parcel.writeInt(selectedDay)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun describeContents(): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object CREATOR : Parcelable.Creator<ScheduleUpdateSheet> {
|
||||||
|
override fun createFromParcel(parcel: Parcel): ScheduleUpdateSheet {
|
||||||
|
return ScheduleUpdateSheet(parcel)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun newArray(size: Int): Array<ScheduleUpdateSheet?> {
|
||||||
|
return arrayOfNulls(size)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user