10ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette/*
20ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * Copyright (C) 2015 The Android Open Source Project
30ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette *
40ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * Licensed under the Apache License, Version 2.0 (the "License");
50ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * you may not use this file except in compliance with the License.
60ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * You may obtain a copy of the License at
70ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette *
80ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette *      http://www.apache.org/licenses/LICENSE-2.0
90ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette *
100ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * Unless required by applicable law or agreed to in writing, software
110ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * distributed under the License is distributed on an "AS IS" BASIS,
120ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * See the License for the specific language governing permissions and
140ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * limitations under the License.
150ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette */
160ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
170ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverettepackage android.widget;
180ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1960b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viveretteimport android.annotation.IdRes;
2060b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viveretteimport android.annotation.LayoutRes;
2160b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viveretteimport android.annotation.NonNull;
2260b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viveretteimport android.annotation.Nullable;
230ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.content.Context;
240ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.content.res.ColorStateList;
250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.content.res.TypedArray;
2699441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport android.graphics.Rect;
2768763be41cffbcb4883a0a6293fc1aa9e17a3957Alan Viveretteimport android.icu.util.Calendar;
280ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.util.SparseArray;
2960b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viveretteimport android.view.LayoutInflater;
300ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.view.View;
310ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.view.ViewGroup;
320ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.widget.SimpleMonthView.OnDayClickListener;
330ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
3499441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport com.android.internal.widget.PagerAdapter;
3599441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas
360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette/**
370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * An adapter for a list of {@link android.widget.SimpleMonthView} items.
380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette */
3978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteclass DayPickerPagerAdapter extends PagerAdapter {
400ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private static final int MONTHS_IN_YEAR = 12;
410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
420ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private final Calendar mMinDate = Calendar.getInstance();
430ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private final Calendar mMaxDate = Calendar.getInstance();
440ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
4560b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette    private final SparseArray<ViewHolder> mItems = new SparseArray<>();
460ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
4760b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette    private final LayoutInflater mInflater;
4860b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette    private final int mLayoutResId;
4960b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette    private final int mCalendarViewId;
5060b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette
5160b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette    private Calendar mSelectedDay = null;
520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private int mMonthTextAppearance;
540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private int mDayOfWeekTextAppearance;
550ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private int mDayTextAppearance;
560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
570ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private ColorStateList mCalendarTextColor;
580ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private ColorStateList mDaySelectorColor;
590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private ColorStateList mDayHighlightColor;
600ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private OnDaySelectedListener mOnDaySelectedListener;
620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
6360b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette    private int mCount;
640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private int mFirstDayOfWeek;
650ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
6678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    public DayPickerPagerAdapter(@NonNull Context context, @LayoutRes int layoutResId,
6760b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette            @IdRes int calendarViewId) {
6860b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        mInflater = LayoutInflater.from(context);
6960b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        mLayoutResId = layoutResId;
7060b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        mCalendarViewId = calendarViewId;
7160b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette
720ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final TypedArray ta = context.obtainStyledAttributes(new int[] {
730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                com.android.internal.R.attr.colorControlHighlight});
740ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mDayHighlightColor = ta.getColorStateList(0);
750ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        ta.recycle();
760ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
770ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
7860b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette    public void setRange(@NonNull Calendar min, @NonNull Calendar max) {
790ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mMinDate.setTimeInMillis(min.getTimeInMillis());
800ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mMaxDate.setTimeInMillis(max.getTimeInMillis());
810ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
8260b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
8360b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        final int diffMonth = mMaxDate.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH);
8460b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        mCount = diffMonth + MONTHS_IN_YEAR * diffYear + 1;
8560b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette
860ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Positions are now invalid, clear everything and start over.
870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        notifyDataSetChanged();
880ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
900ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    /**
910ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * Sets the first day of the week.
920ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     *
930ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param weekStart which day the week should start on, valid values are
940ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     *                  {@link Calendar#SUNDAY} through {@link Calendar#SATURDAY}
950ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     */
960ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public void setFirstDayOfWeek(int weekStart) {
970ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mFirstDayOfWeek = weekStart;
980ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
990ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Update displayed views.
1000ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int count = mItems.size();
1010ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        for (int i = 0; i < count; i++) {
10260b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette            final SimpleMonthView monthView = mItems.valueAt(i).calendar;
1030ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            monthView.setFirstDayOfWeek(weekStart);
1040ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
1050ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1060ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1070ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public int getFirstDayOfWeek() {
1080ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return mFirstDayOfWeek;
1090ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1100ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
111698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov    public boolean getBoundsForDate(Calendar day, Rect outBounds) {
112698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        final int position = getPositionForDay(day);
113698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        final ViewHolder monthView = mItems.get(position, null);
114698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        if (monthView == null) {
115698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov            return false;
116698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        } else {
117698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov            final int dayOfMonth = day.get(Calendar.DAY_OF_MONTH);
118698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov            return monthView.calendar.getBoundsForDay(dayOfMonth, outBounds);
119698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        }
120698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov    }
121698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov
1220ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    /**
1230ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * Sets the selected day.
1240ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     *
1250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param day the selected day
1260ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     */
12760b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette    public void setSelectedDay(@Nullable Calendar day) {
1280ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int oldPosition = getPositionForDay(mSelectedDay);
1290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int newPosition = getPositionForDay(day);
1300ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1310ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Clear the old position if necessary.
13260b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        if (oldPosition != newPosition && oldPosition >= 0) {
13360b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette            final ViewHolder oldMonthView = mItems.get(oldPosition, null);
1340ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            if (oldMonthView != null) {
13560b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette                oldMonthView.calendar.setSelectedDay(-1);
1360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            }
1370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
1380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Set the new position.
14060b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        if (newPosition >= 0) {
14160b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette            final ViewHolder newMonthView = mItems.get(newPosition, null);
14260b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette            if (newMonthView != null) {
14360b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette                final int dayOfMonth = day.get(Calendar.DAY_OF_MONTH);
14460b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette                newMonthView.calendar.setSelectedDay(dayOfMonth);
14560b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette            }
1460ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
1470ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1480ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mSelectedDay = day;
1490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1500ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    /**
1520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * Sets the listener to call when the user selects a day.
1530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     *
1540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param listener The listener to call.
1550ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     */
1560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public void setOnDaySelectedListener(OnDaySelectedListener listener) {
1570ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mOnDaySelectedListener = listener;
1580ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1600ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    void setCalendarTextColor(ColorStateList calendarTextColor) {
1610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mCalendarTextColor = calendarTextColor;
162d6d9a94f80f3469d5a1774c4d28ca57223fe1e61Alan Viverette        notifyDataSetChanged();
1630ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1650ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    void setDaySelectorColor(ColorStateList selectorColor) {
1660ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mDaySelectorColor = selectorColor;
167d6d9a94f80f3469d5a1774c4d28ca57223fe1e61Alan Viverette        notifyDataSetChanged();
1680ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1690ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1700ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    void setMonthTextAppearance(int resId) {
1710ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mMonthTextAppearance = resId;
172d6d9a94f80f3469d5a1774c4d28ca57223fe1e61Alan Viverette        notifyDataSetChanged();
1730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1740ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1750ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    void setDayOfWeekTextAppearance(int resId) {
1760ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mDayOfWeekTextAppearance = resId;
177d6d9a94f80f3469d5a1774c4d28ca57223fe1e61Alan Viverette        notifyDataSetChanged();
1780ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1790ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1800ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    int getDayOfWeekTextAppearance() {
1810ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return mDayOfWeekTextAppearance;
1820ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1830ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1840ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    void setDayTextAppearance(int resId) {
1850ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mDayTextAppearance = resId;
186d6d9a94f80f3469d5a1774c4d28ca57223fe1e61Alan Viverette        notifyDataSetChanged();
1870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1880ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    int getDayTextAppearance() {
1900ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return mDayTextAppearance;
1910ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1920ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1930ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    @Override
1940ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public int getCount() {
19560b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        return mCount;
1960ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1970ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1980ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    @Override
1990ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public boolean isViewFromObject(View view, Object object) {
20060b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        final ViewHolder holder = (ViewHolder) object;
20160b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        return view == holder.container;
2020ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2030ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2040ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private int getMonthForPosition(int position) {
205bd51b4d0b930f8c64920954f4f9e5033e0001d5eAlan Viverette        return (position + mMinDate.get(Calendar.MONTH)) % MONTHS_IN_YEAR;
2060ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2070ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2080ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private int getYearForPosition(int position) {
209bd51b4d0b930f8c64920954f4f9e5033e0001d5eAlan Viverette        final int yearOffset = (position + mMinDate.get(Calendar.MONTH)) / MONTHS_IN_YEAR;
210bd51b4d0b930f8c64920954f4f9e5033e0001d5eAlan Viverette        return yearOffset + mMinDate.get(Calendar.YEAR);
2110ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2120ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
21360b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette    private int getPositionForDay(@Nullable Calendar day) {
21460b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        if (day == null) {
21560b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette            return -1;
21660b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        }
21760b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette
218bd51b4d0b930f8c64920954f4f9e5033e0001d5eAlan Viverette        final int yearOffset = day.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
219bd51b4d0b930f8c64920954f4f9e5033e0001d5eAlan Viverette        final int monthOffset = day.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH);
22078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int position = yearOffset * MONTHS_IN_YEAR + monthOffset;
22178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        return position;
2220ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2230ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2240ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    @Override
2250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public Object instantiateItem(ViewGroup container, int position) {
22660b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        final View itemView = mInflater.inflate(mLayoutResId, container, false);
22760b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette
2288e1a72964517bfd01d8e650453ef41e22f770f21Alan Viverette        final SimpleMonthView v = itemView.findViewById(mCalendarViewId);
2290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        v.setOnDayClickListener(mOnDayClickListener);
2300ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        v.setMonthTextAppearance(mMonthTextAppearance);
2310ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        v.setDayOfWeekTextAppearance(mDayOfWeekTextAppearance);
2320ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        v.setDayTextAppearance(mDayTextAppearance);
2330ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2340ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (mDaySelectorColor != null) {
2350ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            v.setDaySelectorColor(mDaySelectorColor);
2360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
2370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (mDayHighlightColor != null) {
2390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            v.setDayHighlightColor(mDayHighlightColor);
2400ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
2410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2420ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (mCalendarTextColor != null) {
2430ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            v.setMonthTextColor(mCalendarTextColor);
2440ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            v.setDayOfWeekTextColor(mCalendarTextColor);
2450ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            v.setDayTextColor(mCalendarTextColor);
2460ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
2470ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2480ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int month = getMonthForPosition(position);
2490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int year = getYearForPosition(position);
2500ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int selectedDay;
25260b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        if (mSelectedDay != null && mSelectedDay.get(Calendar.MONTH) == month) {
2530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH);
2540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        } else {
2550ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            selectedDay = -1;
2560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
2570ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2580ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int enabledDayRangeStart;
2590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (mMinDate.get(Calendar.MONTH) == month && mMinDate.get(Calendar.YEAR) == year) {
2600ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            enabledDayRangeStart = mMinDate.get(Calendar.DAY_OF_MONTH);
2610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        } else {
2620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            enabledDayRangeStart = 1;
2630ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
2640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2650ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int enabledDayRangeEnd;
2660ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (mMaxDate.get(Calendar.MONTH) == month && mMaxDate.get(Calendar.YEAR) == year) {
2670ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            enabledDayRangeEnd = mMaxDate.get(Calendar.DAY_OF_MONTH);
2680ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        } else {
2690ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            enabledDayRangeEnd = 31;
2700ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
2710ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2720ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        v.setMonthParams(selectedDay, month, year, mFirstDayOfWeek,
2730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                enabledDayRangeStart, enabledDayRangeEnd);
2740ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
27560b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        final ViewHolder holder = new ViewHolder(position, itemView, v);
27660b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        mItems.put(position, holder);
2770ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
27860b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        container.addView(itemView);
2790ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
28060b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        return holder;
2810ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2820ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2830ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    @Override
2840ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public void destroyItem(ViewGroup container, int position, Object object) {
28560b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        final ViewHolder holder = (ViewHolder) object;
28660b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        container.removeView(holder.container);
2870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2880ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mItems.remove(position);
2890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2900ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2910ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    @Override
2920ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public int getItemPosition(Object object) {
29360b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        final ViewHolder holder = (ViewHolder) object;
29460b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        return holder.position;
2950ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2960ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2970ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    @Override
2980ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public CharSequence getPageTitle(int position) {
29960b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        final SimpleMonthView v = mItems.get(position).calendar;
3000ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (v != null) {
301e264f9503b8ffcb2cae84e4e5bb2a03dd0610221Alan Viverette            return v.getMonthYearLabel();
3020ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
3030ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return null;
3040ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
3050ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
306e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount    SimpleMonthView getView(Object object) {
307e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        if (object == null) {
308e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount            return null;
309e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        }
310e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        final ViewHolder holder = (ViewHolder) object;
311e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        return holder.calendar;
312e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount    }
313e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount
3140ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() {
3150ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        @Override
3160ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        public void onDayClick(SimpleMonthView view, Calendar day) {
3175c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette            if (day != null) {
3180ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                setSelectedDay(day);
3190ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
3200ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                if (mOnDaySelectedListener != null) {
32178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                    mOnDaySelectedListener.onDaySelected(DayPickerPagerAdapter.this, day);
3220ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                }
3230ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            }
3240ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
3250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    };
3260ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
32760b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette    private static class ViewHolder {
32860b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        public final int position;
32960b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        public final View container;
33060b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        public final SimpleMonthView calendar;
33160b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette
33260b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        public ViewHolder(int position, View container, SimpleMonthView calendar) {
33360b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette            this.position = position;
33460b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette            this.container = container;
33560b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette            this.calendar = calendar;
33660b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        }
33760b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette    }
33860b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette
3390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public interface OnDaySelectedListener {
34078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        public void onDaySelected(DayPickerPagerAdapter view, Calendar day);
3410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
3420ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette}
343