Merge "Fix min/max date range in DatePicker calendar mode" into lmp-mr1-dev
automerge: 3847552
* commit '384755230c52f0951820ba496f300959dcc84ead':
Fix min/max date range in DatePicker calendar mode
This commit is contained in:
@@ -21,13 +21,11 @@ import android.content.res.ColorStateList;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.format.DateFormat;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.SparseArray;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -186,6 +184,8 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i
|
||||
headerSelectedTextColor));
|
||||
|
||||
mDayPickerView = new DayPickerView(mContext, this);
|
||||
mDayPickerView.setRange(mMinDate, mMaxDate);
|
||||
|
||||
mYearPickerView = new YearPickerView(mContext);
|
||||
mYearPickerView.init(this);
|
||||
|
||||
@@ -411,7 +411,8 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i
|
||||
updateDisplay(false);
|
||||
}
|
||||
mMinDate.setTimeInMillis(minDate);
|
||||
mDayPickerView.goTo(getSelectedDay(), false, true, true);
|
||||
mDayPickerView.setRange(mMinDate, mMaxDate);
|
||||
mYearPickerView.setRange(mMinDate, mMaxDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -432,7 +433,8 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i
|
||||
updateDisplay(false);
|
||||
}
|
||||
mMaxDate.setTimeInMillis(maxDate);
|
||||
mDayPickerView.goTo(getSelectedDay(), false, true, true);
|
||||
mDayPickerView.setRange(mMinDate, mMaxDate);
|
||||
mYearPickerView.setRange(mMinDate, mMaxDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -453,36 +455,6 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i
|
||||
return mCurrentDate.getFirstDayOfWeek();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinYear() {
|
||||
return mMinDate.get(Calendar.YEAR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxYear() {
|
||||
return mMaxDate.get(Calendar.YEAR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinMonth() {
|
||||
return mMinDate.get(Calendar.MONTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxMonth() {
|
||||
return mMaxDate.get(Calendar.MONTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinDay() {
|
||||
return mMinDate.get(Calendar.DAY_OF_MONTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxDay() {
|
||||
return mMaxDate.get(Calendar.DAY_OF_MONTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
mMonthAndDayLayout.setEnabled(enabled);
|
||||
|
||||
@@ -38,20 +38,5 @@ interface DatePickerController {
|
||||
void setFirstDayOfWeek(int firstDayOfWeek);
|
||||
int getFirstDayOfWeek();
|
||||
|
||||
int getMinYear();
|
||||
int getMaxYear();
|
||||
|
||||
int getMinMonth();
|
||||
int getMaxMonth();
|
||||
|
||||
int getMinDay();
|
||||
int getMaxDay();
|
||||
|
||||
void setMinDate(long minDate);
|
||||
Calendar getMinDate();
|
||||
|
||||
void setMaxDate(long maxDate);
|
||||
Calendar getMaxDate();
|
||||
|
||||
void tryVibrate();
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.MathUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
@@ -57,9 +58,11 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener,
|
||||
|
||||
// highlighted time
|
||||
private Calendar mSelectedDay = Calendar.getInstance();
|
||||
private SimpleMonthAdapter mAdapter;
|
||||
|
||||
private Calendar mTempDay = Calendar.getInstance();
|
||||
private Calendar mMinDate = Calendar.getInstance();
|
||||
private Calendar mMaxDate = Calendar.getInstance();
|
||||
|
||||
private SimpleMonthAdapter mAdapter;
|
||||
|
||||
// which month should be displayed/highlighted [0-11]
|
||||
private int mCurrentMonthDisplayed;
|
||||
@@ -75,6 +78,7 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener,
|
||||
|
||||
public DayPickerView(Context context, DatePickerController controller) {
|
||||
super(context);
|
||||
|
||||
init();
|
||||
setController(controller);
|
||||
}
|
||||
@@ -97,6 +101,41 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener,
|
||||
setUpListView();
|
||||
}
|
||||
|
||||
public void setRange(Calendar minDate, Calendar maxDate) {
|
||||
mMinDate.setTimeInMillis(minDate.getTimeInMillis());
|
||||
mMaxDate.setTimeInMillis(maxDate.getTimeInMillis());
|
||||
|
||||
mAdapter.setRange(mMinDate, mMaxDate);
|
||||
|
||||
if (constrainCalendar(mSelectedDay, mMinDate, mMaxDate)) {
|
||||
goTo(mSelectedDay, false, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constrains the supplied calendar to stay within the min and max
|
||||
* calendars, returning <code>true</code> if the supplied calendar
|
||||
* was modified.
|
||||
*
|
||||
* @param value The calendar to constrain
|
||||
* @param min The minimum calendar
|
||||
* @param max The maximum calendar
|
||||
* @return True if <code>value</code> was modified
|
||||
*/
|
||||
private boolean constrainCalendar(Calendar value, Calendar min, Calendar max) {
|
||||
if (value.compareTo(min) < 0) {
|
||||
value.setTimeInMillis(min.getTimeInMillis());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value.compareTo(max) > 0) {
|
||||
value.setTimeInMillis(max.getTimeInMillis());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onChange() {
|
||||
setUpAdapter();
|
||||
setAdapter(mAdapter);
|
||||
@@ -137,23 +176,16 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener,
|
||||
setFriction(ViewConfiguration.getScrollFriction() * mFriction);
|
||||
}
|
||||
|
||||
private int getDiffMonths(Calendar start, Calendar end){
|
||||
private int getDiffMonths(Calendar start, Calendar end) {
|
||||
final int diffYears = end.get(Calendar.YEAR) - start.get(Calendar.YEAR);
|
||||
final int diffMonths = end.get(Calendar.MONTH) - start.get(Calendar.MONTH) + 12 * diffYears;
|
||||
return diffMonths;
|
||||
}
|
||||
|
||||
private int getPositionFromDay(Calendar day) {
|
||||
final int diffMonthMax = getDiffMonths(mController.getMinDate(), mController.getMaxDate());
|
||||
int diffMonth = getDiffMonths(mController.getMinDate(), day);
|
||||
|
||||
if (diffMonth < 0 ) {
|
||||
diffMonth = 0;
|
||||
} else if (diffMonth > diffMonthMax) {
|
||||
diffMonth = diffMonthMax;
|
||||
}
|
||||
|
||||
return diffMonth;
|
||||
final int diffMonthMax = getDiffMonths(mMinDate, mMaxDate);
|
||||
final int diffMonth = getDiffMonths(mMinDate, day);
|
||||
return MathUtils.constrain(diffMonth, 0, diffMonthMax);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,8 +203,7 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener,
|
||||
* visible
|
||||
* @return Whether or not the view animated to the new location
|
||||
*/
|
||||
public boolean goTo(Calendar day, boolean animate, boolean setSelected,
|
||||
boolean forceScroll) {
|
||||
public boolean goTo(Calendar day, boolean animate, boolean setSelected, boolean forceScroll) {
|
||||
|
||||
// Set the selected day
|
||||
if (setSelected) {
|
||||
@@ -464,10 +495,10 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener,
|
||||
}
|
||||
|
||||
// Figure out what month is showing.
|
||||
int firstVisiblePosition = getFirstVisiblePosition();
|
||||
int month = firstVisiblePosition % 12;
|
||||
int year = firstVisiblePosition / 12 + mController.getMinYear();
|
||||
Calendar day = Calendar.getInstance();
|
||||
final int firstVisiblePosition = getFirstVisiblePosition();
|
||||
final int month = firstVisiblePosition % 12;
|
||||
final int year = firstVisiblePosition / 12 + mMinDate.get(Calendar.YEAR);
|
||||
final Calendar day = Calendar.getInstance();
|
||||
day.set(year, month, 1);
|
||||
|
||||
// Scroll either forward or backward one month.
|
||||
|
||||
@@ -28,21 +28,30 @@ import java.util.HashMap;
|
||||
* An adapter for a list of {@link android.widget.SimpleMonthView} items.
|
||||
*/
|
||||
class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayClickListener {
|
||||
private static final String TAG = "SimpleMonthAdapter";
|
||||
private final Calendar mMinDate = Calendar.getInstance();
|
||||
private final Calendar mMaxDate = Calendar.getInstance();
|
||||
|
||||
private final Context mContext;
|
||||
private final DatePickerController mController;
|
||||
private Calendar mSelectedDay;
|
||||
|
||||
private Calendar mSelectedDay;
|
||||
private ColorStateList mCalendarTextColors;
|
||||
|
||||
public SimpleMonthAdapter(Context context, DatePickerController controller) {
|
||||
mContext = context;
|
||||
mController = controller;
|
||||
|
||||
init();
|
||||
setSelectedDay(mController.getSelectedDay());
|
||||
}
|
||||
|
||||
public void setRange(Calendar min, Calendar max) {
|
||||
mMinDate.setTimeInMillis(min.getTimeInMillis());
|
||||
mMaxDate.setTimeInMillis(max.getTimeInMillis());
|
||||
|
||||
notifyDataSetInvalidated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the selected day and related parameters.
|
||||
*
|
||||
@@ -68,10 +77,9 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
final int diffYear = mController.getMaxYear() - mController.getMinYear();
|
||||
final int diffMonth = 1 + mController.getMaxMonth() - mController.getMinMonth()
|
||||
+ 12 * diffYear;
|
||||
return diffMonth;
|
||||
final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
|
||||
final int diffMonth = mMaxDate.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH);
|
||||
return diffMonth + 12 * diffYear + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,36 +100,34 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
SimpleMonthView v;
|
||||
HashMap<String, Integer> drawingParams = null;
|
||||
final SimpleMonthView v;
|
||||
if (convertView != null) {
|
||||
v = (SimpleMonthView) convertView;
|
||||
// We store the drawing parameters in the view so it can be recycled
|
||||
drawingParams = (HashMap<String, Integer>) v.getTag();
|
||||
} else {
|
||||
v = new SimpleMonthView(mContext);
|
||||
|
||||
// Set up the new view
|
||||
AbsListView.LayoutParams params = new AbsListView.LayoutParams(
|
||||
final AbsListView.LayoutParams params = new AbsListView.LayoutParams(
|
||||
AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.MATCH_PARENT);
|
||||
v.setLayoutParams(params);
|
||||
v.setClickable(true);
|
||||
v.setOnDayClickListener(this);
|
||||
|
||||
if (mCalendarTextColors != null) {
|
||||
v.setTextColor(mCalendarTextColors);
|
||||
}
|
||||
}
|
||||
if (drawingParams == null) {
|
||||
drawingParams = new HashMap<String, Integer>();
|
||||
} else {
|
||||
drawingParams.clear();
|
||||
}
|
||||
final int currentMonth = position + mController.getMinMonth();
|
||||
final int month = currentMonth % 12;
|
||||
final int year = currentMonth / 12 + mController.getMinYear();
|
||||
|
||||
int selectedDay = -1;
|
||||
final int minMonth = mMinDate.get(Calendar.MONTH);
|
||||
final int minYear = mMinDate.get(Calendar.YEAR);
|
||||
final int currentMonth = position + minMonth;
|
||||
final int month = currentMonth % 12;
|
||||
final int year = currentMonth / 12 + minYear;
|
||||
final int selectedDay;
|
||||
if (isSelectedDayInMonth(year, month)) {
|
||||
selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH);
|
||||
} else {
|
||||
selectedDay = -1;
|
||||
}
|
||||
|
||||
// Invokes requestLayout() to ensure that the recycled view is set with the appropriate
|
||||
@@ -129,15 +135,15 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli
|
||||
v.reuse();
|
||||
|
||||
final int enabledDayRangeStart;
|
||||
if (mController.getMinMonth() == month && mController.getMinYear() == year) {
|
||||
enabledDayRangeStart = mController.getMinDay();
|
||||
if (minMonth == month && minYear == year) {
|
||||
enabledDayRangeStart = mMinDate.get(Calendar.DAY_OF_MONTH);
|
||||
} else {
|
||||
enabledDayRangeStart = 1;
|
||||
}
|
||||
|
||||
final int enabledDayRangeEnd;
|
||||
if (mController.getMaxMonth() == month && mController.getMaxYear() == year) {
|
||||
enabledDayRangeEnd = mController.getMaxDay();
|
||||
if (mMaxDate.get(Calendar.MONTH) == month && mMaxDate.get(Calendar.YEAR) == year) {
|
||||
enabledDayRangeEnd = mMaxDate.get(Calendar.DAY_OF_MONTH);
|
||||
} else {
|
||||
enabledDayRangeEnd = 31;
|
||||
}
|
||||
@@ -155,20 +161,25 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli
|
||||
|
||||
@Override
|
||||
public void onDayClick(SimpleMonthView view, Calendar day) {
|
||||
if (day != null) {
|
||||
onDayTapped(day);
|
||||
if (day != null && isCalendarInRange(day)) {
|
||||
onDaySelected(day);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCalendarInRange(Calendar value) {
|
||||
return value.compareTo(mMinDate) >= 0 && value.compareTo(mMaxDate) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maintains the same hour/min/sec but moves the day to the tapped day.
|
||||
*
|
||||
* @param day The day that was tapped
|
||||
*/
|
||||
protected void onDayTapped(Calendar day) {
|
||||
private void onDaySelected(Calendar day) {
|
||||
mController.tryVibrate();
|
||||
mController.onDayOfMonthSelected(day.get(Calendar.YEAR), day.get(Calendar.MONTH),
|
||||
day.get(Calendar.DAY_OF_MONTH));
|
||||
|
||||
setSelectedDay(day);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,8 +52,6 @@ import java.util.Locale;
|
||||
* within the specified month.
|
||||
*/
|
||||
class SimpleMonthView extends View {
|
||||
private static final String TAG = "SimpleMonthView";
|
||||
|
||||
private static final int DEFAULT_HEIGHT = 32;
|
||||
private static final int MIN_HEIGHT = 10;
|
||||
|
||||
@@ -67,15 +65,15 @@ class SimpleMonthView extends View {
|
||||
|
||||
private static final int DAY_SEPARATOR_WIDTH = 1;
|
||||
|
||||
private final Formatter mFormatter;
|
||||
private final StringBuilder mStringBuilder;
|
||||
|
||||
private final int mMiniDayNumberTextSize;
|
||||
private final int mMonthLabelTextSize;
|
||||
private final int mMonthDayLabelTextSize;
|
||||
private final int mMonthHeaderSize;
|
||||
private final int mDaySelectedCircleSize;
|
||||
|
||||
// used for scaling to the device density
|
||||
private static float mScale = 0;
|
||||
|
||||
/** Single-letter (when available) formatter for the day of week label. */
|
||||
private SimpleDateFormat mDayFormatter = new SimpleDateFormat("EEEEE", Locale.getDefault());
|
||||
|
||||
@@ -92,9 +90,6 @@ class SimpleMonthView extends View {
|
||||
private Paint mMonthTitlePaint;
|
||||
private Paint mMonthDayLabelPaint;
|
||||
|
||||
private final Formatter mFormatter;
|
||||
private final StringBuilder mStringBuilder;
|
||||
|
||||
private int mMonth;
|
||||
private int mYear;
|
||||
|
||||
@@ -155,11 +150,14 @@ class SimpleMonthView extends View {
|
||||
this(context, attrs, R.attr.datePickerStyle);
|
||||
}
|
||||
|
||||
public SimpleMonthView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs);
|
||||
public SimpleMonthView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
this(context, attrs, defStyleAttr, 0);
|
||||
}
|
||||
|
||||
public SimpleMonthView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
|
||||
final Resources res = context.getResources();
|
||||
|
||||
mDayOfWeekTypeface = res.getString(R.string.day_of_week_label_typeface);
|
||||
mMonthTitleTypeface = res.getString(R.string.sans_serif);
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ package android.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -33,10 +32,15 @@ import com.android.internal.R;
|
||||
*/
|
||||
class YearPickerView extends ListView implements AdapterView.OnItemClickListener,
|
||||
OnDateChangedListener {
|
||||
private final Calendar mMinDate = Calendar.getInstance();
|
||||
private final Calendar mMaxDate = Calendar.getInstance();
|
||||
|
||||
private final YearAdapter mAdapter;
|
||||
private final int mViewSize;
|
||||
private final int mChildSize;
|
||||
|
||||
private DatePickerController mController;
|
||||
private YearAdapter mAdapter;
|
||||
private int mViewSize;
|
||||
private int mChildSize;
|
||||
|
||||
private int mSelectedPosition = -1;
|
||||
private int mYearSelectedCircleColor;
|
||||
|
||||
@@ -72,15 +76,23 @@ class YearPickerView extends ListView implements AdapterView.OnItemClickListener
|
||||
|
||||
setOnItemClickListener(this);
|
||||
setDividerHeight(0);
|
||||
|
||||
mAdapter = new YearAdapter(getContext(), R.layout.year_label_text_view);
|
||||
setAdapter(mAdapter);
|
||||
}
|
||||
|
||||
public void setRange(Calendar min, Calendar max) {
|
||||
mMinDate.setTimeInMillis(min.getTimeInMillis());
|
||||
mMaxDate.setTimeInMillis(max.getTimeInMillis());
|
||||
|
||||
updateAdapterData();
|
||||
}
|
||||
|
||||
public void init(DatePickerController controller) {
|
||||
mController = controller;
|
||||
mController.registerOnDateChangedListener(this);
|
||||
|
||||
mAdapter = new YearAdapter(getContext(), R.layout.year_label_text_view);
|
||||
updateAdapterData();
|
||||
setAdapter(mAdapter);
|
||||
|
||||
onDateChanged();
|
||||
}
|
||||
@@ -98,8 +110,9 @@ class YearPickerView extends ListView implements AdapterView.OnItemClickListener
|
||||
|
||||
private void updateAdapterData() {
|
||||
mAdapter.clear();
|
||||
final int maxYear = mController.getMaxYear();
|
||||
for (int year = mController.getMinYear(); year <= maxYear; year++) {
|
||||
|
||||
final int maxYear = mMaxDate.get(Calendar.YEAR);
|
||||
for (int year = mMinDate.get(Calendar.YEAR); year <= maxYear; year++) {
|
||||
mAdapter.add(year);
|
||||
}
|
||||
}
|
||||
@@ -173,12 +186,13 @@ class YearPickerView extends ListView implements AdapterView.OnItemClickListener
|
||||
updateAdapterData();
|
||||
mAdapter.notifyDataSetChanged();
|
||||
postSetSelectionCentered(
|
||||
mController.getSelectedDay().get(Calendar.YEAR) - mController.getMinYear());
|
||||
mController.getSelectedDay().get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
|
||||
super.onInitializeAccessibilityEvent(event);
|
||||
|
||||
if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
|
||||
event.setFromIndex(0);
|
||||
event.setToIndex(0);
|
||||
|
||||
Reference in New Issue
Block a user