Implement TimePreferenceDialogFragmentCompat
Okay, so it was still a large commit here because I forgot to commit midway through. Oops. There is one outstanding bug: The neutral button is currently not very useful if you don't set a custom listener, because the default listener just sets the time picker back to what it was when the dialog opened. Not very useful considering you can just close the dialog. If anyone else ever uses the library, we can work on making it more useful :P
This commit is contained in:
parent
1d360dd726
commit
099a51ac25
|
@ -5,10 +5,7 @@
|
|||
*/
|
||||
package com.jmstudios.redmoon.settings
|
||||
|
||||
import android.app.TimePickerDialog
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.text.format.DateFormat
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
|
@ -67,6 +64,28 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
true
|
||||
}
|
||||
|
||||
automaticTurnOnPref.neutralButtonListener =
|
||||
TimePreference.OnNeutralButtonPressListener { dialog ->
|
||||
Config.startAtSunset = true
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
automaticTurnOnPref.setOnPreferenceChangeListener { _, _ ->
|
||||
Config.startAtSunset = false
|
||||
true
|
||||
}
|
||||
|
||||
automaticTurnOffPref.neutralButtonListener =
|
||||
TimePreference.OnNeutralButtonPressListener { dialog ->
|
||||
Config.stopAtSunrise = true
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
automaticTurnOffPref.setOnPreferenceChangeListener { _, _ ->
|
||||
Config.stopAtSunrise = false
|
||||
true
|
||||
}
|
||||
|
||||
updatePrefs()
|
||||
}
|
||||
|
||||
|
@ -91,24 +110,15 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
|
||||
override fun onDisplayPreferenceDialog(p: Preference?) {
|
||||
if (p is TimePreference) {
|
||||
val DIALOG_FRAGMENT_TAG: String = "androidx.preference.PreferenceFragment.DIALOG"
|
||||
val f = TimePreferenceDialogFragmentCompat.newInstance(p.key)
|
||||
f.setTargetFragment(this, 0);
|
||||
f.show(fragmentManager!!, DIALOG_FRAGMENT_TAG);
|
||||
TimePreferenceDialogFragmentCompat.newInstance(p.key).let {
|
||||
it.setTargetFragment(this, 0)
|
||||
it.show(fragmentManager!!, DIALOG_FRAGMENT_TAG)
|
||||
}
|
||||
} else {
|
||||
super.onDisplayPreferenceDialog(p)
|
||||
}
|
||||
}
|
||||
|
||||
private fun enableSuntime(key: String, enabled: Boolean) {
|
||||
val start = getString(R.string.pref_key_start_time)
|
||||
val stop = getString(R.string.pref_key_stop_time)
|
||||
when (key) {
|
||||
start -> Config.startAtSunset = enabled
|
||||
stop -> Config.stopAtSunrise = enabled
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateLocationPref() {
|
||||
val (latitude, longitude, time) = Config.location
|
||||
locationPref?.summary = when (time) {
|
||||
|
@ -209,5 +219,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
}
|
||||
//endregion
|
||||
|
||||
companion object : Logger()
|
||||
companion object : Logger() {
|
||||
const val DIALOG_FRAGMENT_TAG = "com.jmstudios.redmoon.DIALOG"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ Optional properties:
|
|||
- `app:showNeutralButton` is `"true"` or `"false"` (default false)
|
||||
- `app:neutralButtonText` is a string or reference to one (`"@string/..."`) (default "Default")
|
||||
- `app:useSimpleSummary` is `"true"` or `"false"` (default true)
|
||||
- `app:is24HourView` is `"true"` or `"false"` (default system locale)
|
||||
|
||||
### Simplest
|
||||
|
||||
|
|
|
@ -4,15 +4,14 @@
|
|||
*/
|
||||
package org.libreshift.preferences
|
||||
|
||||
import android.app.TimePickerDialog
|
||||
import android.content.Context
|
||||
import android.content.res.TypedArray
|
||||
import android.text.format.DateFormat
|
||||
import android.util.AttributeSet
|
||||
import androidx.preference.DialogPreference
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
|
||||
open class TimePreference(
|
||||
context: Context,
|
||||
|
@ -21,21 +20,45 @@ open class TimePreference(
|
|||
defStyleRes: Int
|
||||
) : DialogPreference(context, attrs, defStyleAttr, defStyleRes)
|
||||
{
|
||||
interface OnNeutralButtonPressListener {
|
||||
fun onNeutralButtonPress(dialog: TimePickerDialog)
|
||||
|
||||
// Hack around lack of SAM for kotlin interfaces, see link:
|
||||
// https://youtrack.jetbrains.com/issue/KT-7770#focus=streamItem-27-3290802.0-0
|
||||
companion object {
|
||||
inline operator fun invoke(crossinline op: (dialog: TimePickerDialog) -> Unit) =
|
||||
object : OnNeutralButtonPressListener {
|
||||
override fun onNeutralButtonPress(dialog: TimePickerDialog) = op(dialog)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
val is24HourView: Boolean
|
||||
var showNeutralButton: Boolean
|
||||
val neutralButtonText: String
|
||||
|
||||
var neutralButtonListener: OnNeutralButtonPressListener? = null
|
||||
|
||||
init {
|
||||
val a: TypedArray = context.obtainStyledAttributes(
|
||||
attrs, R.styleable.TimePreference, defStyleAttr, defStyleAttr
|
||||
)
|
||||
|
||||
val default24H = DateFormat.is24HourFormat(context)
|
||||
is24HourView = a.getBoolean(R.styleable.TimePreference_is24HourView, default24H)
|
||||
|
||||
showNeutralButton = a.getBoolean(R.styleable.TimePreference_showNeutralButton, false)
|
||||
|
||||
val nbText = a.getString(R.styleable.TimePreference_neutralButtonText)
|
||||
neutralButtonText = nbText ?: context.getString(R.string.btn_neutral_default)
|
||||
|
||||
if (a.getBoolean(R.styleable.TimePreference_useSimpleSummary, true)) {
|
||||
setSummaryProvider(defaultSummaryProvider)
|
||||
summaryProvider = defaultSummaryProvider
|
||||
}
|
||||
|
||||
neutralButtonListener = OnNeutralButtonPressListener { dialog ->
|
||||
dialog.updateTime(time.hour, time.minute)
|
||||
}
|
||||
|
||||
a.recycle()
|
||||
|
@ -66,10 +89,12 @@ open class TimePreference(
|
|||
}
|
||||
}
|
||||
|
||||
/** To the Android system, we represent time as a string */
|
||||
override fun onGetDefaultValue(a: TypedArray, index: Int): String? {
|
||||
return a.getString(index)
|
||||
}
|
||||
|
||||
/** Internally, though, we store the time as a Time */
|
||||
override fun onSetInitialValue(defaultValue: Any?) {
|
||||
val default: String = defaultValue as? String ?: "$time"
|
||||
time = Time(getPersistedString(default))
|
||||
|
@ -97,14 +122,14 @@ open class TimePreference(
|
|||
|
||||
fun format(context: Context?): String {
|
||||
if (context == null) {
|
||||
// Can't format to local time, so just use the raw HH:mm
|
||||
return this.toString()
|
||||
}
|
||||
val timestr = Calendar.getInstance().run {
|
||||
set(Calendar.HOUR_OF_DAY, hour)
|
||||
set(Calendar.MINUTE, minute)
|
||||
getTime()
|
||||
val calendar = Calendar.getInstance().also {
|
||||
it.set(Calendar.HOUR_OF_DAY, hour)
|
||||
it.set(Calendar.MINUTE, minute)
|
||||
}
|
||||
return DateFormat.getTimeFormat(context).format(timestr)
|
||||
return DateFormat.getTimeFormat(context).format(calendar.time)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
|
|
@ -2,49 +2,32 @@
|
|||
* Copyright (c) 2020 Stephen Michel <s@smichel.me>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Based in part on Android's PreferenceDialogFragmentCompat
|
||||
* Based in part on Android's PreferenceDialogFragmentCompat, which is
|
||||
* Copyright 2018 The Android Open Source Project
|
||||
* Used under the Apache License, Version 2.0
|
||||
*/
|
||||
package org.libreshift.preferences
|
||||
|
||||
import androidx.annotation.RestrictTo.Scope.LIBRARY
|
||||
|
||||
import android.app.Dialog
|
||||
import android.app.TimePickerDialog
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.annotation.RestrictTo
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.text.format.DateFormat
|
||||
import android.util.Log
|
||||
import android.widget.TimePicker
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.preference.DialogPreference
|
||||
import androidx.preference.DialogPreference.TargetFragment
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
|
||||
|
||||
// TimePickerDialog(context, { _, h, m ->
|
||||
// preference.callChangeListener(Time(h, m))
|
||||
// }, 0, 0, false).show()
|
||||
|
||||
open class TimePreferenceDialogFragmentCompat() : DialogFragment(), DialogInterface.OnClickListener {
|
||||
open class TimePreferenceDialogFragmentCompat : DialogFragment(), TimePickerDialog.OnTimeSetListener {
|
||||
/**
|
||||
* The preference that requested this dialog. Available after [.onCreate] has
|
||||
* been called on the [PreferenceFragmentCompat] which launched this dialog.
|
||||
*
|
||||
* @return The [TimePreference] associated with this dialog
|
||||
*/
|
||||
var mPreference: TimePreference? = null
|
||||
var preference: TimePreference? = null
|
||||
get() {
|
||||
if (field == null) {
|
||||
val key = arguments!!.getString(ARG_KEY)!!
|
||||
|
@ -55,17 +38,12 @@ open class TimePreferenceDialogFragmentCompat() : DialogFragment(), DialogInterf
|
|||
}
|
||||
private set
|
||||
|
||||
private var mDialogTitle: CharSequence? = null
|
||||
private var mPositiveButtonText: CharSequence? = null
|
||||
private var mNegativeButtonText: CharSequence? = null
|
||||
private var mDialogMessage: CharSequence? = null
|
||||
private var neutralButtonText: CharSequence? = null
|
||||
private var showNeutralButton: Boolean = false
|
||||
private var is24HourView: Boolean = false
|
||||
private var initialHour: Int = 0
|
||||
private var initialMinute: Int = 0
|
||||
|
||||
@LayoutRes
|
||||
private var mDialogLayoutRes = 0
|
||||
private var mDialogIcon: BitmapDrawable? = null
|
||||
|
||||
/** Which button was clicked. */
|
||||
private var mWhichButtonClicked = 0
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val fragment: TargetFragment
|
||||
|
@ -77,140 +55,105 @@ open class TimePreferenceDialogFragmentCompat() : DialogFragment(), DialogInterf
|
|||
}
|
||||
if (savedInstanceState == null) {
|
||||
val key = arguments!!.getString(ARG_KEY)!!
|
||||
mPreference = fragment.findPreference(key)
|
||||
mDialogTitle = mPreference?.dialogTitle
|
||||
mPositiveButtonText = mPreference?.positiveButtonText
|
||||
mNegativeButtonText = mPreference?.negativeButtonText
|
||||
mDialogMessage = mPreference?.dialogMessage
|
||||
mDialogLayoutRes = mPreference?.dialogLayoutResource ?: mDialogLayoutRes
|
||||
val icon: Drawable? = mPreference?.dialogIcon
|
||||
mDialogIcon = if (icon == null || icon is BitmapDrawable) {
|
||||
icon as BitmapDrawable?
|
||||
} else {
|
||||
val bitmap = Bitmap.createBitmap(icon.intrinsicWidth,
|
||||
icon.intrinsicHeight, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(bitmap)
|
||||
icon.setBounds(0, 0, canvas.width, canvas.height)
|
||||
icon.draw(canvas)
|
||||
BitmapDrawable(resources, bitmap)
|
||||
}
|
||||
preference = fragment.findPreference(key)
|
||||
neutralButtonText = preference?.neutralButtonText
|
||||
showNeutralButton = preference?.showNeutralButton ?: showNeutralButton
|
||||
is24HourView = preference?.is24HourView ?: DateFormat.is24HourFormat(context)
|
||||
initialHour = preference?.time?.hour ?: initialHour
|
||||
initialMinute = preference?.time?.minute ?: initialMinute
|
||||
} else {
|
||||
mDialogTitle = savedInstanceState.getCharSequence(SAVE_STATE_TITLE)
|
||||
mPositiveButtonText = savedInstanceState.getCharSequence(SAVE_STATE_POSITIVE_TEXT)
|
||||
mNegativeButtonText = savedInstanceState.getCharSequence(SAVE_STATE_NEGATIVE_TEXT)
|
||||
mDialogMessage = savedInstanceState.getCharSequence(SAVE_STATE_MESSAGE)
|
||||
mDialogLayoutRes = savedInstanceState.getInt(SAVE_STATE_LAYOUT, 0)
|
||||
val bitmap = savedInstanceState.getParcelable<Bitmap>(SAVE_STATE_ICON)
|
||||
if (bitmap != null) {
|
||||
mDialogIcon = BitmapDrawable(resources, bitmap)
|
||||
}
|
||||
neutralButtonText = savedInstanceState.getCharSequence(SAVE_STATE_NEUTRAL_TEXT)
|
||||
showNeutralButton = savedInstanceState.getBoolean(SAVE_STATE_SHOW_NEUTRAL)
|
||||
is24HourView = savedInstanceState.getBoolean(SAVE_STATE_24_HOUR_VIEW)
|
||||
initialHour = savedInstanceState.getInt(SAVE_STATE_INITIAL_HOUR)
|
||||
initialMinute = savedInstanceState.getInt(SAVE_STATE_INITIAL_MINUTE)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putCharSequence(SAVE_STATE_TITLE, mDialogTitle)
|
||||
outState.putCharSequence(SAVE_STATE_POSITIVE_TEXT, mPositiveButtonText)
|
||||
outState.putCharSequence(SAVE_STATE_NEGATIVE_TEXT, mNegativeButtonText)
|
||||
outState.putCharSequence(SAVE_STATE_MESSAGE, mDialogMessage)
|
||||
outState.putInt(SAVE_STATE_LAYOUT, mDialogLayoutRes)
|
||||
if (mDialogIcon != null) {
|
||||
outState.putParcelable(SAVE_STATE_ICON, mDialogIcon!!.bitmap)
|
||||
}
|
||||
outState.putCharSequence(SAVE_STATE_NEUTRAL_TEXT, neutralButtonText)
|
||||
outState.putBoolean(SAVE_STATE_SHOW_NEUTRAL, showNeutralButton)
|
||||
outState.putBoolean(SAVE_STATE_24_HOUR_VIEW, is24HourView)
|
||||
outState.putInt(SAVE_STATE_INITIAL_HOUR, initialHour)
|
||||
outState.putInt(SAVE_STATE_INITIAL_MINUTE, initialMinute)
|
||||
}
|
||||
|
||||
/**
|
||||
* We'd have more control if we instantiated the dialog and populated the
|
||||
* view directly, but putting a time picker inside a dialog is a black art.
|
||||
* TimePickerDialog needs to subclass AlertDialog and use package-private
|
||||
* methods to do it (specifically for layout in landscape orientation).
|
||||
*
|
||||
* So we'll just call TimePickerDialog and hack its output. This is also
|
||||
* why we subclass DialogFragment instead of PreferenceDialogFragmentCompat.
|
||||
* This means we only have access to the dialog, not its builder, but the
|
||||
* only *real* downside is that we can't access the dialog view (ie, the
|
||||
* time picker) directly, to offer onBindDialogView().
|
||||
*/
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val context: Context = activity!!
|
||||
mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE
|
||||
val builder: AlertDialog.Builder = AlertDialog.Builder(context)
|
||||
.setTitle(mDialogTitle)
|
||||
.setIcon(mDialogIcon)
|
||||
.setPositiveButton(mPositiveButtonText, this)
|
||||
.setNegativeButton(mNegativeButtonText, this)
|
||||
val contentView: View? = onCreateDialogView(context)
|
||||
if (contentView != null) {
|
||||
onBindDialogView(contentView)
|
||||
builder.setView(contentView)
|
||||
} else {
|
||||
builder.setMessage(mDialogMessage)
|
||||
|
||||
val dialog = TimePickerDialog(context, this, initialHour, initialMinute, is24HourView)
|
||||
|
||||
if (showNeutralButton) {
|
||||
// I would pass null for the last argument, but kotlin's type checker yells at me
|
||||
dialog.setButton(DialogInterface.BUTTON_NEUTRAL, neutralButtonText) { _, _ -> }
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
dialog.create()
|
||||
// If we had a higher minApi, we could attach the listener here
|
||||
// Instead, we need to wait until dialog.show() has been called
|
||||
}
|
||||
onPrepareDialogBuilder(builder)
|
||||
// Create the dialog
|
||||
val dialog: Dialog = builder.create()
|
||||
return dialog
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepares the dialog builder to be shown when the preference is clicked.
|
||||
* Use this to set custom properties on the dialog.
|
||||
* DialogFragment.onStart() is where dialog.show() is called, which means
|
||||
* the view has been instantiated so now we can get a reference to the
|
||||
* neutral button and override the onClick listener, to prevent the dialog
|
||||
* from closing if we don't want it to.
|
||||
*
|
||||
* This is a fragile implementation. It would be better to create our own
|
||||
* TimePickerDialog subclass and override its show() and/or onClick methods.
|
||||
* This would also allow us to persist values in the neutral button case.
|
||||
* See: https://android.googlesource.com/platform/frameworks/base/+/master
|
||||
* /core/java/android/app/TimePickerDialog.java#149
|
||||
*
|
||||
* Do not [AlertDialog.Builder.create] or [AlertDialog.Builder.show].
|
||||
* Maybe later, I've already spent a lot of time on this.
|
||||
*/
|
||||
protected fun onPrepareDialogBuilder(builder: AlertDialog.Builder?) {}
|
||||
|
||||
/**
|
||||
* Creates the content view for the dialog (if a custom content view is required).
|
||||
* By default, it inflates the dialog layout resource if it is set.
|
||||
*
|
||||
* @return The content view for the dialog
|
||||
* @see DialogPreference.setLayoutResource
|
||||
*/
|
||||
protected fun onCreateDialogView(context: Context?): View? {
|
||||
val resId = mDialogLayoutRes
|
||||
if (resId == 0) {
|
||||
return null
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val tpd = (dialog as TimePickerDialog)
|
||||
tpd.getButton(DialogInterface.BUTTON_NEUTRAL).setOnClickListener {
|
||||
preference?.neutralButtonListener?.onNeutralButtonPress(tpd)
|
||||
}
|
||||
val inflater = LayoutInflater.from(context)
|
||||
return inflater.inflate(resId, null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds views in the content view of the dialog to data.
|
||||
*
|
||||
*
|
||||
* Make sure to call through to the superclass implementation.
|
||||
*
|
||||
* @param view The content view of the dialog, if it is custom
|
||||
*/
|
||||
protected fun onBindDialogView(view: View) {
|
||||
val dialogMessageView: View? = view.findViewById(R.id.message)
|
||||
if (dialogMessageView != null) {
|
||||
val message = mDialogMessage
|
||||
var newVisibility: Int = View.GONE
|
||||
if (!TextUtils.isEmpty(message)) {
|
||||
if (dialogMessageView is TextView) {
|
||||
(dialogMessageView as TextView).text = message
|
||||
}
|
||||
newVisibility = View.VISIBLE
|
||||
}
|
||||
if (dialogMessageView.visibility !== newVisibility) {
|
||||
dialogMessageView.visibility = newVisibility
|
||||
/** Called when the user presses OK, after the dialog has closed. */
|
||||
override fun onTimeSet(picker: TimePicker?, hour: Int, minute: Int) {
|
||||
Log.i(TAG, "onTimeSet: $hour:$minute")
|
||||
preference?.let {
|
||||
val shouldSave = it.callChangeListener(TimePreference.Time(hour, minute))
|
||||
if (shouldSave) {
|
||||
it.time = TimePreference.Time(hour, minute)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClick(dialog: DialogInterface?, which: Int) {
|
||||
mWhichButtonClicked = which
|
||||
}
|
||||
|
||||
override fun onDismiss(dialog: DialogInterface) {
|
||||
super.onDismiss(dialog)
|
||||
onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE)
|
||||
}
|
||||
|
||||
protected fun onDialogClosed(positiveResult: Boolean) {}
|
||||
/** Called when dialog closes, regardless of which button was pressed */
|
||||
// override fun onDismiss(dialog: DialogInterface) { }
|
||||
|
||||
companion object {
|
||||
private const val TAG = "TimePrefDialogFragment"
|
||||
// For persisting state
|
||||
protected const val ARG_KEY = "key"
|
||||
private const val SAVE_STATE_TITLE = "TimePreferenceDialogFragment.title"
|
||||
private const val SAVE_STATE_POSITIVE_TEXT = "TimePreferenceDialogFragment.positiveText"
|
||||
private const val SAVE_STATE_NEGATIVE_TEXT = "TimePreferenceDialogFragment.negativeText"
|
||||
private const val SAVE_STATE_MESSAGE = "TimePreferenceDialogFragment.message"
|
||||
private const val SAVE_STATE_LAYOUT = "TimePreferenceDialogFragment.layout"
|
||||
private const val SAVE_STATE_ICON = "TimePreferenceDialogFragment.icon"
|
||||
private const val ARG_KEY = "key"
|
||||
private const val SAVE_STATE_NEUTRAL_TEXT = "TimePreferenceDialogFragment.neutralText"
|
||||
private const val SAVE_STATE_SHOW_NEUTRAL = "TimePreferenceDialogFragment.showNeutral"
|
||||
private const val SAVE_STATE_24_HOUR_VIEW = "TimePreferenceDialogFragment.is24HourView"
|
||||
private const val SAVE_STATE_INITIAL_HOUR = "TimePreferenceDialogFragment.initialHour"
|
||||
private const val SAVE_STATE_INITIAL_MINUTE = "TimePreferenceDialogFragment.initialMinute"
|
||||
|
||||
fun newInstance(key: String): TimePreferenceDialogFragmentCompat {
|
||||
return TimePreferenceDialogFragmentCompat().apply {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<resources>
|
||||
<declare-styleable name="TimePreference">
|
||||
<attr name="useSimpleSummary" format="boolean" />
|
||||
<attr name="is24HourView" format="boolean" />
|
||||
<attr name="showNeutralButton" format="boolean" />
|
||||
<attr name="neutralButtonText" format="string|reference" />
|
||||
</declare-styleable>
|
||||
|
|
Loading…
Reference in New Issue