如何使用DatePickerDialog作为首选项

时间:2010-11-18 14:56:37

标签: android

我有偏好工作,我正在使用CheckBoxPreference和EditTextPreference的组合。我想用DatePickerDialog替换其中一个。

当我的设置屏幕显示时,如果您单击其中一个首选项,我希望弹出日期选择器对话框以供用户选择日期,并将选择的日期保存在首选项中。我在其他应用程序中看到过这项工作,但我看不出怎么做。

我在常规视图中使用日期选择器对话框(根据教程),但我想从偏好中使用它。

7 个答案:

答案 0 :(得分:20)

感谢@commonsware。我按照他的项目创建了一个日期选择器首选项对话框。所以它会帮助别人。

按照步骤在偏好设置窗口中打开日期选择器。

1。为日期选择器创建自定义对话框首选项。

package com.packagename;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import android.content.Context;
import android.content.res.TypedArray;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.DatePicker;

public class DatePreference extends DialogPreference {
    private int lastDate = 0;
    private int lastMonth = 0;
    private int lastYear = 0;
    private String dateval;
    private CharSequence mSummary;
    private DatePicker picker = null;
    public static int getYear(String dateval) {
        String[] pieces = dateval.split("-");
        return (Integer.parseInt(pieces[0]));
    }

    public static int getMonth(String dateval) {
        String[] pieces = dateval.split("-");
        return (Integer.parseInt(pieces[1]));
    }

    public static int getDate(String dateval) {
        String[] pieces = dateval.split("-");
        return (Integer.parseInt(pieces[2]));
    }

    public DatePreference(Context ctxt, AttributeSet attrs) {
        super(ctxt, attrs);

        setPositiveButtonText("Set");
        setNegativeButtonText("Cancel");
    }

    @Override
    protected View onCreateDialogView() {
        picker = new DatePicker(getContext());

        // setCalendarViewShown(false) attribute is only available from API level 11
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            picker.setCalendarViewShown(false);
        }

        return (picker);
    }

    @Override
    protected void onBindDialogView(View v) {
        super.onBindDialogView(v);

        picker.updateDate(lastYear, lastMonth + 1, lastDate);
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);

        if (positiveResult) {
            lastYear = picker.getYear();
            lastMonth = picker.getMonth();
            lastDate = picker.getDayOfMonth();

            String dateval = String.valueOf(lastYear) + "-"
                    + String.valueOf(lastMonth) + "-"
                    + String.valueOf(lastDate);

            if (callChangeListener(dateval)) {
                persistString(dateval);
            }
        }
    }

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

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
        dateval = null;

        if (restoreValue) {
            if (defaultValue == null) {
                Calendar cal = Calendar.getInstance();
                SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd");
                String formatted = format1.format(cal.getTime());
                dateval = getPersistedString(formatted);
            } else {
                dateval = getPersistedString(defaultValue.toString());
            }
        } else {
            dateval = defaultValue.toString();
        }
        lastYear = getYear(dateval);
        lastMonth = getMonth(dateval);
        lastDate = getDate(dateval);
    }

    public void setText(String text) {
        final boolean wasBlocking = shouldDisableDependents();

        dateval = text;

        persistString(text);

        final boolean isBlocking = shouldDisableDependents();
        if (isBlocking != wasBlocking) {
            notifyDependencyChange(isBlocking);
        }
    }

    public String getText() {
        return dateval;
    }

    public CharSequence getSummary() {
        return mSummary;
    }

    public void setSummary(CharSequence summary) {
        if (summary == null && mSummary != null || summary != null
                && !summary.equals(mSummary)) {
            mSummary = summary;
            notifyChanged();
        }
    }
}

2。在位于“res / xml / yourpreference.xml”

中的首选项xml中添加以下代码
<com.packagename.DatePreference 
android:key="keyname" 
android:title="Title of the preference" 
android:defaultValue="2014-08-01" 
android:summary="Summary"/>

注意:根据您的要求更改“keyname”,“首选项标题”,“2014-08-01”,“摘要”

3。如果要通过“首选项活动”更改默认值,请使用以下代码。

package com.packagename;

import android.os.Bundle;
import com.packagename.DatePreference;

public class CustomPreference extends PreferenceActivity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    addPreferencesFromResource(R.xml.preferences);

    final DatePreference dp= (DatePreference) findPreference("keyname");
    dp.setText("2014-08-02");
    dp.setSummary("2014-08-02");
    dp.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference,Object newValue) {
            //your code to change values.
            dp.setSummary((String) newValue);
            return true;
        }
    });

  }
}

