TimePicker dans PreferenceScreen

Je voudrais créer un champ de préférences appelé Interval et je veux pouvoir TimePicker un TimePicker et définir une valeur TimePicker mm:ss avec une valeur minimale de 00:30 et un pas de 30 secondes.

Est-il possible d’utiliser TimePicker dans PreferenceScreen ?

Il n’y a pas de TimePreference intégré à Android. Cependant, créer votre propre est assez facile. En voici un que j’ai fait :

 import android.content.Context; import android.content.res.TypedArray; import android.preference.DialogPreference; import android.util.AtsortingbuteSet; import android.view.View; import android.widget.TimePicker; public class TimePreference extends DialogPreference { private int lastHour=0; private int lastMinute=0; private TimePicker picker=null; public static int getHour(Ssortingng time) { Ssortingng[] pieces=time.split(":"); return(Integer.parseInt(pieces[0])); } public static int getMinute(Ssortingng time) { Ssortingng[] pieces=time.split(":"); return(Integer.parseInt(pieces[1])); } public TimePreference(Context ctxt, AtsortingbuteSet attrs) { super(ctxt, attrs); setPositiveButtonText("Set"); setNegativeButtonText("Cancel"); } @Override protected View onCreateDialogView() { picker=new TimePicker(getContext()); return(picker); } @Override protected void onBindDialogView(View v) { super.onBindDialogView(v); picker.setCurrentHour(lastHour); picker.setCurrentMinute(lastMinute); } @Override protected void onDialogClosed(boolean positiveResult) { super.onDialogClosed(positiveResult); if (positiveResult) { lastHour=picker.getCurrentHour(); lastMinute=picker.getCurrentMinute(); Ssortingng time=Ssortingng.valueOf(lastHour)+":"+Ssortingng.valueOf(lastMinute); if (callChangeListener(time)) { persistSsortingng(time); } } } @Override protected Object onGetDefaultValue(TypedArray a, int index) { return(a.getSsortingng(index)); } @Override protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { Ssortingng time=null; if (restoreValue) { if (defaultValue==null) { time=getPersistedSsortingng("00:00"); } else { time=getPersistedSsortingng(defaultValue.toSsortingng()); } } else { time=defaultValue.toSsortingng(); } lastHour=getHour(time); lastMinute=getMinute(time); } } 

J’ai modifié le code de la première réponse:

  • il stocke le temps sélectionné sous forme longue (millisecondes), ce qui est plus facile à utiliser (en utilisant le calendrier)
  • il affiche automatiquement l’heure sélectionnée dans le champ de résumé dans le format de l’utilisateur (12 ou 24 heures)

Code mis à jour:

 public class TimePreference extends DialogPreference { private Calendar calendar; private TimePicker picker = null; public TimePreference(Context ctxt) { this(ctxt, null); } public TimePreference(Context ctxt, AtsortingbuteSet attrs) { this(ctxt, attrs, android.R.attr.dialogPreferenceStyle); } public TimePreference(Context ctxt, AtsortingbuteSet attrs, int defStyle) { super(ctxt, attrs, defStyle); setPositiveButtonText(R.ssortingng.set); setNegativeButtonText(R.ssortingng.cancel); calendar = new GregorianCalendar(); } @Override protected View onCreateDialogView() { picker = new TimePicker(getContext()); return (picker); } @Override protected void onBindDialogView(View v) { super.onBindDialogView(v); picker.setCurrentHour(calendar.get(Calendar.HOUR_OF_DAY)); picker.setCurrentMinute(calendar.get(Calendar.MINUTE)); } @Override protected void onDialogClosed(boolean positiveResult) { super.onDialogClosed(positiveResult); if (positiveResult) { calendar.set(Calendar.HOUR_OF_DAY, picker.getCurrentHour()); calendar.set(Calendar.MINUTE, picker.getCurrentMinute()); setSummary(getSummary()); if (callChangeListener(calendar.getTimeInMillis())) { persistLong(calendar.getTimeInMillis()); notifyChanged(); } } } @Override protected Object onGetDefaultValue(TypedArray a, int index) { return (a.getSsortingng(index)); } @Override protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { if (restoreValue) { if (defaultValue == null) { calendar.setTimeInMillis(getPersistedLong(System.currentTimeMillis())); } else { calendar.setTimeInMillis(Long.parseLong(getPersistedSsortingng((Ssortingng) defaultValue))); } } else { if (defaultValue == null) { calendar.setTimeInMillis(System.currentTimeMillis()); } else { calendar.setTimeInMillis(Long.parseLong((Ssortingng) defaultValue)); } } setSummary(getSummary()); } @Override public CharSequence getSummary() { if (calendar == null) { return null; } return DateFormat.getTimeFormat(getContext()).format(new Date(calendar.getTimeInMillis())); } } 

