Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
*.iml
.gradle
.idea
/local.properties
/.idea/workspace.xml
/.idea/libraries
Expand Down
10 changes: 10 additions & 0 deletions demo/src/main/res/xml/preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@
app:defaultHours="10"
app:defaultMins="0"
app:timeAsSummary="true"/>
<DatePickerPreference
android:key="date_picker_1"
android:title="A date picker"
app:dateAsSummary="true"/>
<DatePickerPreference
android:key="date_picker_2"
android:title="Another date picker"
app:dateFormat="dayMonthYear"
app:defaultYearsAgo="25"
app:dateAsSummary="true"/>
<EditTextPreference
android:defaultValue=""
android:key="edit_text"
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ POM_DEVELOPER_NAME=Phil Bayfield
ANDROID_BUILD_MIN_SDK_VERSION=11
ANDROID_BUILD_TARGET_SDK_VERSION=25
ANDROID_BUILD_TOOLS_VERSION=25.0.2
ANDROID_BUILD_SDK_VERSION=25
ANDROID_BUILD_SDK_VERSION=27
1 change: 1 addition & 0 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:preference-v7:25.3.1'
compile 'com.android.support:preference-v14:25.3.1'
compile 'joda-time:joda-time:2.9.4'
}

def isReleaseBuild() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
package android.support.v7.preference;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.format.DateFormat;
import android.util.AttributeSet;

import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.util.Date;

import me.philio.preferencecompatextended.R;


public class DatePickerPreference extends DialogPreference {

public static final int DATE_FORMAT_INHERIT = 0;
public static final int DATE_FORMAT_MONTH_DAY_YEAR = 1;
public static final int DATE_FORMAT_DAY_MONTH_YEAR = 2;
public static final int DATE_FORMAT_CUSTOM = 3;

private static LocalDate EPOCH = new LocalDate(1970, 1, 1);
private static DateTimeFormatter MONTH_DAY_YEAR_FORAMT = DateTimeFormat.forPattern("MMM d YYYY");
private static DateTimeFormatter DAY_MONTH_YEAR_FORAMT = DateTimeFormat.forPattern("d MMM YYYY");

private boolean dateAsSummary;
private int dateFormat;
private int defaultDayOfMonth;
private int defaultMonthOfYear;
private int defaultYear;
private int defaultYearsAgo;
private int value;
private DateTimeFormatter customFormatter;

public DatePickerPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DatePickerPreference, defStyleAttr, defStyleRes);
dateAsSummary = typedArray.getBoolean(R.styleable.DatePickerPreference_dateAsSummary, true);
defaultYearsAgo = typedArray.getInt(R.styleable.DatePickerPreference_defaultYearsAgo, -1);
defaultYear = typedArray.getInt(R.styleable.DatePickerPreference_defaultYear, -1);
defaultMonthOfYear = typedArray.getInt(R.styleable.DatePickerPreference_defaultMonthOfYear, -1);
defaultDayOfMonth = typedArray.getInt(R.styleable.DatePickerPreference_defaultDayOfMonth, -1);
if (defaultYearsAgo > -1 || defaultYear > -1 && defaultMonthOfYear > -1 && defaultDayOfMonth > -1) {
setDefaultValue(calculateValue(getDefaultDate()));
}
dateFormat = typedArray.getInt(R.styleable.DatePickerPreference_dateFormat, DATE_FORMAT_INHERIT);
if (dateFormat == DATE_FORMAT_CUSTOM) {
String customFormat = typedArray.getString(R.styleable.DatePickerPreference_dateFormatString);
if (customFormat == null || customFormat.isEmpty()) {
throw new IllegalArgumentException("dateFormatString required for custom formats");
}
customFormatter = DateTimeFormat.forPattern(customFormat);
}
typedArray.recycle();
}

public DatePickerPreference(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}

public DatePickerPreference(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.datePickerPreferenceStyle);
}

public DatePickerPreference(Context context) {
this(context, null);
}

public static int calculateValue(LocalDate date) {
return Days.daysBetween(EPOCH, date).getDays();
}

