PreferenceScreen中的TimePicker

hsz*_*hsz 75 android android-preferences

我想创建一个名为的首选项字段Interval,我希望能够弹出一个TimePicker并设置一个mm:ss具有最小值的格式化值00:30并且步骤30秒.

是否有可能使用TimePickerPreferenceScreen

Com*_*are 150

Android中没有内置TimePreference.但是,创建自己的相当容易.这是我做的一个:

import android.content.Context;
import android.content.res.TypedArray;
import android.preference.DialogPreference;
import android.util.AttributeSet;
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(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]));
    }

    public TimePreference(Context ctxt, AttributeSet 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();

            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=null;

        if (restoreValue) {
            if (defaultValue==null) {
                time=getPersistedString("00:00");
            }
            else {
                time=getPersistedString(defaultValue.toString());
            }
        }
        else {
            time=defaultValue.toString();
        }

        lastHour=getHour(time);
        lastMinute=getMinute(time);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这样可以确保输入的类型值与微调器选择的值一起使用:http://stackoverflow.com/questions/3992820/android-how-to-get-the-time-from-a-timepicker-当-IT-是类型化,在 (2认同)
  • @input:此问题中的实现将时间存储为字符串,格式为"HH:MM".这个问题的另一个答案有一个替代版本,可以将时间存储为长时间. (2认同)
  • 非常好!是否可以为新的 androidx api 创建一个? (2认同)

Dav*_*vra 70

我从第一个答案修改了代码:

  • 它以长格式(毫秒)存储选定的时间,这更容易使用(使用Calendar)然后使用字符串
  • 它会以用户的格式(12或24小时)自动显示汇总字段中的选定时间

更新的代码:

public class TimePreference extends DialogPreference {
    private Calendar calendar;
    private TimePicker picker = null;

    public TimePreference(Context ctxt) {
        this(ctxt, null);
    }

    public TimePreference(Context ctxt, AttributeSet attrs) {
        this(ctxt, attrs, android.R.attr.dialogPreferenceStyle);
    }

    public TimePreference(Context ctxt, AttributeSet attrs, int defStyle) {
        super(ctxt, attrs, defStyle);

        setPositiveButtonText(R.string.set);
        setNegativeButtonText(R.string.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.getString(index));
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {

        if (restoreValue) {
            if (defaultValue == null) {
                calendar.setTimeInMillis(getPersistedLong(System.currentTimeMillis()));
            } else {
                calendar.setTimeInMillis(Long.parseLong(getPersistedString((String) defaultValue)));
            }
        } else {
            if (defaultValue == null) {
                calendar.setTimeInMillis(System.currentTimeMillis());
            } else {
                calendar.setTimeInMillis(Long.parseLong((String) defaultValue));
            }
        }
        setSummary(getSummary());
    }

    @Override
    public CharSequence getSummary() {
        if (calendar == null) {
            return null;
        }
        return DateFormat.getTimeFormat(getContext()).format(new Date(calendar.getTimeInMillis()));
    }
} 
Run Code Online (Sandbox Code Playgroud)

  • 如果您遇到与其他首选项不同的文本样式问题,请将两个参数构造函数更改为使用内部Android样式而不是"0".更改:`this(context,attrs,android.R.attr.dialogPreferenceStyle);` (4认同)
  • 很好,但是如何以数字格式提供默认值?当我使用android:defaultValue ="3600000"时,defaultValue是一个String,因此首先需要将其解析为Long. (2认同)
  • 一个小问题除了很好的答案.如果`restoreValue == false`那么你必须调用`persistLong(calendar.getTimeInMillis());`作为代码块中的最后一行.否则`PreferenceManager.setDefaultValues(...)`不能按预期工作,'PreferenceManager.getDefaultSharedPreferences(this).getLong(...)`将不会返回默认值,除非在首选项中实际选择了它. (2认同)
  • 你能否实现如何获得这个课程的getMour?谢谢 (2认同)

Sik*_*ora 54

对于那些自定义偏好的实现不那么明显的人(就像它不适合我),你必须将它添加到你preferences.xml或你正在调用的任何东西.

你最终会得到这样的东西:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <EditTextPreference
        android:key="editTextPref_Key"
        android:title="@string/editTextPref_title"/>
    <com.example.myapp.TimePreference
        android:key="timePrefA_Key"
        android:title="@string/timePrefA_title"/>    
    <com.example.myapp.TimePreference
        android:key="timePrefB_Key"
        android:title="@string/timePrefB_title"/>

</PreferenceScreen>
Run Code Online (Sandbox Code Playgroud)

假设你添加的TimePreference到自己的根包:
(src/com/example/myapp/TimePreference.java)

  • 添加了所述的偏好,其功能类似于魅力(感谢您).但是,偏好文本的样式与其他样式不同,即在标题和摘要的概述中,字体看起来更大,并且似乎添加了边距.关于如何改变的任何想法? (3认同)

Dal*_*kar 27

因为Preferences Support Library需要不同的代码.它需要两个自定义类TimePreferenceTimePreferenceDialogFragmentCompat,以及的超越控制onDisplayPreferenceDialog的方法PreferenceFragmentCompat扩展类.


TimePreference.java

package com.test;

import android.content.Context;
import android.content.res.TypedArray;
import android.support.v7.preference.DialogPreference;
import android.util.AttributeSet;

public class TimePreference extends DialogPreference
{
    public int hour = 0;
    public int minute = 0;

    public static int parseHour(String value)
    {
        try
        {
            String[] time = value.split(":");
            return (Integer.parseInt(time[0]));
        }
        catch (Exception e)
        {
            return 0;
        }
    }

    public static int parseMinute(String value)
    {
        try
        {
            String[] time = value.split(":");
            return (Integer.parseInt(time[1]));
        }
        catch (Exception e)
        {
            return 0;
        }
    }

    public static String timeToString(int h, int m)
    {
        return String.format("%02d", h) + ":" + String.format("%02d", m);
    }

    public TimePreference(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index)
    {
        return a.getString(index);
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue)
    {
        String value;
        if (restoreValue)
        {
            if (defaultValue == null) value = getPersistedString("00:00");
            else value = getPersistedString(defaultValue.toString());
        }
        else
        {
            value = defaultValue.toString();
        }

        hour = parseHour(value);
        minute = parseMinute(value);
    }

    public void persistStringValue(String value)
    {
        persistString(value);
    }
}
Run Code Online (Sandbox Code Playgroud)

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();

            String value = TimePreference.timeToString(pref.hour, pref.minute);
            if (pref.callChangeListener(value)) pref.persistStringValue(value);
        }
    }

    @Override
    public Preference findPreference(CharSequence charSequence)
    {
        return getPreference();
    }
}
Run Code Online (Sandbox Code Playgroud)

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.putString("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);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

使用上面的代码时间首选项可以在这样的首选项xml文件中使用

<com.test.TimePreference
    android:key="some_time"
    android:title="Set some time"
    android:defaultValue="12:00"
    android:summary="Set some time"/>
Run Code Online (Sandbox Code Playgroud)


Mat*_*ala 5

CommonsWare的解决方案存在一些问题,我已解决:

  • 更改后无法正确更新字段
  • 分钟值仅保留一位数字,例如10:2而不是10:02
  • 如果您使用PreferenceManager.setDefaultPreferences在您的应用中设置初始默认偏好设置,则它将无法正常工作,因为onSetInitialValue需要将其保留
  • 结果的格式并非针对用户的语言环境而定制(例如,美国使用AM / PM)

这是我的代码,请尽情享受。

public class TimePreference extends DialogPreference {
    private int lastHour=0;
    private int lastMinute=0;
    private TimePicker picker=null;

    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]));
    }

    public TimePreference(Context ctxt, AttributeSet 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());

            String lastMinuteString = String.valueOf(lastMinute);
            String time = String.valueOf(lastHour) + ":" + (lastMinuteString.length() == 1 ? "0" + lastMinuteString : lastMinuteString);

            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;
        String defaultValueStr = (defaultValue != null) ? defaultValue.toString() : "00:00";
        if (restoreValue)
            time = getPersistedString(defaultValueStr);
        else {
            time = defaultValueStr;
            if (shouldPersist())
                persistString(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());
    }

}
Run Code Online (Sandbox Code Playgroud)