DayPickerView.java revision 95331038c3eea07af17cb8c64574b6516612548c
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
1995331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanuimport static android.os.Build.VERSION_CODES.N_MR1;
2095331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu
21698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikovimport android.graphics.Rect;
220ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport com.android.internal.R;
2378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport com.android.internal.widget.ViewPager;
2478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport com.android.internal.widget.ViewPager.OnPageChangeListener;
250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport android.annotation.Nullable;
27bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.Context;
28bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.ColorStateList;
290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.content.res.TypedArray;
3068763be41cffbcb4883a0a6293fc1aa9e17a3957Alan Viveretteimport android.icu.util.Calendar;
310ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.util.AttributeSet;
3250eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viveretteimport android.util.MathUtils;
3378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport android.view.LayoutInflater;
34816aa142023c75cf427401c21831193998bdf233Alan Viveretteimport android.view.View;
3578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport android.view.ViewGroup;
3678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport android.view.accessibility.AccessibilityManager;
37bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
38bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport java.util.Locale;
39bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
400ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport libcore.icu.LocaleData;
410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
4278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteclass DayPickerView extends ViewGroup {
4378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private static final int DEFAULT_LAYOUT = R.layout.day_picker_content_material;
440ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private static final int DEFAULT_START_YEAR = 1900;
450ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private static final int DEFAULT_END_YEAR = 2100;
46bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
4778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private static final int[] ATTRS_TEXT_COLOR = new int[] { R.attr.textColor };
4878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private final Calendar mSelectedDay = Calendar.getInstance();
500ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private final Calendar mMinDate = Calendar.getInstance();
510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private final Calendar mMaxDate = Calendar.getInstance();
52bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
5378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final AccessibilityManager mAccessibilityManager;
5478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
5578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final ViewPager mViewPager;
5678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final ImageButton mPrevButton;
5778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final ImageButton mNextButton;
58816aa142023c75cf427401c21831193998bdf233Alan Viverette
5978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final DayPickerPagerAdapter mAdapter;
60bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    /** Temporary calendar used for date calculations. */
620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private Calendar mTempCalendar;
63bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private OnDaySelectedListener mOnDaySelectedListener;
65e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette
660ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public DayPickerView(Context context) {
670ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        this(context, null);
680ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
69bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
7078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    public DayPickerView(Context context, @Nullable AttributeSet attrs) {
710ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        this(context, attrs, R.attr.calendarViewStyle);
720ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
73bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
7478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    public DayPickerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
750ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        this(context, attrs, defStyleAttr, 0);
760ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
7750eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette
7878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    public DayPickerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
7978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            int defStyleRes) {
800ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        super(context, attrs, defStyleAttr, defStyleRes);
814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
8278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
8378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                Context.ACCESSIBILITY_SERVICE);
8478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
850ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final TypedArray a = context.obtainStyledAttributes(attrs,
860ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.styleable.CalendarView, defStyleAttr, defStyleRes);
87bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
880ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int firstDayOfWeek = a.getInt(R.styleable.CalendarView_firstDayOfWeek,
890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                LocaleData.get(Locale.getDefault()).firstDayOfWeek);
90bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
910ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final String minDate = a.getString(R.styleable.CalendarView_minDate);
920ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final String maxDate = a.getString(R.styleable.CalendarView_maxDate);
93bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
940ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int monthTextAppearanceResId = a.getResourceId(
950ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.styleable.CalendarView_monthTextAppearance,
960ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.style.TextAppearance_Material_Widget_Calendar_Month);
970ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int dayOfWeekTextAppearanceResId = a.getResourceId(
980ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.styleable.CalendarView_weekDayTextAppearance,
990ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.style.TextAppearance_Material_Widget_Calendar_DayOfWeek);
1000ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int dayTextAppearanceResId = a.getResourceId(
1010ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.styleable.CalendarView_dateTextAppearance,
1020ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.style.TextAppearance_Material_Widget_Calendar_Day);
1030ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1040ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final ColorStateList daySelectorColor = a.getColorStateList(
1050ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.styleable.CalendarView_daySelectorColor);
1060ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1070ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        a.recycle();
1080ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1090ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Set up adapter.
11078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mAdapter = new DayPickerPagerAdapter(context,
11160b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette                R.layout.date_picker_month_item_material, R.id.month_view);
1120ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mAdapter.setMonthTextAppearance(monthTextAppearanceResId);
1130ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mAdapter.setDayOfWeekTextAppearance(dayOfWeekTextAppearanceResId);
1140ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mAdapter.setDayTextAppearance(dayTextAppearanceResId);
1150ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mAdapter.setDaySelectorColor(daySelectorColor);
11650eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette
11778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final LayoutInflater inflater = LayoutInflater.from(context);
11878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final ViewGroup content = (ViewGroup) inflater.inflate(DEFAULT_LAYOUT, this, false);
11978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
12078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        // Transfer all children from content to here.
12178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        while (content.getChildCount() > 0) {
12278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final View child = content.getChildAt(0);
12378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            content.removeViewAt(0);
12478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            addView(child);
12578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        }
12678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
12778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mPrevButton = (ImageButton) findViewById(R.id.prev);
12878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mPrevButton.setOnClickListener(mOnClickListener);
12978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
13078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mNextButton = (ImageButton) findViewById(R.id.next);
13178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mNextButton.setOnClickListener(mOnClickListener);
13278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
13378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mViewPager = (ViewPager) findViewById(R.id.day_picker_view_pager);
13478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mViewPager.setAdapter(mAdapter);
13578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mViewPager.setOnPageChangeListener(mOnPageChangedListener);
13678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
13778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        // Proxy the month text color into the previous and next buttons.
13878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        if (monthTextAppearanceResId != 0) {
13978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final TypedArray ta = mContext.obtainStyledAttributes(null,
14078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                    ATTRS_TEXT_COLOR, 0, monthTextAppearanceResId);
14178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final ColorStateList monthColor = ta.getColorStateList(0);
14278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            if (monthColor != null) {
14378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                mPrevButton.setImageTintList(monthColor);
14478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                mNextButton.setImageTintList(monthColor);
14578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            }
14678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            ta.recycle();
14778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        }
148e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette
1490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Set up min and max dates.
1500ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final Calendar tempDate = Calendar.getInstance();
1510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (!CalendarView.parseDate(minDate, tempDate)) {
1520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            tempDate.set(DEFAULT_START_YEAR, Calendar.JANUARY, 1);
1530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
1540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final long minDateMillis = tempDate.getTimeInMillis();
1550ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (!CalendarView.parseDate(maxDate, tempDate)) {
1570ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            tempDate.set(DEFAULT_END_YEAR, Calendar.DECEMBER, 31);
1580ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
1590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final long maxDateMillis = tempDate.getTimeInMillis();
1600ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (maxDateMillis < minDateMillis) {
1620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            throw new IllegalArgumentException("maxDate must be >= minDate");
1630ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
1640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1650ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final long setDateMillis = MathUtils.constrain(
1660ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                System.currentTimeMillis(), minDateMillis, maxDateMillis);
167e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette
1680ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setFirstDayOfWeek(firstDayOfWeek);
1690ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setMinDate(minDateMillis);
1700ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setMaxDate(maxDateMillis);
1710ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setDate(setDateMillis, false);
1720ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Proxy selection callbacks to our own listener.
17478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mAdapter.setOnDaySelectedListener(new DayPickerPagerAdapter.OnDaySelectedListener() {
1750ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            @Override
17678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            public void onDaySelected(DayPickerPagerAdapter adapter, Calendar day) {
1770ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                if (mOnDaySelectedListener != null) {
1780ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    mOnDaySelectedListener.onDaySelected(DayPickerView.this, day);
1790ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                }
1800ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            }
1810ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        });
1820ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1830ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1845c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette    private void updateButtonVisibility(int position) {
1855c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette        final boolean hasPrev = position > 0;
1865c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette        final boolean hasNext = position < (mAdapter.getCount() - 1);
1875c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette        mPrevButton.setVisibility(hasPrev ? View.VISIBLE : View.INVISIBLE);
1885c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette        mNextButton.setVisibility(hasNext ? View.VISIBLE : View.INVISIBLE);
1895c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette    }
1905c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette
191816aa142023c75cf427401c21831193998bdf233Alan Viverette    @Override
192816aa142023c75cf427401c21831193998bdf233Alan Viverette    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final ViewPager viewPager = mViewPager;
19478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        measureChild(viewPager, widthMeasureSpec, heightMeasureSpec);
19578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
19678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int measuredWidthAndState = viewPager.getMeasuredWidthAndState();
19778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int measuredHeightAndState = viewPager.getMeasuredHeightAndState();
19878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        setMeasuredDimension(measuredWidthAndState, measuredHeightAndState);
19978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
20078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int pagerWidth = viewPager.getMeasuredWidth();
20178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int pagerHeight = viewPager.getMeasuredHeight();
20278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int buttonWidthSpec = MeasureSpec.makeMeasureSpec(pagerWidth, MeasureSpec.AT_MOST);
20378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int buttonHeightSpec = MeasureSpec.makeMeasureSpec(pagerHeight, MeasureSpec.AT_MOST);
20478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mPrevButton.measure(buttonWidthSpec, buttonHeightSpec);
20578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mNextButton.measure(buttonWidthSpec, buttonHeightSpec);
20678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    }
207816aa142023c75cf427401c21831193998bdf233Alan Viverette
20878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    @Override
209ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
210ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette        super.onRtlPropertiesChanged(layoutDirection);
211ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette
212ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette        requestLayout();
213ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette    }
214ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette
215ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette    @Override
21678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
217ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette        final ImageButton leftButton;
218ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette        final ImageButton rightButton;
219ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette        if (isLayoutRtl()) {
220ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette            leftButton = mNextButton;
221ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette            rightButton = mPrevButton;
222ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette        } else {
223ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette            leftButton = mPrevButton;
224ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette            rightButton = mNextButton;
225ddf655c49f4173aa55c9ba1a2622cf75cf5bc2f2Alan Viverette        }
22678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
22778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int width = right - left;
22878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int height = bottom - top;
22978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mViewPager.layout(0, 0, width, height);
23078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
23178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final SimpleMonthView monthView = (SimpleMonthView) mViewPager.getChildAt(0);
23278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int monthHeight = monthView.getMonthHeight();
23378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int cellWidth = monthView.getCellWidth();
23478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
23578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        // Vertically center the previous/next buttons within the month
23678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        // header, horizontally center within the day cell.
23778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int leftDW = leftButton.getMeasuredWidth();
23878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int leftDH = leftButton.getMeasuredHeight();
23978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int leftIconTop = monthView.getPaddingTop() + (monthHeight - leftDH) / 2;
24078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int leftIconLeft = monthView.getPaddingLeft() + (cellWidth - leftDW) / 2;
24178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        leftButton.layout(leftIconLeft, leftIconTop, leftIconLeft + leftDW, leftIconTop + leftDH);
24278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
24378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int rightDW = rightButton.getMeasuredWidth();
24478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int rightDH = rightButton.getMeasuredHeight();
24578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int rightIconTop = monthView.getPaddingTop() + (monthHeight - rightDH) / 2;
24678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final int rightIconRight = width - monthView.getPaddingRight() - (cellWidth - rightDW) / 2;
24778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        rightButton.layout(rightIconRight - rightDW, rightIconTop,
24878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                rightIconRight, rightIconTop + rightDH);
249816aa142023c75cf427401c21831193998bdf233Alan Viverette    }
250816aa142023c75cf427401c21831193998bdf233Alan Viverette
2510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public void setDayOfWeekTextAppearance(int resId) {
2520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mAdapter.setDayOfWeekTextAppearance(resId);
2530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2550ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public int getDayOfWeekTextAppearance() {
2560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return mAdapter.getDayOfWeekTextAppearance();
2570ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2580ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public void setDayTextAppearance(int resId) {
2600ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mAdapter.setDayTextAppearance(resId);
2610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2630ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public int getDayTextAppearance() {
2640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return mAdapter.getDayTextAppearance();
265e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette    }
266e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette
2674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    /**
2684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette     * Sets the currently selected date to the specified timestamp. Jumps
2694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette     * immediately to the new date. To animate to the new date, use
2700ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * {@link #setDate(long, boolean)}.
2714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette     *
2720ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param timeInMillis the target day in milliseconds
2734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette     */
2744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public void setDate(long timeInMillis) {
2750ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setDate(timeInMillis, false);
2764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
2774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
2780ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    /**
2790ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * Sets the currently selected date to the specified timestamp. Jumps
2800ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * immediately to the new date, optionally animating the transition.
2810ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     *
2820ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param timeInMillis the target day in milliseconds
2830ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param animate whether to smooth scroll to the new position
2840ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     */
2850ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    public void setDate(long timeInMillis, boolean animate) {
2860ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setDate(timeInMillis, animate, true);
2870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
2880ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    /**
2900ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * Moves to the month containing the specified day, optionally setting the
2910ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * day as selected.
2920ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     *
2930ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param timeInMillis the target day in milliseconds
2940ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param animate whether to smooth scroll to the new position
2950ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param setSelected whether to set the specified day as selected
29695331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu     *
29795331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu     * @throws IllegalArgumentException as of {@link android.os.Build.VERSION_CODES#N_MR1} if the
29895331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu     *         provided timeInMillis is before the range start or after the range end.
2990ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     */
3000ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private void setDate(long timeInMillis, boolean animate, boolean setSelected) {
30195331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu        getTempCalendarForTime(timeInMillis);
30295331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu
30395331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu        final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
30495331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu        if (targetSdkVersion >= N_MR1) {
30595331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu            if (mTempCalendar.before(mMinDate) || mTempCalendar.after(mMaxDate)) {
30695331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu                throw new IllegalArgumentException("timeInMillis must be between the values of "
30795331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu                        + "getMinDate() and getMaxDate()");
30895331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu            }
30995331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu        }
31095331038c3eea07af17cb8c64574b6516612548cAndrei Stingaceanu
3110ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (setSelected) {
3120ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            mSelectedDay.setTimeInMillis(timeInMillis);
3130ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
3140ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
3150ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int position = getPositionFromDay(timeInMillis);
31678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        if (position != mViewPager.getCurrentItem()) {
31778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            mViewPager.setCurrentItem(position, animate);
3180ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
319f63757b7a6d06138860640f8e95326dc1ff47646Alan Viverette
320f63757b7a6d06138860640f8e95326dc1ff47646Alan Viverette        mAdapter.setSelectedDay(mTempCalendar);
3214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
3224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
3234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public long getDate() {
3244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        return mSelectedDay.getTimeInMillis();
325e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette    }
326e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette
327698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov    public boolean getBoundsForDate(long timeInMillis, Rect outBounds) {
328698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        final int position = getPositionFromDay(timeInMillis);
329698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        if (position != mViewPager.getCurrentItem()) {
330698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov            return false;
331698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        }
332698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov
333698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        mTempCalendar.setTimeInMillis(timeInMillis);
334698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov        return mAdapter.getBoundsForDate(mTempCalendar, outBounds);
335698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov    }
336698b751dc78f8a325c5b513cacd3335151f807eaKirill Grouchnikov
337e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette    public void setFirstDayOfWeek(int firstDayOfWeek) {
338e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette        mAdapter.setFirstDayOfWeek(firstDayOfWeek);
339bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
340bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
3414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public int getFirstDayOfWeek() {
3424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        return mAdapter.getFirstDayOfWeek();
3434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
3444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
3454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public void setMinDate(long timeInMillis) {
3464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        mMinDate.setTimeInMillis(timeInMillis);
3474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        onRangeChanged();
3484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
3494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
3504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public long getMinDate() {
3514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        return mMinDate.getTimeInMillis();
3524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
3534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
3544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public void setMaxDate(long timeInMillis) {
3554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        mMaxDate.setTimeInMillis(timeInMillis);
3564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        onRangeChanged();
3574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
35850eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette
3594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public long getMaxDate() {
3604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        return mMaxDate.getTimeInMillis();
3614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
3624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
3634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    /**
3644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette     * Handles changes to date range.
3654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette     */
3664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    public void onRangeChanged() {
36750eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette        mAdapter.setRange(mMinDate, mMaxDate);
36850eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette
3695ecbfeb38b6bdcfe8f3561f8cdcb4af9ba30c886Alan Viverette        // Changing the min/max date changes the selection position since we
3704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        // don't really have stable IDs. Jumps immediately to the new position.
3710ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setDate(mSelectedDay.getTimeInMillis(), false, false);
372bd51b4d0b930f8c64920954f4f9e5033e0001d5eAlan Viverette
373bd51b4d0b930f8c64920954f4f9e5033e0001d5eAlan Viverette        updateButtonVisibility(mViewPager.getCurrentItem());
37450eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette    }
37550eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette
37650eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette    /**
377e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette     * Sets the listener to call when the user selects a day.
37850eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette     *
379e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette     * @param listener The listener to call.
380bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio     */
381e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette    public void setOnDaySelectedListener(OnDaySelectedListener listener) {
382e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette        mOnDaySelectedListener = listener;
383bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
384bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
38550eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette    private int getDiffMonths(Calendar start, Calendar end) {
386bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        final int diffYears = end.get(Calendar.YEAR) - start.get(Calendar.YEAR);
3870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return end.get(Calendar.MONTH) - start.get(Calendar.MONTH) + 12 * diffYears;
388bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
389bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
3904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    private int getPositionFromDay(long timeInMillis) {
39150eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette        final int diffMonthMax = getDiffMonths(mMinDate, mMaxDate);
3924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        final int diffMonth = getDiffMonths(mMinDate, getTempCalendarForTime(timeInMillis));
39350eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette        return MathUtils.constrain(diffMonth, 0, diffMonthMax);
394bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
395bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
3964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    private Calendar getTempCalendarForTime(long timeInMillis) {
3974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        if (mTempCalendar == null) {
3984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette            mTempCalendar = Calendar.getInstance();
3994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        }
4004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        mTempCalendar.setTimeInMillis(timeInMillis);
4014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        return mTempCalendar;
4024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette    }
4034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette
404bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    /**
405bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio     * Gets the position of the view that is most prominently displayed within the list view.
406bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio     */
407bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public int getMostVisiblePosition() {
40878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        return mViewPager.getCurrentItem();
409bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
410e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette
41178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    public void setPosition(int position) {
41278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mViewPager.setCurrentItem(position, false);
41378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    }
41478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
41578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final OnPageChangeListener mOnPageChangedListener = new OnPageChangeListener() {
41678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        @Override
41778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
41878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final float alpha = Math.abs(0.5f - positionOffset) * 2.0f;
41978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            mPrevButton.setAlpha(alpha);
42078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            mNextButton.setAlpha(alpha);
42178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        }
42278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
42378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        @Override
42478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        public void onPageScrollStateChanged(int state) {}
42578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
42678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        @Override
42778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        public void onPageSelected(int position) {
4285c33949d0272c4dfc313cf8b56d28597e2ec2c62Alan Viverette            updateButtonVisibility(position);
42978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        }
43078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    };
43178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
43278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final OnClickListener mOnClickListener = new OnClickListener() {
43378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        @Override
43478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        public void onClick(View v) {
43578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final int direction;
43678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            if (v == mPrevButton) {
43778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                direction = -1;
43878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            } else if (v == mNextButton) {
43978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                direction = 1;
44078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            } else {
44178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                return;
44278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            }
44378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
44478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            // Animation is expensive for accessibility services since it sends
44578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            // lots of scroll and content change events.
44678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final boolean animate = !mAccessibilityManager.isEnabled();
44778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
44878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            // ViewPager clamps input values, so we don't need to worry
44978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            // about passing invalid indices.
45078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final int nextItem = mViewPager.getCurrentItem() + direction;
45178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            mViewPager.setCurrentItem(nextItem, animate);
45278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        }
45378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    };
45478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
455e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette    public interface OnDaySelectedListener {
45678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        void onDaySelected(DayPickerView view, Calendar day);
457e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette    }
458bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio}
459