现在享受......

答案 1 :(得分:9)

Here是一个可以在项目中用作lib的实现。

引用来源:

  

使用它就像PreferenceScreen XML中的任何其他首选项一样:

<org.bostonandroid.datepreference.DatePreference
      android:key="dob" android:title="@string/dob"
      android:defaultValue="1991.01.01" />

答案 2 :(得分:5)

您需要创建一个包含DialogPreference的自定义DatePickerHere is a project根据自定义DialogPreference小部件显示自定义ColorMixer

答案 3 :(得分:3)

在androidx中,DialogPreference类的实现分为用于处理数据持久性的DialogPreference和用于处理UI的PreferenceDialogFragmentCompat。可以在Mahendran Sakkarai's answerthis one之上并以EditTextPreference类为基础进行构建,就像这样。

1。 DatePreference类。

package com.example.util.timereminder.ui.prefs.custom;

import android.content.Context;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;

import com.example.util.timereminder.R;

import androidx.preference.DialogPreference;

/**
 * A dialog preference that shown calendar in the dialog.
 *
 * Saves a string value.
 */
public class DatePreference extends DialogPreference {

    private String mDateValue;

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

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

    @Override
    protected void onSetInitialValue(Object defaultValue) {
        setDate(getPersistedString((String) defaultValue));
    }

    /**
     * Gets the date as a string from the current data storage.
     *
     * @return string representation of the date.
     */
    public String getDate() {
        return mDateValue;
    }

    /**
     * Saves the date as a string in the current data storage.
     *
     * @param text string representation of the date to save.
     */
    public void setDate(String text) {
        final boolean wasBlocking = shouldDisableDependents();

        mDateValue = text;

        persistString(text);

        final boolean isBlocking = shouldDisableDependents();
        if (isBlocking != wasBlocking) {
            notifyDependencyChange(isBlocking);
        }

        notifyChanged();
    }

    /**
     * A simple {@link androidx.preference.Preference.SummaryProvider} implementation for an
     * {@link DatePreference}. If no value has been set, the summary displayed will be 'Not
     * set', otherwise the summary displayed will be the value set for this preference.
     */
    public static final class SimpleSummaryProvider implements SummaryProvider<DatePreference> {

        private static SimpleSummaryProvider sSimpleSummaryProvider;

        private SimpleSummaryProvider() {}

        /**
         * Retrieve a singleton instance of this simple
         * {@link androidx.preference.Preference.SummaryProvider} implementation.
         *
         * @return a singleton instance of this simple
         * {@link androidx.preference.Preference.SummaryProvider} implementation
         */
        public static SimpleSummaryProvider getInstance() {
            if (sSimpleSummaryProvider == null) {
                sSimpleSummaryProvider = new SimpleSummaryProvider();
            }
            return sSimpleSummaryProvider;
        }

        @Override
        public CharSequence provideSummary(DatePreference preference) {
            if (TextUtils.isEmpty(preference.getDate())) {
                return (preference.getContext().getString(R.string.not_set));
            } else {
                return preference.getDate();
            }
        }
    }
}

2。 DatePreferenceDialogFragment类。

package com.example.util.timereminder.ui.prefs.custom;

import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.DatePicker;

import java.text.SimpleDateFormat;
import java.util.Calendar;

import androidx.preference.PreferenceDialogFragmentCompat;

public class DatePreferenceDialogFragment extends PreferenceDialogFragmentCompat {

    private int mLastYear;
    private int mLastMonth;
    private int mLastDay;
    private DatePicker mDatePicker;

    public static DatePreferenceDialogFragment newInstance(String key) {
        final DatePreferenceDialogFragment
                fragment = new DatePreferenceDialogFragment();
        final Bundle b = new Bundle(1);
        b.putString(ARG_KEY, key);
        fragment.setArguments(b);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        String dateValue = getDatePreference().getDate();

        if (dateValue == null || dateValue.isEmpty()) {
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            dateValue = df.format(calendar.getTime());
        }

        mLastYear = getYear(dateValue);
        mLastMonth = getMonth(dateValue);
        mLastDay = getDay(dateValue);
    }

    @Override
    protected View onCreateDialogView(Context context) {
        mDatePicker = new DatePicker(getContext());
        // Show spinner dialog for old APIs.
        mDatePicker.setCalendarViewShown(false);

        return mDatePicker;
    }

    @Override
    protected void onBindDialogView(View view) {
        super.onBindDialogView(view);

        mDatePicker.updateDate(mLastYear, mLastMonth - 1, mLastDay);
    }

