blob: 8ce2f9cb470c3caab9d8233d0021996e252d382e [file] [log] [blame]
Alan Viverette0ef59ac2015-03-23 13:13:25 -07001/*
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
17package android.widget;
18
19import com.android.internal.widget.PagerAdapter;
20
Alan Viverette60b674e2015-03-25 13:00:42 -070021import android.annotation.IdRes;
22import android.annotation.LayoutRes;
23import android.annotation.NonNull;
24import android.annotation.Nullable;
Alan Viverette0ef59ac2015-03-23 13:13:25 -070025import android.content.Context;
26import android.content.res.ColorStateList;
27import android.content.res.TypedArray;
28import android.util.SparseArray;
Alan Viverette60b674e2015-03-25 13:00:42 -070029import android.view.LayoutInflater;
Alan Viverette0ef59ac2015-03-23 13:13:25 -070030import android.view.View;
31import android.view.ViewGroup;
32import android.widget.SimpleMonthView.OnDayClickListener;
33
34import java.util.Calendar;
35
36/**
37 * An adapter for a list of {@link android.widget.SimpleMonthView} items.
38 */
Alan Viverette78bf1d32015-04-17 10:39:22 -070039class DayPickerPagerAdapter extends PagerAdapter {
Alan Viverette0ef59ac2015-03-23 13:13:25 -070040 private static final int MONTHS_IN_YEAR = 12;
41
42 private final Calendar mMinDate = Calendar.getInstance();
43 private final Calendar mMaxDate = Calendar.getInstance();
44
Alan Viverette60b674e2015-03-25 13:00:42 -070045 private final SparseArray<ViewHolder> mItems = new SparseArray<>();
Alan Viverette0ef59ac2015-03-23 13:13:25 -070046
Alan Viverette60b674e2015-03-25 13:00:42 -070047 private final LayoutInflater mInflater;
48 private final int mLayoutResId;
49 private final int mCalendarViewId;
50
51 private Calendar mSelectedDay = null;
Alan Viverette0ef59ac2015-03-23 13:13:25 -070052
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
Alan Viverette60b674e2015-03-25 13:00:42 -070063 private int mCount;
Alan Viverette0ef59ac2015-03-23 13:13:25 -070064 private int mFirstDayOfWeek;
65
Alan Viverette78bf1d32015-04-17 10:39:22 -070066 public DayPickerPagerAdapter(@NonNull Context context, @LayoutRes int layoutResId,
Alan Viverette60b674e2015-03-25 13:00:42 -070067 @IdRes int calendarViewId) {
68 mInflater = LayoutInflater.from(context);
69 mLayoutResId = layoutResId;
70 mCalendarViewId = calendarViewId;
71
Alan Viverette0ef59ac2015-03-23 13:13:25 -070072 final TypedArray ta = context.obtainStyledAttributes(new int[] {
73 com.android.internal.R.attr.colorControlHighlight});
74 mDayHighlightColor = ta.getColorStateList(0);
75 ta.recycle();
76 }
77
Alan Viverette60b674e2015-03-25 13:00:42 -070078 public void setRange(@NonNull Calendar min, @NonNull Calendar max) {
Alan Viverette0ef59ac2015-03-23 13:13:25 -070079 mMinDate.setTimeInMillis(min.getTimeInMillis());
80 mMaxDate.setTimeInMillis(max.getTimeInMillis());
81
Alan Viverette60b674e2015-03-25 13:00:42 -070082 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
Alan Viverette0ef59ac2015-03-23 13:13:25 -070086 // 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++) {
Alan Viverette60b674e2015-03-25 13:00:42 -0700102 final SimpleMonthView monthView = mItems.valueAt(i).calendar;
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700103 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 */
Alan Viverette60b674e2015-03-25 13:00:42 -0700116 public void setSelectedDay(@Nullable Calendar day) {
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700117 final int oldPosition = getPositionForDay(mSelectedDay);
118 final int newPosition = getPositionForDay(day);
119
120 // Clear the old position if necessary.
Alan Viverette60b674e2015-03-25 13:00:42 -0700121 if (oldPosition != newPosition && oldPosition >= 0) {
122 final ViewHolder oldMonthView = mItems.get(oldPosition, null);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700123 if (oldMonthView != null) {
Alan Viverette60b674e2015-03-25 13:00:42 -0700124 oldMonthView.calendar.setSelectedDay(-1);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700125 }
126 }
127
128 // Set the new position.
Alan Viverette60b674e2015-03-25 13:00:42 -0700129 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 }
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700135 }
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() {
Alan Viverette60b674e2015-03-25 13:00:42 -0700179 return mCount;
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700180 }
181
182 @Override
183 public boolean isViewFromObject(View view, Object object) {
Alan Viverette60b674e2015-03-25 13:00:42 -0700184 final ViewHolder holder = (ViewHolder) object;
185 return view == holder.container;
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700186 }
187
188 private int getMonthForPosition(int position) {
Alan Viverettebd51b4d2015-05-15 14:18:44 -0700189 return (position + mMinDate.get(Calendar.MONTH)) % MONTHS_IN_YEAR;
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700190 }
191
192 private int getYearForPosition(int position) {
Alan Viverettebd51b4d2015-05-15 14:18:44 -0700193 final int yearOffset = (position + mMinDate.get(Calendar.MONTH)) / MONTHS_IN_YEAR;
194 return yearOffset + mMinDate.get(Calendar.YEAR);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700195 }
196
Alan Viverette60b674e2015-03-25 13:00:42 -0700197 private int getPositionForDay(@Nullable Calendar day) {
198 if (day == null) {
199 return -1;
200 }
201
Alan Viverettebd51b4d2015-05-15 14:18:44 -0700202 final int yearOffset = day.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
203 final int monthOffset = day.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH);
Alan Viverette78bf1d32015-04-17 10:39:22 -0700204 final int position = yearOffset * MONTHS_IN_YEAR + monthOffset;
205 return position;
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700206 }
207
208 @Override
209 public Object instantiateItem(ViewGroup container, int position) {
Alan Viverette60b674e2015-03-25 13:00:42 -0700210 final View itemView = mInflater.inflate(mLayoutResId, container, false);
211
212 final SimpleMonthView v = (SimpleMonthView) itemView.findViewById(mCalendarViewId);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700213 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;
Alan Viverette60b674e2015-03-25 13:00:42 -0700236 if (mSelectedDay != null && mSelectedDay.get(Calendar.MONTH) == month) {
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700237 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
Alan Viverette60b674e2015-03-25 13:00:42 -0700259 final ViewHolder holder = new ViewHolder(position, itemView, v);
260 mItems.put(position, holder);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700261
Alan Viverette60b674e2015-03-25 13:00:42 -0700262 container.addView(itemView);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700263
Alan Viverette60b674e2015-03-25 13:00:42 -0700264 return holder;
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700265 }
266
267 @Override
268 public void destroyItem(ViewGroup container, int position, Object object) {
Alan Viverette60b674e2015-03-25 13:00:42 -0700269 final ViewHolder holder = (ViewHolder) object;
270 container.removeView(holder.container);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700271
272 mItems.remove(position);
273 }
274
275 @Override
276 public int getItemPosition(Object object) {
Alan Viverette60b674e2015-03-25 13:00:42 -0700277 final ViewHolder holder = (ViewHolder) object;
278 return holder.position;
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700279 }
280
281 @Override
282 public CharSequence getPageTitle(int position) {
Alan Viverette60b674e2015-03-25 13:00:42 -0700283 final SimpleMonthView v = mItems.get(position).calendar;
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700284 if (v != null) {
Alan Viverettee264f952016-03-04 13:18:48 -0500285 return v.getMonthYearLabel();
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700286 }
287 return null;
288 }
289
George Mounte998c3f2015-10-27 08:46:44 -0700290 SimpleMonthView getView(Object object) {
291 if (object == null) {
292 return null;
293 }
294 final ViewHolder holder = (ViewHolder) object;
295 return holder.calendar;
296 }
297
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700298 private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() {
299 @Override
300 public void onDayClick(SimpleMonthView view, Calendar day) {
Alan Viverette5c339492015-04-28 14:07:36 -0700301 if (day != null) {
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700302 setSelectedDay(day);
303
304 if (mOnDaySelectedListener != null) {
Alan Viverette78bf1d32015-04-17 10:39:22 -0700305 mOnDaySelectedListener.onDaySelected(DayPickerPagerAdapter.this, day);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700306 }
307 }
308 }
309 };
310
Alan Viverette60b674e2015-03-25 13:00:42 -0700311 private static class ViewHolder {
312 public final int position;
313 public final View container;
314 public final SimpleMonthView calendar;
315
316 public ViewHolder(int position, View container, SimpleMonthView calendar) {
317 this.position = position;
318 this.container = container;
319 this.calendar = calendar;
320 }
321 }
322
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700323 public interface OnDaySelectedListener {
Alan Viverette78bf1d32015-04-17 10:39:22 -0700324 public void onDaySelected(DayPickerPagerAdapter view, Calendar day);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700325 }
326}