Last active
October 15, 2015 06:04
-
-
Save resengupta/83e70fdf26b7858a85f7 to your computer and use it in GitHub Desktop.
Date picker modified... which allows the user to select month and year (Without the day)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.view.View; | |
import android.widget.NumberPicker; | |
import com.myapp.android.us.R; | |
import java.text.DateFormatSymbols; | |
import java.util.Arrays; | |
import java.util.Calendar; | |
import java.util.Locale; | |
/** | |
* A delegate implementing the simple Date Picker functionality and takes care of the spinner UI. | |
*/ | |
public class SimpleDatePickerDelegate { | |
private static final int DEFAULT_START_YEAR = 1900; | |
private static final int DEFAULT_END_YEAR = 2100; | |
private final NumberPicker mMonthSpinner; | |
private final NumberPicker mYearSpinner; | |
private Calendar mTempDate; | |
private Calendar mCurrentDate; | |
private Calendar mMinDate; | |
private Calendar mMaxDate; | |
private String[] mShortMonths; | |
private int mNumberOfMonths; | |
private Locale mCurrentLocale; | |
private OnDateChangedListener mOnDateChangedListener; | |
public SimpleDatePickerDelegate(View parent) { | |
setCurrentLocale(Locale.getDefault()); | |
NumberPicker.OnValueChangeListener onChangeListener = new NumberPicker | |
.OnValueChangeListener() { | |
public void onValueChange(NumberPicker picker, int oldVal, int newVal) { | |
mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis()); | |
// take care of wrapping of days and months to update greater fields | |
if (picker == mMonthSpinner) { | |
if (oldVal == 11 && newVal == 0) { | |
mTempDate.add(Calendar.MONTH, 1); | |
} else if (oldVal == 0 && newVal == 11) { | |
mTempDate.add(Calendar.MONTH, -1); | |
} else { | |
mTempDate.add(Calendar.MONTH, newVal - oldVal); | |
} | |
} else if (picker == mYearSpinner) { | |
mTempDate.set(Calendar.YEAR, newVal); | |
} else { | |
throw new IllegalArgumentException(); | |
} | |
// now set the date to the adjusted one | |
setDate(mTempDate.get(Calendar.YEAR), mTempDate.get(Calendar.MONTH)); | |
updateSpinners(); | |
notifyDateChanged(); | |
} | |
}; | |
// month | |
mMonthSpinner = (NumberPicker) parent.findViewById(R.id.month); | |
mMonthSpinner.setMinValue(0); | |
mMonthSpinner.setMaxValue(mNumberOfMonths - 1); | |
mMonthSpinner.setDisplayedValues(mShortMonths); | |
mMonthSpinner.setOnLongPressUpdateInterval(200); | |
mMonthSpinner.setOnValueChangedListener(onChangeListener); | |
// year | |
mYearSpinner = (NumberPicker) parent.findViewById(R.id.year); | |
mYearSpinner.setOnLongPressUpdateInterval(100); | |
mYearSpinner.setOnValueChangedListener(onChangeListener); | |
// set the min date giving priority of the minDate over startYear | |
mTempDate.clear(); | |
mTempDate.set(DEFAULT_START_YEAR, 0, 1); | |
setMinDate(mTempDate.getTimeInMillis()); | |
// set the max date giving priority of the maxDate over endYear | |
mTempDate.clear(); | |
mTempDate.set(DEFAULT_END_YEAR, 11, 31); | |
setMaxDate(mTempDate.getTimeInMillis()); | |
// initialize to current date | |
mCurrentDate.setTimeInMillis(System.currentTimeMillis()); | |
init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH), null); | |
} | |
public void init(int year, int monthOfYear, OnDateChangedListener onDateChangedListener) { | |
setDate(year, monthOfYear); | |
updateSpinners(); | |
mOnDateChangedListener = onDateChangedListener; | |
} | |
public void setMinDate(long minDate) { | |
mTempDate.setTimeInMillis(minDate); | |
if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR) | |
&& mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) { | |
return; | |
} | |
mMinDate.setTimeInMillis(minDate); | |
if (mCurrentDate.before(mMinDate)) { | |
mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis()); | |
} | |
updateSpinners(); | |
} | |
public void setMaxDate(long maxDate) { | |
mTempDate.setTimeInMillis(maxDate); | |
if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR) | |
&& mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) { | |
return; | |
} | |
mMaxDate.setTimeInMillis(maxDate); | |
if (mCurrentDate.after(mMaxDate)) { | |
mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis()); | |
} | |
updateSpinners(); | |
} | |
public int getYear() { | |
return mCurrentDate.get(Calendar.YEAR); | |
} | |
public int getMonth() { | |
return mCurrentDate.get(Calendar.MONTH); | |
} | |
/** | |
* Sets the current locale. | |
* | |
* @param locale The current locale. | |
*/ | |
protected void setCurrentLocale(Locale locale) { | |
if (!locale.equals(mCurrentLocale)) { | |
mCurrentLocale = locale; | |
} | |
mTempDate = getCalendarForLocale(mTempDate, locale); | |
mMinDate = getCalendarForLocale(mMinDate, locale); | |
mMaxDate = getCalendarForLocale(mMaxDate, locale); | |
mCurrentDate = getCalendarForLocale(mCurrentDate, locale); | |
mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1; | |
mShortMonths = new DateFormatSymbols().getShortMonths(); | |
if (usingNumericMonths()) { | |
// We're in a locale where a date should either be all-numeric, or all-text. | |
// All-text would require custom NumberPicker formatters for day and year. | |
mShortMonths = new String[mNumberOfMonths]; | |
for (int i = 0; i < mNumberOfMonths; ++i) { | |
mShortMonths[i] = String.format("%d", i + 1); | |
} | |
} | |
} | |
private void setDate(int year, int month) { | |
mCurrentDate.set(Calendar.YEAR, year); | |
mCurrentDate.set(Calendar.MONTH, month); | |
if (mCurrentDate.before(mMinDate)) { | |
mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis()); | |
} else if (mCurrentDate.after(mMaxDate)) { | |
mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis()); | |
} | |
} | |
private void updateSpinners() { | |
// set the spinner ranges respecting the min and max dates | |
if (mCurrentDate.equals(mMinDate)) { | |
mMonthSpinner.setDisplayedValues(null); | |
mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH)); | |
mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH)); | |
mMonthSpinner.setWrapSelectorWheel(false); | |
} else if (mCurrentDate.equals(mMaxDate)) { | |
mMonthSpinner.setDisplayedValues(null); | |
mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH)); | |
mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH)); | |
mMonthSpinner.setWrapSelectorWheel(false); | |
} else { | |
mMonthSpinner.setDisplayedValues(null); | |
mMonthSpinner.setMinValue(0); | |
mMonthSpinner.setMaxValue(11); | |
mMonthSpinner.setWrapSelectorWheel(true); | |
} | |
// make sure the month names are a zero based array | |
// with the months in the month spinner | |
String[] displayedValues = Arrays.copyOfRange( | |
mShortMonths, mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1); | |
mMonthSpinner.setDisplayedValues(displayedValues); | |
// year spinner range does not change based on the current date | |
mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR)); | |
mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR)); | |
mYearSpinner.setWrapSelectorWheel(false); | |
// set the spinner values | |
mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR)); | |
mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH)); | |
} | |
private boolean usingNumericMonths() { | |
return Character.isDigit(mShortMonths[Calendar.JANUARY].charAt(0)); | |
} | |
/** | |
* Gets a calendar for locale bootstrapped with the value of a given calendar. | |
* | |
* @param oldCalendar The old calendar. | |
* @param locale The locale. | |
*/ | |
private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) { | |
if (oldCalendar == null) { | |
return Calendar.getInstance(locale); | |
} else { | |
long currentTimeMillis = oldCalendar.getTimeInMillis(); | |
Calendar newCalendar = Calendar.getInstance(locale); | |
newCalendar.setTimeInMillis(currentTimeMillis); | |
return newCalendar; | |
} | |
} | |
/** | |
* Notifies the listener, if such, for a change in the selected date. | |
*/ | |
private void notifyDateChanged() { | |
if (mOnDateChangedListener != null) { | |
mOnDateChangedListener.onDateChanged(getYear(), getMonth()); | |
} | |
} | |
/** | |
* The callback used to indicate the user changed the date. | |
*/ | |
public interface OnDateChangedListener { | |
/** | |
* Called upon a date change. | |
* | |
* @param year The year that was set. | |
* @param monthOfYear The month that was set (0-11) for compatibility with {@link | |
* java.util.Calendar}. | |
*/ | |
void onDateChanged(int year, int monthOfYear); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment