Merge "Clean up encapsulation in date picker classes" into lmp-mr1-dev

This commit is contained in:
Alan Viverette
2014-11-10 18:29:27 +00:00
committed by Android (Google) Code Review
4 changed files with 108 additions and 140 deletions

View File

@@ -183,8 +183,11 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i
mHeaderYearTextView.getTextColors(), R.attr.state_selected, mHeaderYearTextView.getTextColors(), R.attr.state_selected,
headerSelectedTextColor)); headerSelectedTextColor));
mDayPickerView = new DayPickerView(mContext, this); mDayPickerView = new DayPickerView(mContext);
mDayPickerView.setFirstDayOfWeek(mFirstDayOfWeek);
mDayPickerView.setRange(mMinDate, mMaxDate); mDayPickerView.setRange(mMinDate, mMaxDate);
mDayPickerView.setDay(mCurrentDate);
mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener);
mYearPickerView = new YearPickerView(mContext); mYearPickerView = new YearPickerView(mContext);
mYearPickerView.init(this); mYearPickerView.init(this);
@@ -333,7 +336,7 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i
switch (viewIndex) { switch (viewIndex) {
case MONTH_AND_DAY_VIEW: case MONTH_AND_DAY_VIEW:
mDayPickerView.onDateChanged(); mDayPickerView.setDay(getSelectedDay());
if (mCurrentView != viewIndex) { if (mCurrentView != viewIndex) {
mMonthAndDayLayout.setSelected(true); mMonthAndDayLayout.setSelected(true);
mHeaderYearTextView.setSelected(false); mHeaderYearTextView.setSelected(false);
@@ -445,6 +448,8 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i
@Override @Override
public void setFirstDayOfWeek(int firstDayOfWeek) { public void setFirstDayOfWeek(int firstDayOfWeek) {
mFirstDayOfWeek = firstDayOfWeek; mFirstDayOfWeek = firstDayOfWeek;
mDayPickerView.setFirstDayOfWeek(firstDayOfWeek);
} }
@Override @Override
@@ -606,19 +611,12 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i
} }
} }
@Override
public void onDayOfMonthSelected(int year, int month, int day) {
mCurrentDate.set(Calendar.YEAR, year);
mCurrentDate.set(Calendar.MONTH, month);
mCurrentDate.set(Calendar.DAY_OF_MONTH, day);
updatePickers();
updateDisplay(true);
}
private void updatePickers() { private void updatePickers() {
for (OnDateChangedListener listener : mListeners) { for (OnDateChangedListener listener : mListeners) {
listener.onDateChanged(); listener.onDateChanged();
} }
mDayPickerView.setDay(getSelectedDay());
} }
@Override @Override
@@ -626,11 +624,6 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i
mListeners.add(listener); mListeners.add(listener);
} }
@Override
public void unregisterOnDateChangedListener(OnDateChangedListener listener) {
mListeners.remove(listener);
}
@Override @Override
public Calendar getSelectedDay() { public Calendar getSelectedDay() {
return mCurrentDate; return mCurrentDate;
@@ -651,6 +644,22 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i
} }
} }
/**
* Listener called when the user selects a day in the day picker view.
*/
private final DayPickerView.OnDaySelectedListener
mOnDaySelectedListener = new DayPickerView.OnDaySelectedListener() {
@Override
public void onDaySelected(DayPickerView view, Calendar day) {
mCurrentDate.setTimeInMillis(day.getTimeInMillis());
updatePickers();
updateDisplay(true);
tryVibrate();
}
};
/** /**
* Class for managing state storing/restoring. * Class for managing state storing/restoring.
*/ */

View File

@@ -27,16 +27,9 @@ interface DatePickerController {
void onYearSelected(int year); void onYearSelected(int year);
void onDayOfMonthSelected(int year, int month, int day);
void registerOnDateChangedListener(OnDateChangedListener listener); void registerOnDateChangedListener(OnDateChangedListener listener);
void unregisterOnDateChangedListener(OnDateChangedListener listener);
Calendar getSelectedDay(); Calendar getSelectedDay();
void setFirstDayOfWeek(int firstDayOfWeek);
int getFirstDayOfWeek();
void tryVibrate(); void tryVibrate();
} }

