OSDN Git Service

Fix DatePicker max date, disabled day color, and arrow visibility
[android-x86/frameworks-base.git] / core / java / android / widget / DayPickerPagerAdapter.java
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package android.widget;
18
19 import com.android.internal.widget.PagerAdapter;
20
21 import android.annotation.IdRes;
22 import android.annotation.LayoutRes;
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.content.Context;
26 import android.content.res.ColorStateList;
27 import android.content.res.TypedArray;
28 import android.util.SparseArray;
29 import android.view.LayoutInflater;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.widget.SimpleMonthView.OnDayClickListener;
33
34 import java.util.Calendar;
35
36 /**
37  * An adapter for a list of {@link android.widget.SimpleMonthView} items.
38  */
39 class DayPickerPagerAdapter extends PagerAdapter {
40     private static final int MONTHS_IN_YEAR = 12;
41
42     private final Calendar mMinDate = Calendar.getInstance();
43     private final Calendar mMaxDate = Calendar.getInstance();
44
45     private final SparseArray<ViewHolder> mItems = new SparseArray<>();
46
47     private final LayoutInflater mInflater;
48     private final int mLayoutResId;
49     private final int mCalendarViewId;
50
51     private Calendar mSelectedDay = null;
52
53     private int mMonthTextAppearance;
54     private int mDayOfWeekTextAppearance;
55     private int mDayTextAppearance;
56
57     private ColorStateList mCalendarTextColor;
58     private ColorStateList mDaySelectorColor;
59     private ColorStateList mDayHighlightColor;
60
61     private OnDaySelectedListener mOnDaySelectedListener;
62
63     private int mCount;
64     private int mFirstDayOfWeek;
65
66     public DayPickerPagerAdapter(@NonNull Context context, @LayoutRes int layoutResId,
67             @IdRes int calendarViewId) {
68         mInflater = LayoutInflater.from(context);
69         mLayoutResId = layoutResId;
70         mCalendarViewId = calendarViewId;
71
72         final TypedArray ta = context.obtainStyledAttributes(new int[] {
73                 com.android.internal.R.attr.colorControlHighlight});
74         mDayHighlightColor = ta.getColorStateList(0);
75         ta.recycle();
76     }
77
78     public void setRange(@NonNull Calendar min, @NonNull Calendar max) {
79         mMinDate.setTimeInMillis(min.getTimeInMillis());
80         mMaxDate.setTimeInMillis(max.getTimeInMillis());
81
82         final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
83         final int diffMonth = mMaxDate.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH);
84         mCount = diffMonth + MONTHS_IN_YEAR * diffYear + 1;
85
86         // Positions are now invalid, clear everything and start over.
87         notifyDataSetChanged();
88     }
89
90     /**
91      * Sets the first day of the week.
92      *
93      * @param weekStart which day the week should start on, valid values are
94      *                  {@link Calendar#SUNDAY} through {@link Calendar#SATURDAY}
95      */
96     public void setFirstDayOfWeek(int weekStart) {
97         mFirstDayOfWeek = weekStart;
98
99         // Update displayed views.
100         final int count = mItems.size();
101         for (int i = 0; i < count; i++) {
102             final SimpleMonthView monthView = mItems.valueAt(i).calendar;
103             monthView.setFirstDayOfWeek(weekStart);
104         }
105     }
106
107     public int getFirstDayOfWeek() {
108         return mFirstDayOfWeek;
109     }
110
111     /**
112      * Sets the selected day.
113      *
114      * @param day the selected day
115      */
116     public void setSelectedDay(@Nullable Calendar day) {
117         final int oldPosition = getPositionForDay(mSelectedDay);
118         final int newPosition = getPositionForDay(day);
119
120         // Clear the old position if necessary.
121         if (oldPosition != newPosition && oldPosition >= 0) {
122             final ViewHolder oldMonthView = mItems.get(oldPosition, null);
123             if (oldMonthView != null) {
124                 oldMonthView.calendar.setSelectedDay(-1);
125             }
126         }
127
128         // Set the new position.
129         if (newPosition >= 0) {
130             final ViewHolder newMonthView = mItems.get(newPosition, null);
131             if (newMonthView != null) {
132                 final int dayOfMonth = day.get(Calendar.DAY_OF_MONTH);
133                 newMonthView.calendar.setSelectedDay(dayOfMonth);
134             }
135         }
136
137         mSelectedDay = day;
138     }
139
140     /**
141      * Sets the listener to call when the user selects a day.
142      *
143      * @param listener The listener to call.
144      */
145     public void setOnDaySelectedListener(OnDaySelectedListener listener) {
146         mOnDaySelectedListener = listener;
147     }
148
149     void setCalendarTextColor(ColorStateList calendarTextColor) {
150         mCalendarTextColor = calendarTextColor;
151     }
152
153     void setDaySelectorColor(ColorStateList selectorColor) {
154         mDaySelectorColor = selectorColor;
155     }
156
157     void setMonthTextAppearance(int resId) {
158         mMonthTextAppearance = resId;
159     }
160
161     void setDayOfWeekTextAppearance(int resId) {
162         mDayOfWeekTextAppearance = resId;
163     }
164
165     int getDayOfWeekTextAppearance() {
166         return mDayOfWeekTextAppearance;
167     }
168
169     void setDayTextAppearance(int resId) {
170         mDayTextAppearance = resId;
171     }
172
173     int getDayTextAppearance() {
174         return mDayTextAppearance;
175     }
176
177     @Override
178     public int getCount() {
179         return mCount;
180     }
181
182     @Override
183     public boolean isViewFromObject(View view, Object object) {
184         final ViewHolder holder = (ViewHolder) object;
185         return view == holder.container;
186     }
187
188     private int getMonthForPosition(int position) {
189         return position % MONTHS_IN_YEAR + mMinDate.get(Calendar.MONTH);
190     }
191
192     private int getYearForPosition(int position) {
193         return position / MONTHS_IN_YEAR + mMinDate.get(Calendar.YEAR);
194     }
195
196     private int getPositionForDay(@Nullable Calendar day) {
197         if (day == null) {
198             return -1;
199         }
200
201         final int yearOffset = (day.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR));
202         final int monthOffset = (day.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH));
203         final int position = yearOffset * MONTHS_IN_YEAR + monthOffset;
204         return position;
205     }
206
207     @Override
208     public Object instantiateItem(ViewGroup container, int position) {
209         final View itemView = mInflater.inflate(mLayoutResId, container, false);
210
211         final SimpleMonthView v = (SimpleMonthView) itemView.findViewById(mCalendarViewId);
212         v.setOnDayClickListener(mOnDayClickListener);
213         v.setMonthTextAppearance(mMonthTextAppearance);
214         v.setDayOfWeekTextAppearance(mDayOfWeekTextAppearance);
215         v.setDayTextAppearance(mDayTextAppearance);
216
217         if (mDaySelectorColor != null) {
218             v.setDaySelectorColor(mDaySelectorColor);
219         }
220
221         if (mDayHighlightColor != null) {
222             v.setDayHighlightColor(mDayHighlightColor);
223         }
224
225         if (mCalendarTextColor != null) {
226             v.setMonthTextColor(mCalendarTextColor);
227             v.setDayOfWeekTextColor(mCalendarTextColor);
228             v.setDayTextColor(mCalendarTextColor);
229         }
230
231         final int month = getMonthForPosition(position);
232         final int year = getYearForPosition(position);
233
234         final int selectedDay;
235         if (mSelectedDay != null && mSelectedDay.get(Calendar.MONTH) == month) {
236             selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH);
237         } else {
238             selectedDay = -1;
239         }
240
241         final int enabledDayRangeStart;
242         if (mMinDate.get(Calendar.MONTH) == month && mMinDate.get(Calendar.YEAR) == year) {
243             enabledDayRangeStart = mMinDate.get(Calendar.DAY_OF_MONTH);
244         } else {
245             enabledDayRangeStart = 1;
246         }
247
248         final int enabledDayRangeEnd;
249         if (mMaxDate.get(Calendar.MONTH) == month && mMaxDate.get(Calendar.YEAR) == year) {
250             enabledDayRangeEnd = mMaxDate.get(Calendar.DAY_OF_MONTH);
251         } else {
252             enabledDayRangeEnd = 31;
253         }
254
255         v.setMonthParams(selectedDay, month, year, mFirstDayOfWeek,
256                 enabledDayRangeStart, enabledDayRangeEnd);
257
258         final ViewHolder holder = new ViewHolder(position, itemView, v);
259         mItems.put(position, holder);
260
261         container.addView(itemView);
262
263         return holder;
264     }
265
266     @Override
267     public void destroyItem(ViewGroup container, int position, Object object) {
268         final ViewHolder holder = (ViewHolder) object;
269         container.removeView(holder.container);
270
271         mItems.remove(position);
272     }
273
274     @Override
275     public int getItemPosition(Object object) {
276         final ViewHolder holder = (ViewHolder) object;
277         return holder.position;
278     }
279
280     @Override
281     public CharSequence getPageTitle(int position) {
282         final SimpleMonthView v = mItems.get(position).calendar;
283         if (v != null) {
284             return v.getTitle();
285         }
286         return null;
287     }
288
289     private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() {
290         @Override
291         public void onDayClick(SimpleMonthView view, Calendar day) {
292             if (day != null) {
293                 setSelectedDay(day);
294
295                 if (mOnDaySelectedListener != null) {
296                     mOnDaySelectedListener.onDaySelected(DayPickerPagerAdapter.this, day);
297                 }
298             }
299         }
300     };
301
302     private static class ViewHolder {
303         public final int position;
304         public final View container;
305         public final SimpleMonthView calendar;
306
307         public ViewHolder(int position, View container, SimpleMonthView calendar) {
308             this.position = position;
309             this.container = container;
310             this.calendar = calendar;
311         }
312     }
313
314     public interface OnDaySelectedListener {
315         public void onDaySelected(DayPickerPagerAdapter view, Calendar day);
316     }
317 }