    @Override
    public void onDialogClosed(boolean positiveResult) {
        if (positiveResult) {
            mLastYear = mDatePicker.getYear();
            mLastMonth = mDatePicker.getMonth() + 1;
            mLastDay = mDatePicker.getDayOfMonth();

            String dateVal = String.valueOf(mLastYear) + "-"
                    + String.valueOf(mLastMonth) + "-"
                    + String.valueOf(mLastDay);

            final DatePreference preference = getDatePreference();
            if (preference.callChangeListener(dateVal)) {
                preference.setDate(dateVal);
            }
        }
    }

    private DatePreference getDatePreference() {
        return (DatePreference) getPreference();
    }

    private int getYear(String dateString) {
        String[] datePieces = dateString.split("-");
        return (Integer.parseInt(datePieces[0]));
    }

    private int getMonth(String dateString) {
        String[] datePieces = dateString.split("-");
        return (Integer.parseInt(datePieces[1]));
    }

    private int getDay(String dateString) {
        String[] datePieces = dateString.split("-");
        return (Integer.parseInt(datePieces[2]));
    }
}

3。在PreferenceFragment中。

package com.example.util.timereminder.ui.prefs;

import android.os.Bundle;

import com.example.util.timereminder.R;
import com.example.util.timereminder.ui.prefs.custom.DatePreferenceDialogFragment;
import com.example.util.timereminder.ui.prefs.custom.DatePreference;

import androidx.fragment.app.DialogFragment;
import androidx.preference.EditTextPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceGroup;

/**
 * Displays different preferences.
 */
public class PrefsFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        addPreferencesFromResource(R.xml.preferences);

        initSummary(getPreferenceScreen());
    }

    @Override
    public void onDisplayPreferenceDialog(Preference preference) {
        if (preference instanceof DatePreference) {
            final DialogFragment f;
            f = DatePreferenceDialogFragment.newInstance(preference.getKey());
            f.setTargetFragment(this, 0);
            f.show(getFragmentManager(), null);
        } else {
            super.onDisplayPreferenceDialog(preference);
        }
    }

    /**
     * Walks through all preferences.
     *
     * @param p The starting preference to search from.
     */
    private void initSummary(Preference p) {
        if (p instanceof PreferenceGroup) {
            PreferenceGroup pGrp = (PreferenceGroup) p;
            for (int i = 0; i < pGrp.getPreferenceCount(); i++) {
                initSummary(pGrp.getPreference(i));
            }
        } else {
            setPreferenceSummary(p);
        }
    }

    /**
     * Sets up summary providers for the preferences.
     *
     * @param p The preference to set up summary provider.
     */
    private void setPreferenceSummary(Preference p) {
        // No need to set up preference summaries for checkbox preferences because
        // they can be set up in xml using summaryOff and summary On
        if (p instanceof DatePreference) {
            p.setSummaryProvider(DatePreference.SimpleSummaryProvider.getInstance());
        } else if (p instanceof EditTextPreference) {
            p.setSummaryProvider(EditTextPreference.SimpleSummaryProvider.getInstance());
        }
    }
}

4。并且在preference.xml中。如果遗漏了默认值,则日历会在当前日期打开。

<com.example.util.timereminder.ui.prefs.custom.DatePreference
    android:title="@string/prefs_date_of_birth_title"
    android:key="@string/prefs_date_of_birth_key"
    android:defaultValue="2014-08-01"
    app:iconSpaceReserved="false"/>

答案 4 :(得分:1)

这是在设置中使用TimePickerFragment的一种简单方法,它并不能真正回答您的问题,但可以帮助某些人。
请先阅读以下内容:https://developer.android.com/guide/topics/ui/settings
从“概述”到“首选项...属性”,当然...噢

controller.fragments

public class TimePickerFragment extends DialogFragment {

    private TimePickerDialog.OnTimeSetListener onTimeSetListener;
    private int hours;
    private int minutes;

    TimePickerFragment(TimePickerDialog.OnTimeSetListener onTimeSetListener, int hours, int minutes) {
        this.onTimeSetListener = onTimeSetListener;
        this.hours = hours;
        this.minutes = minutes;
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        return new TimePickerDialog(getActivity(), R.style.dateTimePicker,
                onTimeSetListener, hours, minutes, DateFormat.is24HourFormat(getActivity()));
    }
}

res.values.style

<style name="dateTimePicker" parent="ThemeOverlay.MaterialComponents.Dialog">
        <item name="colorAccent">@color/colorPrimary</item>
</style>