private LocalDate getDate() {
return EPOCH.plusDays(value);
}

public int getYear() {
return getDate().getYear();
}

public int getMonthOfYear() {
return getDate().getMonthOfYear();
}

public int getDayOfMonth() {
return getDate().getDayOfMonth();
}

public void setValue(LocalDate date) {
setValue(calculateValue(date));
}

public void setValue(int value) {
this.value = value;
if (dateAsSummary) {
switch (dateFormat) {
case DATE_FORMAT_MONTH_DAY_YEAR:
setSummary(MONTH_DAY_YEAR_FORAMT.print(getDate()));
break;
case DATE_FORMAT_DAY_MONTH_YEAR:
setSummary(DAY_MONTH_YEAR_FORAMT.print(getDate()));
break;
case DATE_FORMAT_CUSTOM:
setSummary(customFormatter.print(getDate()));
case DATE_FORMAT_INHERIT:
default:
Date date = getDate().toDateTimeAtStartOfDay().toDate();
setSummary(DateFormat.getDateFormat(getContext()).format(date));
break;
}
}
persistInt(value);
}

private LocalDate getDefaultDate() {
if (defaultYear > -1 && defaultYearsAgo > -1) {
throw new IllegalArgumentException("Cannot specify both defaultYear and defaultYearsAgo");
}
if (defaultYearsAgo > -1) {
return LocalDate.now().minusYears(defaultYearsAgo);
} else {
return new LocalDate(defaultYear, defaultMonthOfYear + 1, defaultDayOfMonth);
}
}

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

@Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
setValue(restorePersistedValue ? getPersistedInt(value) : (Integer) defaultValue);
}

@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
if (isPersistent()) {
return superState;
}
final SavedState savedState = new SavedState(superState);
savedState.dateAsSummary = dateAsSummary;
savedState.dateFormat = dateFormat;
savedState.defaultDayOfMonth = defaultDayOfMonth;
savedState.defaultMonthOfYear = defaultMonthOfYear;
savedState.defaultYear = defaultYear;
savedState.defaultYearsAgo = defaultYearsAgo;
savedState.value = value;
return savedState;
}

@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state == null || !state.getClass().equals(SavedState.class)) {
super.onRestoreInstanceState(state);
return;
}
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
dateAsSummary = savedState.dateAsSummary;
dateFormat = savedState.dateFormat;
defaultDayOfMonth = savedState.defaultDayOfMonth;
defaultMonthOfYear = savedState.defaultMonthOfYear;
defaultYear = savedState.defaultYear;
defaultYearsAgo = savedState.defaultYearsAgo;
value = savedState.value;
}

private static class SavedState extends BaseSavedState {

private boolean dateAsSummary;
private int dateFormat;
private int defaultDayOfMonth;
private int defaultMonthOfYear;
private int defaultYear;
private int defaultYearsAgo;
private int value;

@SuppressLint("ParcelClassLoader")
SavedState(Parcel source) {
super(source);
dateAsSummary = (boolean) source.readValue(null);
dateFormat = source.readInt();
defaultDayOfMonth = source.readInt();
defaultMonthOfYear = source.readInt();
defaultYear = source.readInt();
defaultYearsAgo = source.readInt();
value = source.readInt();
}

SavedState(Parcelable superState) {
super(superState);
}

@Override public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeValue(dateAsSummary);
dest.writeInt(dateFormat);
dest.writeInt(defaultDayOfMonth);
dest.writeInt(defaultMonthOfYear);
dest.writeInt(defaultYear);
dest.writeInt(defaultYearsAgo);
dest.writeInt(value);
}

public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
@Override public SavedState createFromParcel(Parcel source) {
return new SavedState(source);
}

@Override public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package android.support.v7.preference;

import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.widget.DatePicker;

import org.joda.time.LocalDate;

/**
* Created by parkeroth on 1/14/18.
*/