Pour ceux que l’implémentation d’une préférence personnalisée n’est pas si évidente (comme ce n’était pas le cas pour moi), vous devez l’append à votre preferences.xml ou à tout ce que vous appelez.

Vous allez vous retrouver avec quelque chose comme ça:

       

En supposant que vous avez ajouté le TimePreference à votre propre package racine:
( src/com/example/myapp/TimePreference.java )

Pour la Preferences Support Library un code différent est nécessaire. Il nécessite deux classes personnalisées TimePreference et TimePreferenceDialogFragmentCompat , ainsi que la substitution de la méthode onDisplayPreferenceDialog dans la classe d’extension PreferenceFragmentCompat .


TimePreference.java

 package com.test; import android.content.Context; import android.content.res.TypedArray; import android.support.v7.preference.DialogPreference; import android.util.AtsortingbuteSet; public class TimePreference extends DialogPreference { public int hour = 0; public int minute = 0; public static int parseHour(Ssortingng value) { try { Ssortingng[] time = value.split(":"); return (Integer.parseInt(time[0])); } catch (Exception e) { return 0; } } public static int parseMinute(Ssortingng value) { try { Ssortingng[] time = value.split(":"); return (Integer.parseInt(time[1])); } catch (Exception e) { return 0; } } public static Ssortingng timeToSsortingng(int h, int m) { return Ssortingng.format("%02d", h) + ":" + Ssortingng.format("%02d", m); } public TimePreference(Context context, AtsortingbuteSet attrs) { super(context, attrs); } @Override protected Object onGetDefaultValue(TypedArray a, int index) { return a.getSsortingng(index); } @Override protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { Ssortingng value; if (restoreValue) { if (defaultValue == null) value = getPersistedSsortingng("00:00"); else value = getPersistedSsortingng(defaultValue.toSsortingng()); } else { value = defaultValue.toSsortingng(); } hour = parseHour(value); minute = parseMinute(value); } public void persistSsortingngValue(Ssortingng value) { persistSsortingng(value); } } 

TimePreferenceDialogFragmentCompat.java

 package com.test; import android.content.Context; import android.support.v7.preference.DialogPreference; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceDialogFragmentCompat; import android.view.View; import android.widget.TimePicker; public class TimePreferenceDialogFragmentCompat extends PreferenceDialogFragmentCompat implements DialogPreference.TargetFragment { TimePicker timePicker = null; @Override protected View onCreateDialogView(Context context) { timePicker = new TimePicker(context); return (timePicker); } @Override protected void onBindDialogView(View v) { super.onBindDialogView(v); timePicker.setIs24HourView(true); TimePreference pref = (TimePreference) getPreference(); timePicker.setCurrentHour(pref.hour); timePicker.setCurrentMinute(pref.minute); } @Override public void onDialogClosed(boolean positiveResult) { if (positiveResult) { TimePreference pref = (TimePreference) getPreference(); pref.hour = timePicker.getCurrentHour(); pref.minute = timePicker.getCurrentMinute(); Ssortingng value = TimePreference.timeToSsortingng(pref.hour, pref.minute); if (pref.callChangeListener(value)) pref.persistSsortingngValue(value); } } @Override public Preference findPreference(CharSequence charSequence) { return getPreference(); } } 

Modifications requirejses dans la classe d’extension PreferenceFragmentCompat

  public static class PreferencesFragment extends PreferenceFragmentCompat { .... @Override public void onDisplayPreferenceDialog(Preference preference) { DialogFragment dialogFragment = null; if (preference instanceof TimePreference) { dialogFragment = new TimePreferenceDialogFragmentCompat(); Bundle bundle = new Bundle(1); bundle.putSsortingng("key", preference.getKey()); dialogFragment.setArguments(bundle); } if (dialogFragment != null) { dialogFragment.setTargetFragment(this, 0); dialogFragment.show(this.getFragmentManager(), "android.support.v7.preference.PreferenceFragment.DIALOG"); } else { super.onDisplayPreferenceDialog(preference); } } } 