res.xml.root_preferences.xml 在res中创建xml文件夹和Oo文件的root_preferences

<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
    <PreferenceCategory app:title="Set time">

        <Preference
            app:key="set_time"
            app:title="Set time"
            app:summary="bla bla bla"/>

    </PreferenceCategory>
</PreferenceScreen>

controller.activities.SettingsActivity

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.settings_activity);
    getSupportFragmentManager()
            .beginTransaction()
            .add(R.id.settings, new SettingsFragment())
            .commit();
}

controller.fragments.SettingsFragment

public class SettingsFragment extends PreferenceFragmentCompat implements TimePickerDialog.OnTimeSetListener {


         private Preference setTime;

         public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
            setPreferencesFromResource(R.xml.root_preferences, rootKey);
            getPreference();
            configListener();
        }

        private void getPreference() {
            setTime = findPreference("set_time");
        }

        private void configListener() {
            if (setTime != null){
                setTime.setOnPreferenceClickListener(preference -> {
                    showTimeDialog(preference);
                    return true;
                });
            }
        }

        private void showTimeDialog(Preference preference) {
            String value = preference.getSharedPreferences().getString("set_time", "12:00");
            String[] time = value.split(":");
            int hours = Integer.parseInt(time[0]);
            int minutes = Integer.parseInt(time[1]);
            if (getFragmentManager() != null) {
            new TimePickerFragment(this, hours, minutes)
                .show(getFragmentManager(), getString(R.string.tag_time_picker));
            }
        }

        @Override
        public void onTimeSet(TimePicker timePicker, int h, int m) {
            String time = format(Locale.getDefault(),"%02d", h) + ":" + format(Locale.getDefault(), "%02d", m);
            SharedPreferences sharedPreferences =
                    PreferenceManager.getDefaultSharedPreferences(context);
            sharedPreferences.edit().putString("set_time", time).apply();
            // if you use setOnPreferenceChangeListener on it, use setTime.callChangeListener(time);
        }
}

我什么也没写,因为在阅读了指南之后,你们都应该了解^^

答案 5 :(得分:0)

在寻找在偏好中使用的TimePicker时,我发现了这个帖子。 我想指出该回购中还有一个TimePicker项目(link)。

唯一的问题是default.jardesc不可用,但可以很容易地从DatePicker项目中相应的那个。

答案 6 :(得分:0)

我将展示我的代码以从 SettingsActivity.java 中选择和保存日期,应用在 Preferences 片段类中。适用于所有设备,从 API 级别 16 到 API 级别 29。

首先,将此标记放在“root_preferences.xml”文件中的 <PreferenceScreen> 之间或 <PreferenceCategory> 标记之间(如果有):

    <Preference
        app:key="date_pref"
        app:title="Set date"
        app:useSimpleSummaryProvider="true" />

最后,将此代码放在 SettingsActivity.java 文件中,在名为 SettingsFragment 的子类中:

public static class SettingsFragment extends PreferenceFragmentCompat {
    SharedPreferences settings;

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        settings = requireContext().getSharedPreferences(requireContext().getPackageName() + "_preferences", Context.MODE_PRIVATE);
        setPreferencesFromResource(R.xml.root_preferences, rootKey);
            
        Preference date_pref = getPreferenceManager().findPreference("date_pref");
        assert date_pref != null;
        date_pref.setSummary(settings.getString("date_pref", ""));
        date_pref.setOnPreferenceClickListener(datePicker);
    }
    
    Preference.OnPreferenceClickListener datePicker = new Preference.OnPreferenceClickListener() {
        @Override
        public boolean onPreferenceClick(Preference preference) {
            Calendar cal = Calendar.getInstance();
            int cal_month = cal.get(Calendar.MONTH);
            int cal_day = cal.get(Calendar.DAY_OF_MONTH);
            int cal_year = cal.get(Calendar.YEAR);
            DatePickerDialog datePickerDialog = new DatePickerDialog(requireActivity(), new DatePickerDialog.OnDateSetListener() {
                @Override
                public void onDateSet(DatePicker view, int year, int month, int day) {
                    String datePicked = day + "." + month + "." + year;
                    settings.edit().putString("date_pref", datePicked).apply();
                    preference.setSummary(datePicked);
                }
            }, cal_year, cal_month, cal_day);
            datePickerDialog.show();
            return false;
        }
    };
}

不要忘记这个导入:

import android.app.DatePickerDialog;
import android.content.Context;
import android.content.SharedPreferences;
import java.util.Calendar;

别忘了Vote Up我的帖子:)