public class DatePickerPreferenceDialogFragmentCompat extends PreferenceDialogFragmentCompat implements DatePickerDialog.OnDateSetListener {

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

@Override
public void onDateSet(DatePicker datePicker, int year, int monthOfYear, int dayOfMonth) {
DatePickerPreference preference = (DatePickerPreference) getPreference();
LocalDate date = new LocalDate(year, monthOfYear + 1, dayOfMonth);
if (preference.callChangeListener(DatePickerPreference.calculateValue(date))) {
preference.setValue(date);
}
}

@Override
public void onDialogClosed(boolean positiveResult) {
// Not needed, as handled by onTimeSet
}

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
DatePickerPreference preference = (DatePickerPreference) getPreference();
return new DatePickerDialog(getActivity(), this, preference.getYear(), preference.getMonthOfYear() - 1, preference.getDayOfMonth());
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package me.philio.preferencecompatextended;

import android.support.v4.app.DialogFragment;
import android.support.v7.preference.DatePickerPreference;
import android.support.v7.preference.DatePickerPreferenceDialogFragmentCompat;
import android.support.v7.preference.NumberPickerPreference;
import android.support.v7.preference.NumberPickerPreferenceDialogFragmentCompat;
import android.support.v7.preference.Preference;
Expand Down Expand Up @@ -28,6 +30,14 @@ public abstract class PreferenceFragmentCompat extends android.support.v7.prefer
final DialogFragment fragment = TimePickerPreferenceDialogFragmentCompat.newInstance(preference.getKey());
fragment.setTargetFragment(this, 0);
fragment.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
} else if (preference instanceof DatePickerPreference) {
// Inherit the same behaviour as parent
if (getFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) {
return;
}
final DialogFragment fragment = DatePickerPreferenceDialogFragmentCompat.newInstance(preference.getKey());
fragment.setTargetFragment(this, 0);
fragment.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
} else {
super.onDisplayPreferenceDialog(preference);
}
Expand Down
5 changes: 5 additions & 0 deletions library/src/main/res/values-v14/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<style name="PreferenceTheme" parent="PreferenceThemeOverlay.v14.Material">
<item name="numberPickerPreferenceStyle">@style/Preference.DialogPreference.NumberPickerPreference.Material</item>
<item name="timePickerPreferenceStyle">@style/Preference.DialogPreference.TimePickerPreference.Material</item>
<item name="datePickerPreferenceStyle">@style/Preference.DialogPreference.DatePickerPreference.Material</item>
</style>

<style name="Preference.DialogPreference.NumberPickerPreference.Material">
Expand All @@ -14,4 +15,8 @@
<item name="android:layout">@layout/preference_material</item>
</style>

<style name="Preference.DialogPreference.DatePickerPreference.Material">
<item name="android:layout">@layout/preference_material</item>
</style>

</resources>
17 changes: 17 additions & 0 deletions library/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<attr name="numberPickerPreferenceStyle" format="reference" />
<!-- Default style for TimePickerPreference -->
<attr name="timePickerPreferenceStyle" format="reference" />
<!-- Default style for DatePickerPreference -->
<attr name="datePickerPreferenceStyle" format="reference" />
</declare-styleable>

<declare-styleable name="NumberPickerPreference">
Expand Down Expand Up @@ -38,4 +40,19 @@
<enum name="hours24" value="2" />
</attr>
</declare-styleable>

<declare-styleable name="DatePickerPreference">
<attr name="dateAsSummary" format="boolean" />
<attr name="defaultYearsAgo" format="integer" />
<attr name="defaultYear" format="integer" />
<attr name="defaultMonthOfYear" format="integer" />
<attr name="defaultDayOfMonth" format="integer" />
<attr name="dateFormat" format="enum">
<enum name="inherit" value="0" />
<enum name="dayMonthYear" value="1" />
<enum name="monthDayYear" value="2" />
<enum name="custom" value="3" />
</attr>
<attr name="dateFormatString" format="string" />
</declare-styleable>
</resources>
2 changes: 2 additions & 0 deletions library/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@

<style name="Preference.DialogPreference.TimePickerPreference"/>

<style name="Preference.DialogPreference.DatePickerPreference"/>

</resources>