Avec le code ci-dessus, la préférence de temps peut être utilisée dans un fichier XML de préférences comme celui-ci

  

ajoutez ceci pour le résumé:

 @Override public CharSequence getSummary() { Calendar cal = Calendar.getInstance(); cal.set(Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH, lastHour, lastMinute); return DateFormat.getTimeFormat(getContext()).format(new Date(cal.getTimeInMillis())); } 

et append

 setSummary(getSummary()); 

pour terminer onSetInitialValue et onDialogClosed .

La solution CommonsWare a quelques problèmes, que j’ai corrigés:

  • Il ne met pas à jour le champ correctement après sa modification
  • La valeur des minutes ne persiste qu’un seul chiffre, par exemple 10: 2 au lieu de 10:02
  • Si vous utilisez PreferenceManager.setDefaultPreferences pour définir les préférences par défaut initiales dans votre application, cela ne fonctionnera pas car onSetInitialValue doit le persister
  • Le formatage du résultat n’est pas adapté aux parameters régionaux de l’utilisateur (par exemple, les États-Unis utilisent AM / PM)

Voici mon code, profitez-en.

 public class TimePreference extends DialogPreference { private int lastHour=0; private int lastMinute=0; private TimePicker picker=null; public static int getHour(Ssortingng time) { Ssortingng[] pieces=time.split(":"); return(Integer.parseInt(pieces[0])); } public static int getMinute(Ssortingng time) { Ssortingng[] pieces=time.split(":"); return(Integer.parseInt(pieces[1])); } public TimePreference(Context ctxt, AtsortingbuteSet attrs) { super(ctxt, attrs); setPositiveButtonText("Set"); setNegativeButtonText("Cancel"); } @Override protected View onCreateDialogView() { picker=new TimePicker(getContext()); return(picker); } @Override protected void onBindDialogView(View v) { super.onBindDialogView(v); picker.setCurrentHour(lastHour); picker.setCurrentMinute(lastMinute); } @Override protected void onDialogClosed(boolean positiveResult) { super.onDialogClosed(positiveResult); if (positiveResult) { lastHour=picker.getCurrentHour(); lastMinute=picker.getCurrentMinute(); setSummary(getSummary()); Ssortingng lastMinuteSsortingng = Ssortingng.valueOf(lastMinute); Ssortingng time = Ssortingng.valueOf(lastHour) + ":" + (lastMinuteSsortingng.length() == 1 ? "0" + lastMinuteSsortingng : lastMinuteSsortingng); if (callChangeListener(time)) { persistSsortingng(time); } } } @Override protected Object onGetDefaultValue(TypedArray a, int index) { return(a.getSsortingng(index)); } @Override protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { Ssortingng time; Ssortingng defaultValueStr = (defaultValue != null) ? defaultValue.toSsortingng() : "00:00"; if (restoreValue) time = getPersistedSsortingng(defaultValueStr); else { time = defaultValueStr; if (shouldPersist()) persistSsortingng(defaultValueStr); } lastHour=getHour(time); lastMinute=getMinute(time); setSummary(getSummary()); } @Override public CharSequence getSummary() { Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, lastHour); cal.set(Calendar.MINUTE, lastMinute); DateFormat sdf = SimpleDateFormat.getTimeInstance(SimpleDateFormat.SHORT); return sdf.format(cal.getTime()); } } 

