blob: 478fa00d4607037325d34391e51961eaa34d31c8 [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) {
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
Alan Viverette60b674e2015-03-25 13:00:42 -0700196 private int getPositionForDay(@Nullable Calendar day) {
197 if (day == null) {
198 return -1;
199 }
200
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700201 final int yearOffset = (day.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR));
202 final int monthOffset = (day.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH));
Alan Viverette78bf1d32015-04-17 10:39:22 -0700203 final int position = yearOffset * MONTHS_IN_YEAR + monthOffset;
204 return position;
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700205 }
206
207 @Override
208 public Object instantiateItem(ViewGroup container, int position) {
Alan Viverette60b674e2015-03-25 13:00:42 -0700209 final View itemView = mInflater.inflate(mLayoutResId, container, false);
210
211 final SimpleMonthView v = (SimpleMonthView) itemView.findViewById(mCalendarViewId);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700212 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;
Alan Viverette60b674e2015-03-25 13:00:42 -0700235 if (mSelectedDay != null && mSelectedDay.get(Calendar.MONTH) == month) {
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700236 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
Alan Viverette60b674e2015-03-25 13:00:42 -0700258 final ViewHolder holder = new ViewHolder(position, itemView, v);
259 mItems.put(position, holder);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700260
Alan Viverette60b674e2015-03-25 13:00:42 -0700261 container.addView(itemView);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700262
Alan Viverette60b674e2015-03-25 13:00:42 -0700263 return holder;
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700264 }
265
266 @Override
267 public void destroyItem(ViewGroup container, int position, Object object) {
Alan Viverette60b674e2015-03-25 13:00:42 -0700268 final ViewHolder holder = (ViewHolder) object;
269 container.removeView(holder.container);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700270
271 mItems.remove(position);
272 }
273
274 @Override
275 public int getItemPosition(Object object) {
Alan Viverette60b674e2015-03-25 13:00:42 -0700276 final ViewHolder holder = (ViewHolder) object;
277 return holder.position;
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700278 }
279
280 @Override
281 public CharSequence getPageTitle(int position) {
Alan Viverette60b674e2015-03-25 13:00:42 -0700282 final SimpleMonthView v = mItems.get(position).calendar;
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700283 if (v != null) {
284 return v.getTitle();
285 }
286 return null;
287 }
288
289 private boolean isCalendarInRange(Calendar value) {
290 return value.compareTo(mMinDate) >= 0 && value.compareTo(mMaxDate) <= 0;
291 }
292
293 private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() {
294 @Override
295 public void onDayClick(SimpleMonthView view, Calendar day) {
296 if (day != null && isCalendarInRange(day)) {
297 setSelectedDay(day);
298
299 if (mOnDaySelectedListener != null) {
Alan Viverette78bf1d32015-04-17 10:39:22 -0700300 mOnDaySelectedListener.onDaySelected(DayPickerPagerAdapter.this, day);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700301 }
302 }
303 }
304 };
305
Alan Viverette60b674e2015-03-25 13:00:42 -0700306 private static class ViewHolder {
307 public final int position;
308 public final View container;
309 public final SimpleMonthView calendar;
310
311 public ViewHolder(int position, View container, SimpleMonthView calendar) {
312 this.position = position;
313 this.container = container;
314 this.calendar = calendar;
315 }
316 }
317
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700318 public interface OnDaySelectedListener {
Alan Viverette78bf1d32015-04-17 10:39:22 -0700319 public void onDaySelected(DayPickerPagerAdapter view, Calendar day);
Alan Viverette0ef59ac2015-03-23 13:13:25 -0700320 }
321}