1bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio/*
278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette * Copyright (C) 2015 The Android Open Source Project
3bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio *
4bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * Licensed under the Apache License, Version 2.0 (the "License");
5bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * you may not use this file except in compliance with the License.
6bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * You may obtain a copy of the License at
7bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio *
8bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio *      http://www.apache.org/licenses/LICENSE-2.0
9bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio *
10bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * Unless required by applicable law or agreed to in writing, software
11bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * distributed under the License is distributed on an "AS IS" BASIS,
12bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * See the License for the specific language governing permissions and
14bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * limitations under the License.
15bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio */
16bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
17bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Megliopackage android.widget;
18bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
1978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport android.annotation.Nullable;
20bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.Context;
21bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.ColorStateList;
220ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.content.res.TypedArray;
2399441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport android.graphics.Rect;
2468763be41cffbcb4883a0a6293fc1aa9e17a3957Alan Viveretteimport android.icu.util.Calendar;
250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.util.AttributeSet;
2650eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viveretteimport android.util.MathUtils;
2778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport android.view.LayoutInflater;
28816aa142023c75cf427401c21831193998bdf233Alan Viveretteimport android.view.View;
2978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport android.view.ViewGroup;
3078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport android.view.accessibility.AccessibilityManager;
31bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
3299441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport com.android.internal.R;
3399441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport com.android.internal.widget.ViewPager;
3499441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport com.android.internal.widget.ViewPager.OnPageChangeListener;
35bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport libcore.icu.LocaleData;
370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
3899441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport java.util.Locale;
3999441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas
4078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteclass DayPickerView extends ViewGroup {
4178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private static final int DEFAULT_LAYOUT = R.layout.day_picker_content_material;
420ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private static final int DEFAULT_START_YEAR = 1900;
430ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private static final int DEFAULT_END_YEAR = 2100;
44bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
4578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private static final int[] ATTRS_TEXT_COLOR = new int[] { R.attr.textColor };
4678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
470ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private final Calendar mSelectedDay = Calendar.getInstance();
480ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private final Calendar mMinDate = Calendar.getInstance();
490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private final Calendar mMaxDate = Calendar.getInstance();
50bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
5178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final AccessibilityManager mAccessibilityManager;
5278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
5378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final ViewPager mViewPager;
5478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final ImageButton mPrevButton;
5578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final ImageButton mNextButton;
56816aa142023c75cf427401c21831193998bdf233Alan Viverette
5778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final DayPickerPagerAdapter mAdapter;
58bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    /** Temporary calendar used for date calculations. */
600ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private Calendar mTempCalendar;
61bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private OnDaySelectedListener mOnDaySelectedListener;
63e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette
640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public DayPickerView(Context context) {
650ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        this(context, null);
660ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
67bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
6878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    public DayPickerView(Context context, @Nullable AttributeSet attrs) {
690ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        this(context, attrs, R.attr.calendarViewStyle);
700ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
71bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
7278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    public DayPickerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        this(context, attrs, defStyleAttr, 0);
740ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
7550eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette
7678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    public DayPickerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
7778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            int defStyleRes) {
780ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        super(context, attrs, defStyleAttr, defStyleRes);
794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
8078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
8178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                Context.ACCESSIBILITY_SERVICE);
8278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
830ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final TypedArray a = context.obtainStyledAttributes(attrs,
840ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.styleable.CalendarView, defStyleAttr, defStyleRes);
85bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
860ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int firstDayOfWeek = a.getInt(R.styleable.CalendarView_firstDayOfWeek,
870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                LocaleData.get(Locale.getDefault()).firstDayOfWeek);
88bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final String minDate = a.getString(R.styleable.CalendarView_minDate);
900ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final String maxDate = a.getString(R.styleable.CalendarView_maxDate);
91bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
920ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int monthTextAppearanceResId = a.getResourceId(
930ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.styleable.CalendarView_monthTextAppearance,
940ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.style.TextAppearance_Material_Widget_Calendar_Month);
950ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int dayOfWeekTextAppearanceResId = a.getResourceId(
960ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.styleable.CalendarView_weekDayTextAppearance,
970ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.style.TextAppearance_Material_Widget_Calendar_DayOfWeek);
980ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int dayTextAppearanceResId = a.getResourceId(
990ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.styleable.CalendarView_dateTextAppearance,
1000ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.style.TextAppearance_Material_Widget_Calendar_Day);
1010ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1020ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final ColorStateList daySelectorColor = a.getColorStateList(
1030ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.styleable.CalendarView_daySelectorColor);
1040ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1050ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        a.recycle();
1060ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1070ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Set up adapter.
10878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mAdapter = new DayPickerPagerAdapter(context,
10960b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette                R.layout.date_picker_month_item_material, R.id.month_view);
1100ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mAdapter.setMonthTextAppearance(monthTextAppearanceResId);
1110ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mAdapter.setDayOfWeekTextAppearance(dayOfWeekTextAppearanceResId);
1120ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mAdapter.setDayTextAppearance(dayTextAppearanceResId);
1130ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mAdapter.setDaySelectorColor(daySelectorColor);
11450eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette
11578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final LayoutInflater inflater = LayoutInflater.from(context);
11678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final ViewGroup content = (ViewGroup) inflater.inflate(DEFAULT_LAYOUT, this, false);
11778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
11878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        // Transfer all children from content to here.
11978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        while (content.getChildCount() > 0) {
12078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final View child = content.getChildAt(0);
12178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            content.removeViewAt(0);
12278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            addView(child);
12378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        }
12478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
12551efddbd3bb304de2dd47fa8cd1114ac555958bbAlan Viverette        mPrevButton = findViewById(R.id.prev);
12678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mPrevButton.setOnClickListener(mOnClickListener);
12778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
12851efddbd3bb304de2dd47fa8cd1114ac555958bbAlan Viverette        mNextButton = findViewById(R.id.next);
12978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mNextButton.setOnClickListener(mOnClickListener);
13078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
13151efddbd3bb304de2dd47fa8cd1114ac555958bbAlan Viverette        mViewPager = findViewById(R.id.day_picker_view_pager);
13278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mViewPager.setAdapter(mAdapter);
13378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mViewPager.setOnPageChangeListener(mOnPageChangedListener);
13478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
13578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        // Proxy the month text color into the previous and next buttons.
13678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        if (monthTextAppearanceResId != 0) {
13778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final TypedArray ta = mContext.obtainStyledAttributes(null,
13878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                    ATTRS_TEXT_COLOR, 0, monthTextAppearanceResId);
13978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final ColorStateList monthColor = ta.getColorStateList(0);
14078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            if (monthColor != null) {
14178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                mPrevButton.setImageTintList(monthColor);
14278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                mNextButton.setImageTintList(monthColor);
14378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            }
14478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            ta.recycle();
14578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        }
146e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette
1470ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Set up min and max dates.
1480ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final Calendar tempDate = Calendar.getInstance();
1490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (!CalendarView.parseDate(minDate, tempDate)) {
1500ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            tempDate.set(DEFAULT_START_YEAR, Calendar.JANUARY, 1);
1510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
1520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final long minDateMillis = tempDate.getTimeInMillis();
1530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (!CalendarView.parseDate(maxDate, tempDate)) {
1550ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            tempDate.set(DEFAULT_END_YEAR, Calendar.DECEMBER, 31);
1560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
1570ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final long maxDateMillis = tempDate.getTimeInMillis();
1580ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (maxDateMillis < minDateMillis) {
1600ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            throw new IllegalArgumentException("maxDate must be >= minDate");
1610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
1620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1630ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final long setDateMillis = MathUtils.constrain(
1640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                System.currentTimeMillis(), minDateMillis, maxDateMillis);
165e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette
1660ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setFirstDayOfWeek(firstDayOfWeek);
1670ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setMinDate(minDateMillis);
1680ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setMaxDate(maxDateMillis);
1690ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setDate(setDateMillis, false);
1700ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1710ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Proxy selection callbacks to our own listener.
17278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mAdapter.setOnDaySelectedListener(new DayPickerPagerAdapter.OnDaySelectedListener() {
1730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            @Override
17478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            public void onDaySelected(DayPickerPagerAdapter adapter, Calendar day) {
1750ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                if (mOnDaySelectedListener != null) {
1760ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    mOnDaySelectedListener.onDaySelected(DayPickerView.this, day);
1770ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                }
1780ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            }
1790ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        });
1800ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1810ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1825c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette    private void updateButtonVisibility(int position) {
1835c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette        final boolean hasPrev = position > 0;
1845c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette        final boolean hasNext = position < (mAdapter.getCount() - 1);
1855c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette        mPrevButton.setVisibility(hasPrev ? View.VISIBLE : View.INVISIBLE);
1865c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette        mNextButton.setVisibility(hasNext ? View.VISIBLE : View.INVISIBLE);
1875c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette    }
1885c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette
189816aa142023c75cf427401c21831193998bdf233Alan Viverette    @Override
190816aa142023c75cf427401c21831193998bdf233Alan Viverette    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final ViewPager viewPager = mViewPager;
19278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        measureChild(viewPager, widthMeasureSpec, heightMeasureSpec);
19378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
19478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int measuredWidthAndState = viewPager.getMeasuredWidthAndState();
19578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int measuredHeightAndState = viewPager.getMeasuredHeightAndState();
19678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        setMeasuredDimension(measuredWidthAndState, measuredHeightAndState);
19778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
19878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int pagerWidth = viewPager.getMeasuredWidth();
19978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int pagerHeight = viewPager.getMeasuredHeight();
20078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int buttonWidthSpec = MeasureSpec.makeMeasureSpec(pagerWidth, MeasureSpec.AT_MOST);
20178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int buttonHeightSpec = MeasureSpec.makeMeasureSpec(pagerHeight, MeasureSpec.AT_MOST);
20278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mPrevButton.measure(buttonWidthSpec, buttonHeightSpec);
20378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mNextButton.measure(buttonWidthSpec, buttonHeightSpec);
20478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    }
205816aa142023c75cf427401c21831193998bdf233Alan Viverette
20678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    @Override
207ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
208ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette        super.onRtlPropertiesChanged(layoutDirection);
209ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette
210ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette        requestLayout();
211ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette    }
212ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette
213ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette    @Override
21478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
215ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette        final ImageButton leftButton;
216ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette        final ImageButton rightButton;
217ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette        if (isLayoutRtl()) {
218ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette            leftButton = mNextButton;
219ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette            rightButton = mPrevButton;
220ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette        } else {
221ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette            leftButton = mPrevButton;
222ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette            rightButton = mNextButton;
223ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette        }
22478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
22578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int width = right - left;
22678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int height = bottom - top;
22778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mViewPager.layout(0, 0, width, height);
22878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
22978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final SimpleMonthView monthView = (SimpleMonthView) mViewPager.getChildAt(0);
23078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int monthHeight = monthView.getMonthHeight();
23178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int cellWidth = monthView.getCellWidth();
23278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
23378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        // Vertically center the previous/next buttons within the month
23478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        // header, horizontally center within the day cell.
23578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int leftDW = leftButton.getMeasuredWidth();
23678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int leftDH = leftButton.getMeasuredHeight();
23778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int leftIconTop = monthView.getPaddingTop() + (monthHeight - leftDH) / 2;
23878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int leftIconLeft = monthView.getPaddingLeft() + (cellWidth - leftDW) / 2;
23978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        leftButton.layout(leftIconLeft, leftIconTop, leftIconLeft + leftDW, leftIconTop + leftDH);
24078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
24178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int rightDW = rightButton.getMeasuredWidth();
24278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int rightDH = rightButton.getMeasuredHeight();
24378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int rightIconTop = monthView.getPaddingTop() + (monthHeight - rightDH) / 2;
24478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int rightIconRight = width - monthView.getPaddingRight() - (cellWidth - rightDW) / 2;
24578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        rightButton.layout(rightIconRight - rightDW, rightIconTop,
24678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                rightIconRight, rightIconTop + rightDH);
247816aa142023c75cf427401c21831193998bdf233Alan Viverette    }
248816aa142023c75cf427401c21831193998bdf233Alan Viverette
2490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public void setDayOfWeekTextAppearance(int resId) {
2500ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mAdapter.setDayOfWeekTextAppearance(resId);
2510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public int getDayOfWeekTextAppearance() {
2540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return mAdapter.getDayOfWeekTextAppearance();
2550ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2570ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public void setDayTextAppearance(int resId) {
2580ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mAdapter.setDayTextAppearance(resId);
2590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2600ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public int getDayTextAppearance() {
2620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return mAdapter.getDayTextAppearance();
263e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette    }
264e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette
2654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    /**
2664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette     * Sets the currently selected date to the specified timestamp. Jumps
2674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette     * immediately to the new date. To animate to the new date, use
2680ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * {@link #setDate(long, boolean)}.
2694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette     *
2700ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param timeInMillis the target day in milliseconds
2714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette     */
2724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public void setDate(long timeInMillis) {
2730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setDate(timeInMillis, false);
2744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
2754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
2760ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    /**
2770ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * Sets the currently selected date to the specified timestamp. Jumps
2780ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * immediately to the new date, optionally animating the transition.
2790ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     *
2800ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param timeInMillis the target day in milliseconds
2810ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param animate whether to smooth scroll to the new position
2820ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     */
2830ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public void setDate(long timeInMillis, boolean animate) {
2840ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setDate(timeInMillis, animate, true);
2850ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2860ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    /**
2880ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * Moves to the month containing the specified day, optionally setting the
2890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * day as selected.
2900ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     *
2910ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param timeInMillis the target day in milliseconds
2920ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param animate whether to smooth scroll to the new position
2930ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param setSelected whether to set the specified day as selected
2940ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     */
2950ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private void setDate(long timeInMillis, boolean animate, boolean setSelected) {
296e565e525fadbe7bed7c3c5a47331ba1ea3d1f0beAndrei Stingaceanu        boolean dateClamped = false;
297e565e525fadbe7bed7c3c5a47331ba1ea3d1f0beAndrei Stingaceanu        // Clamp the target day in milliseconds to the min or max if outside the range.
298e565e525fadbe7bed7c3c5a47331ba1ea3d1f0beAndrei Stingaceanu        if (timeInMillis < mMinDate.getTimeInMillis()) {
299e565e525fadbe7bed7c3c5a47331ba1ea3d1f0beAndrei Stingaceanu            timeInMillis = mMinDate.getTimeInMillis();
300e565e525fadbe7bed7c3c5a47331ba1ea3d1f0beAndrei Stingaceanu            dateClamped = true;
301e565e525fadbe7bed7c3c5a47331ba1ea3d1f0beAndrei Stingaceanu        } else if (timeInMillis > mMaxDate.getTimeInMillis()) {
302e565e525fadbe7bed7c3c5a47331ba1ea3d1f0beAndrei Stingaceanu            timeInMillis = mMaxDate.getTimeInMillis();
303e565e525fadbe7bed7c3c5a47331ba1ea3d1f0beAndrei Stingaceanu            dateClamped = true;
304e565e525fadbe7bed7c3c5a47331ba1ea3d1f0beAndrei Stingaceanu        }
305e565e525fadbe7bed7c3c5a47331ba1ea3d1f0beAndrei Stingaceanu
30695331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu        getTempCalendarForTime(timeInMillis);
30795331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu
308e565e525fadbe7bed7c3c5a47331ba1ea3d1f0beAndrei Stingaceanu        if (setSelected || dateClamped) {
3090ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            mSelectedDay.setTimeInMillis(timeInMillis);
3100ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
3110ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
3120ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int position = getPositionFromDay(timeInMillis);
31378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        if (position != mViewPager.getCurrentItem()) {
31478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            mViewPager.setCurrentItem(position, animate);
3150ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
316f63757b7a6d06138860640f8e95326dc1ff47646Alan Viverette
317f63757b7a6d06138860640f8e95326dc1ff47646Alan Viverette        mAdapter.setSelectedDay(mTempCalendar);
3184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
3194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
3204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public long getDate() {
3214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        return mSelectedDay.getTimeInMillis();
322e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette    }
323e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette
324698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov    public boolean getBoundsForDate(long timeInMillis, Rect outBounds) {
325698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        final int position = getPositionFromDay(timeInMillis);
326698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        if (position != mViewPager.getCurrentItem()) {
327698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov            return false;
328698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        }
329698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov
330698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        mTempCalendar.setTimeInMillis(timeInMillis);
331698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        return mAdapter.getBoundsForDate(mTempCalendar, outBounds);
332698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov    }
333698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov
334e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette    public void setFirstDayOfWeek(int firstDayOfWeek) {
335e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette        mAdapter.setFirstDayOfWeek(firstDayOfWeek);
336bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
337bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
3384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public int getFirstDayOfWeek() {
3394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        return mAdapter.getFirstDayOfWeek();
3404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
3414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
3424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public void setMinDate(long timeInMillis) {
3434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        mMinDate.setTimeInMillis(timeInMillis);
3444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        onRangeChanged();
3454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
3464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
3474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public long getMinDate() {
3484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        return mMinDate.getTimeInMillis();
3494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
3504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
3514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public void setMaxDate(long timeInMillis) {
3524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        mMaxDate.setTimeInMillis(timeInMillis);
3534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        onRangeChanged();
3544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
35550eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette
3564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public long getMaxDate() {
3574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        return mMaxDate.getTimeInMillis();
3584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
3594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
3604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    /**
3614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette     * Handles changes to date range.
3624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette     */
3634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public void onRangeChanged() {
36450eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette        mAdapter.setRange(mMinDate, mMaxDate);
36550eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette
3665ecbfeb38b6bdcfe8f3561f8cdcb4af9ba30c886Alan Viverette        // Changing the min/max date changes the selection position since we
3674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        // don't really have stable IDs. Jumps immediately to the new position.
3680ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setDate(mSelectedDay.getTimeInMillis(), false, false);
369bd51b4d0b930f8c64920954f4f9e5033e0001d5eAlan Viverette
370bd51b4d0b930f8c64920954f4f9e5033e0001d5eAlan Viverette        updateButtonVisibility(mViewPager.getCurrentItem());
37150eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette    }
37250eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette
37350eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette    /**
374e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette     * Sets the listener to call when the user selects a day.
37550eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette     *
376e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette     * @param listener The listener to call.
377bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio     */
378e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette    public void setOnDaySelectedListener(OnDaySelectedListener listener) {
379e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette        mOnDaySelectedListener = listener;
380bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
381bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
38250eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette    private int getDiffMonths(Calendar start, Calendar end) {
383bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        final int diffYears = end.get(Calendar.YEAR) - start.get(Calendar.YEAR);
3840ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return end.get(Calendar.MONTH) - start.get(Calendar.MONTH) + 12 * diffYears;
385bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
386bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
3874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    private int getPositionFromDay(long timeInMillis) {
38850eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette        final int diffMonthMax = getDiffMonths(mMinDate, mMaxDate);
3894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        final int diffMonth = getDiffMonths(mMinDate, getTempCalendarForTime(timeInMillis));
39050eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette        return MathUtils.constrain(diffMonth, 0, diffMonthMax);
391bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
392bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
3934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    private Calendar getTempCalendarForTime(long timeInMillis) {
3944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        if (mTempCalendar == null) {
3954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette            mTempCalendar = Calendar.getInstance();
3964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        }
3974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        mTempCalendar.setTimeInMillis(timeInMillis);
3984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        return mTempCalendar;
3994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
4004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
401bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    /**
402bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio     * Gets the position of the view that is most prominently displayed within the list view.
403bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio     */
404bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public int getMostVisiblePosition() {
40578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        return mViewPager.getCurrentItem();
406bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
407e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette
40878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    public void setPosition(int position) {
40978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mViewPager.setCurrentItem(position, false);
41078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    }
41178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
41278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final OnPageChangeListener mOnPageChangedListener = new OnPageChangeListener() {
41378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        @Override
41478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
41578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final float alpha = Math.abs(0.5f - positionOffset) * 2.0f;
41678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            mPrevButton.setAlpha(alpha);
41778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            mNextButton.setAlpha(alpha);
41878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        }
41978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
42078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        @Override
42178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        public void onPageScrollStateChanged(int state) {}
42278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
42378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        @Override
42478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        public void onPageSelected(int position) {
4255c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette            updateButtonVisibility(position);
42678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        }
42778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    };
42878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
42978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final OnClickListener mOnClickListener = new OnClickListener() {
43078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        @Override
43178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        public void onClick(View v) {
43278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final int direction;
43378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            if (v == mPrevButton) {
43478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                direction = -1;
43578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            } else if (v == mNextButton) {
43678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                direction = 1;
43778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            } else {
43878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                return;
43978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            }
44078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
44178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            // Animation is expensive for accessibility services since it sends
44278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            // lots of scroll and content change events.
44378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final boolean animate = !mAccessibilityManager.isEnabled();
44478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
44578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            // ViewPager clamps input values, so we don't need to worry
44678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            // about passing invalid indices.
44778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final int nextItem = mViewPager.getCurrentItem() + direction;
44878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            mViewPager.setCurrentItem(nextItem, animate);
44978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        }
45078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    };
45178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
452e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette    public interface OnDaySelectedListener {
45378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        void onDaySelected(DayPickerView view, Calendar day);
454e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette    }
455bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio}
456