2 * Copyright (C) 2015 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package android.widget;
19 import com.android.internal.widget.PagerAdapter;
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;
34 import java.util.Calendar;
37 * An adapter for a list of {@link android.widget.SimpleMonthView} items.
39 class DayPickerPagerAdapter extends PagerAdapter {
40 private static final int MONTHS_IN_YEAR = 12;
42 private final Calendar mMinDate = Calendar.getInstance();
43 private final Calendar mMaxDate = Calendar.getInstance();
45 private final SparseArray<ViewHolder> mItems = new SparseArray<>();
47 private final LayoutInflater mInflater;
48 private final int mLayoutResId;
49 private final int mCalendarViewId;
51 private Calendar mSelectedDay = null;
53 private int mMonthTextAppearance;
54 private int mDayOfWeekTextAppearance;
55 private int mDayTextAppearance;
57 private ColorStateList mCalendarTextColor;
58 private ColorStateList mDaySelectorColor;
59 private ColorStateList mDayHighlightColor;
61 private OnDaySelectedListener mOnDaySelectedListener;
64 private int mFirstDayOfWeek;
66 public DayPickerPagerAdapter(@NonNull Context context, @LayoutRes int layoutResId,
67 @IdRes int calendarViewId) {
68 mInflater = LayoutInflater.from(context);
69 mLayoutResId = layoutResId;
70 mCalendarViewId = calendarViewId;
72 final TypedArray ta = context.obtainStyledAttributes(new int[] {
73 com.android.internal.R.attr.colorControlHighlight});
74 mDayHighlightColor = ta.getColorStateList(0);
78 public void setRange(@NonNull Calendar min, @NonNull Calendar max) {
79 mMinDate.setTimeInMillis(min.getTimeInMillis());
80 mMaxDate.setTimeInMillis(max.getTimeInMillis());
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;
86 // Positions are now invalid, clear everything and start over.
87 notifyDataSetChanged();
91 * Sets the first day of the week.
93 * @param weekStart which day the week should start on, valid values are
94 * {@link Calendar#SUNDAY} through {@link Calendar#SATURDAY}
96 public void setFirstDayOfWeek(int weekStart) {
97 mFirstDayOfWeek = weekStart;
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);
107 public int getFirstDayOfWeek() {
108 return mFirstDayOfWeek;
112 * Sets the selected day.
114 * @param day the selected day
116 public void setSelectedDay(@Nullable Calendar day) {
117 final int oldPosition = getPositionForDay(mSelectedDay);
118 final int newPosition = getPositionForDay(day);
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);
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);
141 * Sets the listener to call when the user selects a day.
143 * @param listener The listener to call.
145 public void setOnDaySelectedListener(OnDaySelectedListener listener) {
146 mOnDaySelectedListener = listener;
149 void setCalendarTextColor(ColorStateList calendarTextColor) {
150 mCalendarTextColor = calendarTextColor;
153 void setDaySelectorColor(ColorStateList selectorColor) {
154 mDaySelectorColor = selectorColor;
157 void setMonthTextAppearance(int resId) {
158 mMonthTextAppearance = resId;
161 void setDayOfWeekTextAppearance(int resId) {
162 mDayOfWeekTextAppearance = resId;
165 int getDayOfWeekTextAppearance() {
166 return mDayOfWeekTextAppearance;
169 void setDayTextAppearance(int resId) {
170 mDayTextAppearance = resId;
173 int getDayTextAppearance() {
174 return mDayTextAppearance;
178 public int getCount() {
183 public boolean isViewFromObject(View view, Object object) {
184 final ViewHolder holder = (ViewHolder) object;
185 return view == holder.container;
188 private int getMonthForPosition(int position) {
189 return position % MONTHS_IN_YEAR + mMinDate.get(Calendar.MONTH);
192 private int getYearForPosition(int position) {
193 return position / MONTHS_IN_YEAR + mMinDate.get(Calendar.YEAR);
196 private int getPositionForDay(@Nullable Calendar day) {
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;
208 public Object instantiateItem(ViewGroup container, int position) {
209 final View itemView = mInflater.inflate(mLayoutResId, container, false);
211 final SimpleMonthView v = (SimpleMonthView) itemView.findViewById(mCalendarViewId);
212 v.setOnDayClickListener(mOnDayClickListener);
213 v.setMonthTextAppearance(mMonthTextAppearance);
214 v.setDayOfWeekTextAppearance(mDayOfWeekTextAppearance);
215 v.setDayTextAppearance(mDayTextAppearance);
217 if (mDaySelectorColor != null) {
218 v.setDaySelectorColor(mDaySelectorColor);
221 if (mDayHighlightColor != null) {
222 v.setDayHighlightColor(mDayHighlightColor);
225 if (mCalendarTextColor != null) {
226 v.setMonthTextColor(mCalendarTextColor);
227 v.setDayOfWeekTextColor(mCalendarTextColor);
228 v.setDayTextColor(mCalendarTextColor);
231 final int month = getMonthForPosition(position);
232 final int year = getYearForPosition(position);
234 final int selectedDay;
235 if (mSelectedDay != null && mSelectedDay.get(Calendar.MONTH) == month) {
236 selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH);
241 final int enabledDayRangeStart;
242 if (mMinDate.get(Calendar.MONTH) == month && mMinDate.get(Calendar.YEAR) == year) {
243 enabledDayRangeStart = mMinDate.get(Calendar.DAY_OF_MONTH);
245 enabledDayRangeStart = 1;
248 final int enabledDayRangeEnd;
249 if (mMaxDate.get(Calendar.MONTH) == month && mMaxDate.get(Calendar.YEAR) == year) {
250 enabledDayRangeEnd = mMaxDate.get(Calendar.DAY_OF_MONTH);
252 enabledDayRangeEnd = 31;
255 v.setMonthParams(selectedDay, month, year, mFirstDayOfWeek,
256 enabledDayRangeStart, enabledDayRangeEnd);
258 final ViewHolder holder = new ViewHolder(position, itemView, v);
259 mItems.put(position, holder);
261 container.addView(itemView);
267 public void destroyItem(ViewGroup container, int position, Object object) {
268 final ViewHolder holder = (ViewHolder) object;
269 container.removeView(holder.container);
271 mItems.remove(position);
275 public int getItemPosition(Object object) {
276 final ViewHolder holder = (ViewHolder) object;
277 return holder.position;
281 public CharSequence getPageTitle(int position) {
282 final SimpleMonthView v = mItems.get(position).calendar;
289 private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() {
291 public void onDayClick(SimpleMonthView view, Calendar day) {
295 if (mOnDaySelectedListener != null) {
296 mOnDaySelectedListener.onDaySelected(DayPickerPagerAdapter.this, day);
302 private static class ViewHolder {
303 public final int position;
304 public final View container;
305 public final SimpleMonthView calendar;
307 public ViewHolder(int position, View container, SimpleMonthView calendar) {
308 this.position = position;
309 this.container = container;
310 this.calendar = calendar;
314 public interface OnDaySelectedListener {
315 public void onDaySelected(DayPickerPagerAdapter view, Calendar day);