Ответ 1
Вам необходимо создать пользовательский DialogPreference
, включающий DatePicker
. Вот проект, показывающий пользовательский DialogPreference
на основе пользовательского виджета ColorMixer
.
У меня есть настройки, и я использую комбинацию CheckBoxPreference и EditTextPreference. Я хотел бы заменить один из них DatePickerDialog.
Когда отобразится экран настроек, если вы нажмете на одну из настроек, я бы хотел, чтобы диалоговое окно выбора даты отображалось для пользователя, чтобы выбрать дату и сохранить выбранную дату в настройках. Я видел эту работу в других приложениях, но я не вижу, как это сделать.
У меня есть диалог выбора даты, который работает с обычного вида (в соответствии с учебником), но я хотел бы использовать его с предпочтением.
Вам необходимо создать пользовательский DialogPreference
, включающий DatePicker
. Вот проект, показывающий пользовательский DialogPreference
на основе пользовательского виджета ColorMixer
.
Благодаря @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. Добавьте следующий код в префикс xml, расположенный в "res/xml/yourpreference.xml"
<com.packagename.DatePreference
android:key="keyname"
android:title="Title of the preference"
android:defaultValue="2014-08-01"
android:summary="Summary"/>
Примечание. Измените "имя ключа", "Название предпочтения", "2014-08-01", "сводка" по вашему требованию
3. Если вы хотите поменять vaules по умолчанию с помощью Activity Preference, используйте следующий код.
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;
}
});
}
}
Теперь наслаждайтесь...
Здесь реализация готова к использованию в вашем проекте как lib.
Чтобы указать источник:
Используйте его так же, как любые другие предпочтения в вашем XML-экране PreferenceScreen:
<org.bostonandroid.datepreference.DatePreference
android:key="dob" android:title="@string/dob"
android:defaultValue="1991.01.01" />
В androidx реализация класса DialogPreference разделена на DialogPreference, который обрабатывает постоянство данных, и PreferenceDialogFragmentCompat, который обрабатывает пользовательский интерфейс. Основываясь на ответе Махендрана Саккарая, этого и на примере класса 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"/>
При поиске TimePicker для использования в настройках я нашел этот поток. Я хотел бы указать, что в этом репо также есть проект TimePicker (ссылка).
Единственная проблема заключается в том, что default.jardesc недоступен, но может быть легко выполнен из соответствующего в проекте DatePicker.
Просто простой способ использовать TimePickerFragment в настройках, он на самом деле не отвечает на ваш вопрос, но может помочь некоторым парням.
Пожалуйста, прочитайте это раньше: https://developer.android.com/guide/topics/ui/settings
Из "Обзора" в "Предпочтения... атрибуты", конечно... Oo
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 создайте папку xml в res & файл root_preferences конечно OO
<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);
}
}
Я ничего не задокументировал, потому что после прочтения руководства вы все должны понять ^^