• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DayPickerPagerAdapter(@onNull Context context, @LayoutRes int layoutResId, @IdRes int calendarViewId)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 
setRange(@onNull Calendar min, @NonNull Calendar max)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      */
setFirstDayOfWeek(int weekStart)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 
getFirstDayOfWeek()107     public int getFirstDayOfWeek() {
108         return mFirstDayOfWeek;
109     }
110 
111     /**
112      * Sets the selected day.
113      *
114      * @param day the selected day
115      */
setSelectedDay(@ullable Calendar day)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      */
setOnDaySelectedListener(OnDaySelectedListener listener)145     public void setOnDaySelectedListener(OnDaySelectedListener listener) {
146         mOnDaySelectedListener = listener;
147     }
148 
setCalendarTextColor(ColorStateList calendarTextColor)149     void setCalendarTextColor(ColorStateList calendarTextColor) {
150         mCalendarTextColor = calendarTextColor;
151     }
152 
setDaySelectorColor(ColorStateList selectorColor)153     void setDaySelectorColor(ColorStateList selectorColor) {
154         mDaySelectorColor = selectorColor;
155     }
156 
setMonthTextAppearance(int resId)157     void setMonthTextAppearance(int resId) {
158         mMonthTextAppearance = resId;
159     }
160 
setDayOfWeekTextAppearance(int resId)161     void setDayOfWeekTextAppearance(int resId) {
162         mDayOfWeekTextAppearance = resId;
163     }
164 
getDayOfWeekTextAppearance()165     int getDayOfWeekTextAppearance() {
166         return mDayOfWeekTextAppearance;
167     }
168 
setDayTextAppearance(int resId)169     void setDayTextAppearance(int resId) {
170         mDayTextAppearance = resId;
171     }
172 
getDayTextAppearance()173     int getDayTextAppearance() {
174         return mDayTextAppearance;
175     }
176 
177     @Override
getCount()178     public int getCount() {
179         return mCount;
180     }
181 
182     @Override
isViewFromObject(View view, Object object)183     public boolean isViewFromObject(View view, Object object) {
184         final ViewHolder holder = (ViewHolder) object;
185         return view == holder.container;
186     }
187 
getMonthForPosition(int position)188     private int getMonthForPosition(int position) {
189         return (position + mMinDate.get(Calendar.MONTH)) % MONTHS_IN_YEAR;
190     }
191 
getYearForPosition(int position)192     private int getYearForPosition(int position) {
193         final int yearOffset = (position + mMinDate.get(Calendar.MONTH)) / MONTHS_IN_YEAR;
194         return yearOffset + mMinDate.get(Calendar.YEAR);
195     }
196 
getPositionForDay(@ullable Calendar day)197     private int getPositionForDay(@Nullable Calendar day) {
198         if (day == null) {
199             return -1;
200         }
201 
202         final int yearOffset = day.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
203         final int monthOffset = day.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH);
204         final int position = yearOffset * MONTHS_IN_YEAR + monthOffset;
205         return position;
206     }
207 
208     @Override
instantiateItem(ViewGroup container, int position)209     public Object instantiateItem(ViewGroup container, int position) {
210         final View itemView = mInflater.inflate(mLayoutResId, container, false);
211 
212         final SimpleMonthView v = (SimpleMonthView) itemView.findViewById(mCalendarViewId);
213         v.setOnDayClickListener(mOnDayClickListener);
214         v.setMonthTextAppearance(mMonthTextAppearance);
215         v.setDayOfWeekTextAppearance(mDayOfWeekTextAppearance);
216         v.setDayTextAppearance(mDayTextAppearance);
217 
218         if (mDaySelectorColor != null) {
219             v.setDaySelectorColor(mDaySelectorColor);
220         }
221 
222         if (mDayHighlightColor != null) {
223             v.setDayHighlightColor(mDayHighlightColor);
224         }
225 
226         if (mCalendarTextColor != null) {
227             v.setMonthTextColor(mCalendarTextColor);
228             v.setDayOfWeekTextColor(mCalendarTextColor);
229             v.setDayTextColor(mCalendarTextColor);
230         }
231 
232         final int month = getMonthForPosition(position);
233         final int year = getYearForPosition(position);
234 
235         final int selectedDay;
236         if (mSelectedDay != null && mSelectedDay.get(Calendar.MONTH) == month) {
237             selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH);
238         } else {
239             selectedDay = -1;
240         }
241 
242         final int enabledDayRangeStart;
243         if (mMinDate.get(Calendar.MONTH) == month && mMinDate.get(Calendar.YEAR) == year) {
244             enabledDayRangeStart = mMinDate.get(Calendar.DAY_OF_MONTH);
245         } else {
246             enabledDayRangeStart = 1;
247         }
248 
249         final int enabledDayRangeEnd;
250         if (mMaxDate.get(Calendar.MONTH) == month && mMaxDate.get(Calendar.YEAR) == year) {
251             enabledDayRangeEnd = mMaxDate.get(Calendar.DAY_OF_MONTH);
252         } else {
253             enabledDayRangeEnd = 31;
254         }
255 
256         v.setMonthParams(selectedDay, month, year, mFirstDayOfWeek,
257                 enabledDayRangeStart, enabledDayRangeEnd);
258 
259         final ViewHolder holder = new ViewHolder(position, itemView, v);
260         mItems.put(position, holder);
261 
262         container.addView(itemView);
263 
264         return holder;
265     }
266 
267     @Override
destroyItem(ViewGroup container, int position, Object object)268     public void destroyItem(ViewGroup container, int position, Object object) {
269         final ViewHolder holder = (ViewHolder) object;
270         container.removeView(holder.container);
271 
272         mItems.remove(position);
273     }
274 
275     @Override
getItemPosition(Object object)276     public int getItemPosition(Object object) {
277         final ViewHolder holder = (ViewHolder) object;
278         return holder.position;
279     }
280 
281     @Override
getPageTitle(int position)282     public CharSequence getPageTitle(int position) {
283         final SimpleMonthView v = mItems.get(position).calendar;
284         if (v != null) {
285             return v.getTitle();
286         }
287         return null;
288     }
289 
290     private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() {
291         @Override
292         public void onDayClick(SimpleMonthView view, Calendar day) {
293             if (day != null) {
294                 setSelectedDay(day);
295 
296                 if (mOnDaySelectedListener != null) {
297                     mOnDaySelectedListener.onDaySelected(DayPickerPagerAdapter.this, day);
298                 }
299             }
300         }
301     };
302 
303     private static class ViewHolder {
304         public final int position;
305         public final View container;
306         public final SimpleMonthView calendar;
307 
ViewHolder(int position, View container, SimpleMonthView calendar)308         public ViewHolder(int position, View container, SimpleMonthView calendar) {
309             this.position = position;
310             this.container = container;
311             this.calendar = calendar;
312         }
313     }
314 
315     public interface OnDaySelectedListener {
onDaySelected(DayPickerPagerAdapter view, Calendar day)316         public void onDaySelected(DayPickerPagerAdapter view, Calendar day);
317     }
318 }
319