View File

@@ -16,14 +16,10 @@
package android.widget; package android.widget;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
import android.util.MathUtils; import android.util.MathUtils;
import android.view.View; import android.view.View;
@@ -38,9 +34,7 @@ import java.util.Locale;
/** /**
* This displays a list of months in a calendar format with selectable days. * This displays a list of months in a calendar format with selectable days.
*/ */
class DayPickerView extends ListView implements AbsListView.OnScrollListener, class DayPickerView extends ListView implements AbsListView.OnScrollListener {
OnDateChangedListener {
private static final String TAG = "DayPickerView"; private static final String TAG = "DayPickerView";
// How long the GoTo fling animation should last // How long the GoTo fling animation should last
@@ -49,20 +43,22 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener,
// How long to wait after receiving an onScrollStateChanged notification before acting on it // How long to wait after receiving an onScrollStateChanged notification before acting on it
private static final int SCROLL_CHANGE_DELAY = 40; private static final int SCROLL_CHANGE_DELAY = 40;
private static int LIST_TOP_OFFSET = -1; // so that the top line will be under the separator // so that the top line will be under the separator
private static final int LIST_TOP_OFFSET = -1;
private final SimpleMonthAdapter mAdapter = new SimpleMonthAdapter(getContext());
private final ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable(this);
private SimpleDateFormat mYearFormat = new SimpleDateFormat("yyyy", Locale.getDefault()); private SimpleDateFormat mYearFormat = new SimpleDateFormat("yyyy", Locale.getDefault());
// These affect the scroll speed and feel
private float mFriction = 1.0f;
// highlighted time // highlighted time
private Calendar mSelectedDay = Calendar.getInstance(); private Calendar mSelectedDay = Calendar.getInstance();
private Calendar mTempDay = Calendar.getInstance(); private Calendar mTempDay = Calendar.getInstance();
private Calendar mMinDate = Calendar.getInstance(); private Calendar mMinDate = Calendar.getInstance();
private Calendar mMaxDate = Calendar.getInstance(); private Calendar mMaxDate = Calendar.getInstance();
private SimpleMonthAdapter mAdapter; private OnDaySelectedListener mOnDaySelectedListener;
// which month should be displayed/highlighted [0-11] // which month should be displayed/highlighted [0-11]
private int mCurrentMonthDisplayed; private int mCurrentMonthDisplayed;
@@ -71,34 +67,27 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener,
// used for tracking what state listview is in // used for tracking what state listview is in
private int mCurrentScrollState = OnScrollListener.SCROLL_STATE_IDLE; private int mCurrentScrollState = OnScrollListener.SCROLL_STATE_IDLE;
private DatePickerController mController;
private boolean mPerformingScroll; private boolean mPerformingScroll;
private ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable(this); public DayPickerView(Context context) {
public DayPickerView(Context context, DatePickerController controller) {
super(context); super(context);
init();
setController(controller);
}
public void setController(DatePickerController controller) {
if (mController != null) {
mController.unregisterOnDateChangedListener(this);
}
mController = controller;
mController.registerOnDateChangedListener(this);
setUpAdapter();
setAdapter(mAdapter); setAdapter(mAdapter);
onDateChanged();
}
public void init() {
setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
setDrawSelectorOnTop(false); setDrawSelectorOnTop(false);
setUpListView(); setUpListView();
goTo(mSelectedDay, false, true, true);
mAdapter.setOnDaySelectedListener(mProxyOnDaySelectedListener);
}
public void setDay(Calendar day) {
goTo(day, false, true, true);
}
public void setFirstDayOfWeek(int firstDayOfWeek) {
mAdapter.setFirstDayOfWeek(firstDayOfWeek);
} }
public void setRange(Calendar minDate, Calendar maxDate) { public void setRange(Calendar minDate, Calendar maxDate) {
@@ -113,54 +102,19 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener,
} }
/** /**
* Constrains the supplied calendar to stay within the min and max * Sets the listener to call when the user selects a day.
* calendars, returning <code>true</code> if the supplied calendar
* was modified.
* *
* @param value The calendar to constrain * @param listener The listener to call.
* @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) { public void setOnDaySelectedListener(OnDaySelectedListener listener) {
if (value.compareTo(min) < 0) { mOnDaySelectedListener = listener;
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);
}
/**
* Creates a new adapter if necessary and sets up its parameters. Override
* this method to provide a custom adapter.
*/
protected void setUpAdapter() {
if (mAdapter == null) {
mAdapter = new SimpleMonthAdapter(getContext(), mController);
} else {
mAdapter.setSelectedDay(mSelectedDay);
mAdapter.notifyDataSetChanged();
}
// refresh the view with the new parameters
mAdapter.notifyDataSetChanged();
} }
/* /*
* Sets all the required fields for the list view. Override this method to * Sets all the required fields for the list view. Override this method to
* set a different list view behavior. * set a different list view behavior.
*/ */
protected void setUpListView() { private void setUpListView() {
// Transparent background on scroll // Transparent background on scroll
setCacheColorHint(0); setCacheColorHint(0);
// No dividers // No dividers
@@ -173,7 +127,7 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener,
setOnScrollListener(this); setOnScrollListener(this);
setFadingEdgeLength(0); setFadingEdgeLength(0);
// Make the scrolling behavior nicer // Make the scrolling behavior nicer
setFriction(ViewConfiguration.getScrollFriction() * mFriction); setFriction(ViewConfiguration.getScrollFriction());
} }
private int getDiffMonths(Calendar start, Calendar end) { private int getDiffMonths(Calendar start, Calendar end) {
@@ -203,7 +157,7 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener,
* visible * visible
* @return Whether or not the view animated to the new location * @return Whether or not the view animated to the new location
*/ */
public boolean goTo(Calendar day, boolean animate, boolean setSelected, boolean forceScroll) { private boolean goTo(Calendar day, boolean animate, boolean setSelected, boolean forceScroll) {
// Set the selected day // Set the selected day
if (setSelected) { if (setSelected) {
@@ -392,11 +346,6 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener,
return firstPosition + mostVisibleIndex; return firstPosition + mostVisibleIndex;
} }
@Override
public void onDateChanged() {
goTo(mController.getSelectedDay(), false, true, true);
}
/** /**
* Attempts to return the date that has accessibility focus. * Attempts to return the date that has accessibility focus.
* *
@@ -529,4 +478,18 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener,
mPerformingScroll = true; mPerformingScroll = true;
return true; return true;
} }
public interface OnDaySelectedListener {
public void onDaySelected(DayPickerView view, Calendar day);
}
private final SimpleMonthAdapter.OnDaySelectedListener
mProxyOnDaySelectedListener = new SimpleMonthAdapter.OnDaySelectedListener() {
@Override
public void onDaySelected(SimpleMonthAdapter adapter, Calendar day) {
if (mOnDaySelectedListener != null) {
mOnDaySelectedListener.onDaySelected(DayPickerView.this, day);
}
}
};
} }

View File

@@ -20,29 +20,28 @@ import android.content.Context;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.SimpleMonthView.OnDayClickListener;
import java.util.Calendar; import java.util.Calendar;
import java.util.HashMap;
/** /**
* An adapter for a list of {@link android.widget.SimpleMonthView} items. * An adapter for a list of {@link android.widget.SimpleMonthView} items.
*/ */
class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayClickListener { class SimpleMonthAdapter extends BaseAdapter {
private final Calendar mMinDate = Calendar.getInstance(); private final Calendar mMinDate = Calendar.getInstance();
private final Calendar mMaxDate = Calendar.getInstance(); private final Calendar mMaxDate = Calendar.getInstance();
private final Context mContext; private final Context mContext;
private final DatePickerController mController;
private Calendar mSelectedDay; private Calendar mSelectedDay;
private ColorStateList mCalendarTextColors; private ColorStateList mCalendarTextColors;
private OnDaySelectedListener mOnDaySelectedListener;
public SimpleMonthAdapter(Context context, DatePickerController controller) { private int mFirstDayOfWeek;
public SimpleMonthAdapter(Context context) {
mContext = context; mContext = context;
mController = controller; mSelectedDay = Calendar.getInstance();
init();
setSelectedDay(mController.getSelectedDay());
} }
public void setRange(Calendar min, Calendar max) { public void setRange(Calendar min, Calendar max) {
@@ -52,29 +51,36 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli
notifyDataSetInvalidated(); notifyDataSetInvalidated();
} }
public void setFirstDayOfWeek(int firstDayOfWeek) {
mFirstDayOfWeek = firstDayOfWeek;
notifyDataSetInvalidated();
}
/** /**
* Updates the selected day and related parameters. * Updates the selected day and related parameters.
* *
* @param day The day to highlight * @param day The day to highlight
*/ */
public void setSelectedDay(Calendar day) { public void setSelectedDay(Calendar day) {
if (mSelectedDay != day) { mSelectedDay = day;
mSelectedDay = day;
notifyDataSetChanged(); notifyDataSetChanged();
} }
/**
* Sets the listener to call when the user selects a day.
*
* @param listener The listener to call.
*/
public void setOnDaySelectedListener(OnDaySelectedListener listener) {
mOnDaySelectedListener = listener;
} }
void setCalendarTextColor(ColorStateList colors) { void setCalendarTextColor(ColorStateList colors) {
mCalendarTextColors = colors; mCalendarTextColors = colors;
} }
/**
* Set up the gesture detector and selected time
*/
protected void init() {
mSelectedDay = Calendar.getInstance();
}
@Override @Override
public int getCount() { public int getCount() {
final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR); final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
@@ -111,7 +117,7 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli
AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.MATCH_PARENT); AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.MATCH_PARENT);
v.setLayoutParams(params); v.setLayoutParams(params);
v.setClickable(true); v.setClickable(true);
v.setOnDayClickListener(this); v.setOnDayClickListener(mOnDayClickListener);
if (mCalendarTextColors != null) { if (mCalendarTextColors != null) {
v.setTextColor(mCalendarTextColors); v.setTextColor(mCalendarTextColors);
@@ -148,7 +154,7 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli
enabledDayRangeEnd = 31; enabledDayRangeEnd = 31;
} }
v.setMonthParams(selectedDay, month, year, mController.getFirstDayOfWeek(), v.setMonthParams(selectedDay, month, year, mFirstDayOfWeek,
enabledDayRangeStart, enabledDayRangeEnd); enabledDayRangeStart, enabledDayRangeEnd);
v.invalidate(); v.invalidate();
@@ -159,27 +165,24 @@ class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayCli
return mSelectedDay.get(Calendar.YEAR) == year && mSelectedDay.get(Calendar.MONTH) == month; return mSelectedDay.get(Calendar.YEAR) == year && mSelectedDay.get(Calendar.MONTH) == month;
} }
@Override
public void onDayClick(SimpleMonthView view, Calendar day) {
if (day != null && isCalendarInRange(day)) {
onDaySelected(day);
}
}
private boolean isCalendarInRange(Calendar value) { private boolean isCalendarInRange(Calendar value) {
return value.compareTo(mMinDate) >= 0 && value.compareTo(mMaxDate) <= 0; return value.compareTo(mMinDate) >= 0 && value.compareTo(mMaxDate) <= 0;
} }
/** private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() {
* Maintains the same hour/min/sec but moves the day to the tapped day. @Override
* public void onDayClick(SimpleMonthView view, Calendar day) {
* @param day The day that was tapped if (day != null && isCalendarInRange(day)) {
*/ setSelectedDay(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); if (mOnDaySelectedListener != null) {
mOnDaySelectedListener.onDaySelected(SimpleMonthAdapter.this, day);
}
}
}
};
public interface OnDaySelectedListener {
public void onDaySelected(SimpleMonthAdapter view, Calendar day);
} }
} }