J’ai modifié CommonsWare pour utiliser la bibliothèque JodaTime:

 import android.content.Context; import android.content.res.TypedArray; import android.preference.DialogPreference; import android.support.annotation.NonNull; import android.util.AtsortingbuteSet; import android.view.View; import android.widget.TimePicker; import org.joda.time.LocalTime; public class TimePreference extends DialogPreference { private int lastHour; private int lastMinute; private TimePicker picker; public TimePreference(Context context, AtsortingbuteSet attrs) { super(context, attrs); setPositiveButtonText("Set"); setNegativeButtonText("Cancel"); } @Override protected View onCreateDialogView() { picker = new TimePicker(getContext()); return(picker); } @Override protected void onBindDialogView(@NonNull View v) { super.onBindDialogView(v); picker.setCurrentHour(lastHour); picker.setCurrentMinute(lastMinute); } @Override protected void onDialogClosed(boolean positiveResult) { super.onDialogClosed(positiveResult); if (positiveResult) { lastHour = picker.getCurrentHour(); lastMinute = picker.getCurrentMinute(); LocalTime localTime = new LocalTime(lastHour, lastMinute); Ssortingng time = localTime.toSsortingng(); if (callChangeListener(time)) { persistSsortingng(time); } } } @Override protected Object onGetDefaultValue(TypedArray a, int index) { return(a.getSsortingng(index)); } @Override protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { LocalTime time; if (restoreValue) { if (defaultValue == null) { time = LocalTime.parse(getPersistedSsortingng("08:00:00.000")); } else { time = LocalTime.parse(getPersistedSsortingng(defaultValue.toSsortingng())); } } else { time = LocalTime.parse(defaultValue.toSsortingng()); } lastHour = time.getHourOfDay(); lastMinute = time.getMinuteOfHour(); } } 

En outre, vous devrez append une préférence personnalisée, comme dit Sikora.

       

Avec Android 6, “heure actuelle” et “minute actuelle” sont obsolètes. Utilisez cette option pour garantir la compatibilité avec la guimauve:

 import android.content.Context; import android.content.res.TypedArray; import android.os.Build; import android.preference.DialogPreference; import android.util.AtsortingbuteSet; import android.view.View; import android.widget.TimePicker; public class TimePreference extends DialogPreference { private int lastHour; private int lastMinute; private TimePicker picker; public TimePreference(Context ctx, AtsortingbuteSet attrs) { super(ctx, attrs); setPositiveButtonText(ctx.getSsortingng(android.R.ssortingng.ok)); setNegativeButtonText(ctx.getSsortingng(android.R.ssortingng.cancel)); } @Override protected View onCreateDialogView() { picker = new TimePicker(getContext()); picker.setIs24HourView(true); return picker; } @SuppressWarnings("deprecation") @Override protected void onBindDialogView(View v) { super.onBindDialogView(v); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { picker.setCurrentHour(lastHour); picker.setCurrentMinute(lastMinute); } else { picker.setHour(lastHour); picker.setMinute(lastMinute); } } @SuppressWarnings("deprecation") @Override protected void onDialogClosed(boolean positiveResult) { super.onDialogClosed(positiveResult); if (positiveResult) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { lastHour = picker.getCurrentHour(); lastMinute = picker.getCurrentMinute(); } else { lastHour = picker.getHour(); lastMinute = picker.getMinute(); } String time = String.valueOf(lastHour) + ":" + String.valueOf(lastMinute); if (callChangeListener(time)) { persistString(time); } } } @Override protected Object onGetDefaultValue(TypedArray a, int index) { return a.getString(index); } @Override protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { String time; if (restoreValue) { if (defaultValue == null) { time = getPersistedString("00:00"); } else { time = getPersistedString(defaultValue.toString()); } } else { time = defaultValue.toString(); } lastHour = getHour(time); lastMinute = getMinute(time); } public static int getHour(String time) { String[] pieces = time.split(":"); return Integer.parseInt(pieces[0]); } public static int getMinute(String time) { String[] pieces = time.split(":"); return Integer.parseInt(pieces[1]); } } 

Comme LEO87, je voyais des ClassCastException. Le problème était dû aux données persistantes obsolètes d’un contrôle précédent du même nom. Les solutions possibles consistent à effacer les données de l’application, à utiliser un nom (clé) différent ou, si vous devez utiliser le même nom de clé, à intercepter l’exception comme suit:

 @Override protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { if (restoreValue) { long persistedValue; try { persistedValue = getPersistedLong(System.currentTimeMillis()); } catch (Exception e) { //Stale persisted data may be the wrong type persistedValue = System.currentTimeMillis(); } calendar.setTimeInMillis(persistedValue); } else if (defaultValue != null) { calendar.setTimeInMillis(Long.parseLong((Ssortingng) defaultValue)); } else { //!restoreValue, defaultValue == null calendar.setTimeInMillis(System.currentTimeMillis()); } setSummary(getSummary()); }