178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette/*
278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette * Copyright (C) 2015 The Android Open Source Project
378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette *
478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette * Licensed under the Apache License, Version 2.0 (the "License");
578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette * you may not use this file except in compliance with the License.
678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette * You may obtain a copy of the License at
778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette *
878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette *      http://www.apache.org/licenses/LICENSE-2.0
978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette *
1078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette * Unless required by applicable law or agreed to in writing, software
1178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette * distributed under the License is distributed on an "AS IS" BASIS,
1278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette * See the License for the specific language governing permissions and
1478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette * limitations under the License.
1578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette */
1678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
1778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverettepackage android.widget;
1878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
1978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport android.content.Context;
2078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport android.graphics.drawable.Drawable;
2178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport android.util.AttributeSet;
2278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport android.view.View;
23e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount
24e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mountimport com.android.internal.widget.ViewPager;
2578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
2678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteimport java.util.ArrayList;
27ca4964ccbef5f2c85855fc14577c7c25d0e0588dPaul Duffinimport java.util.function.Predicate;
2878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
2978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette/**
3078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette * This displays a list of months in a calendar format with selectable days.
3178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette */
3278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viveretteclass DayPickerViewPager extends ViewPager {
3378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1);
3478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
3578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    public DayPickerViewPager(Context context) {
3678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        this(context, null);
3778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    }
3878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
3978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    public DayPickerViewPager(Context context, AttributeSet attrs) {
4078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        this(context, attrs, 0);
4178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    }
4278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
4378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    public DayPickerViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
4478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        this(context, attrs, defStyleAttr, 0);
4578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    }
4678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
4778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    public DayPickerViewPager(Context context, AttributeSet attrs, int defStyleAttr,
4878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            int defStyleRes) {
4978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        super(context, attrs, defStyleAttr, defStyleRes);
5078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    }
5178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
5278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    @Override
5378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
5478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        populate();
5578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
5678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        // Everything below is mostly copied from FrameLayout.
5778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        int count = getChildCount();
5878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
5978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final boolean measureMatchParentChildren =
6078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
6178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                        MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
6278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
6378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        int maxHeight = 0;
6478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        int maxWidth = 0;
6578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        int childState = 0;
6678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
6778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        for (int i = 0; i < count; i++) {
6878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            final View child = getChildAt(i);
6978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            if (child.getVisibility() != GONE) {
7078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                measureChild(child, widthMeasureSpec, heightMeasureSpec);
7178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
7278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
7378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
7478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                childState = combineMeasuredStates(childState, child.getMeasuredState());
7578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                if (measureMatchParentChildren) {
7678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                    if (lp.width == LayoutParams.MATCH_PARENT ||
7778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                            lp.height == LayoutParams.MATCH_PARENT) {
7878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                        mMatchParentChildren.add(child);
7978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                    }
8078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                }
8178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            }
8278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        }
8378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
8478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        // Account for padding too
8578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        maxWidth += getPaddingLeft() + getPaddingRight();
8678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        maxHeight += getPaddingTop() + getPaddingBottom();
8778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
8878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        // Check against our minimum height and width
8978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
9078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
9178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
9278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        // Check against our foreground's minimum height and width
9378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        final Drawable drawable = getForeground();
9478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        if (drawable != null) {
9578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
9678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
9778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        }
9878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
9978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
10078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                resolveSizeAndState(maxHeight, heightMeasureSpec,
10178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                        childState << MEASURED_HEIGHT_STATE_SHIFT));
10278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
10378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        count = mMatchParentChildren.size();
10478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        if (count > 1) {
10578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            for (int i = 0; i < count; i++) {
10678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                final View child = mMatchParentChildren.get(i);
10778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
10878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
10978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                final int childWidthMeasureSpec;
11078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                final int childHeightMeasureSpec;
11178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
11278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                if (lp.width == LayoutParams.MATCH_PARENT) {
11378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                    childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
11478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                            getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
11578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                            MeasureSpec.EXACTLY);
11678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                } else {
11778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                    childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
11878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                            getPaddingLeft() + getPaddingRight(),
11978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                            lp.width);
12078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                }
12178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
12278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                if (lp.height == LayoutParams.MATCH_PARENT) {
12378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                    childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
12478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                            getMeasuredHeight() - getPaddingTop() - getPaddingBottom(),
12578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                            MeasureSpec.EXACTLY);
12678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                } else {
12778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                    childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
12878bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                            getPaddingTop() + getPaddingBottom(),
12978bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                            lp.height);
13078bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                }
13178bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
13278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette                child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
13378bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette            }
13478bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        }
13578bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette
13678bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette        mMatchParentChildren.clear();
13778bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette    }
138e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount
139e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount    @Override
1408e1a72964517bfd01d8e650453ef41e22f770f21Alan Viverette    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
1418e1a72964517bfd01d8e650453ef41e22f770f21Alan Viverette            View childToSkip) {
142ca4964ccbef5f2c85855fc14577c7c25d0e0588dPaul Duffin        if (predicate.test(this)) {
1438e1a72964517bfd01d8e650453ef41e22f770f21Alan Viverette            return (T) this;
144e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        }
145e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount
146e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        // Always try the selected view first.
147e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        final DayPickerPagerAdapter adapter = (DayPickerPagerAdapter) getAdapter();
148e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        final SimpleMonthView current = adapter.getView(getCurrent());
149e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        if (current != childToSkip && current != null) {
150e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount            final View v = current.findViewByPredicate(predicate);
151e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount            if (v != null) {
1528e1a72964517bfd01d8e650453ef41e22f770f21Alan Viverette                return (T) v;
153e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount            }
154e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        }
155e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount
156e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        final int len = getChildCount();
157e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        for (int i = 0; i < len; i++) {
158e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount            final View child = getChildAt(i);
159e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount
160e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount            if (child != childToSkip && child != current) {
161e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                final View v = child.findViewByPredicate(predicate);
162e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount
163e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                if (v != null) {
1648e1a72964517bfd01d8e650453ef41e22f770f21Alan Viverette                    return (T) v;
165e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                }
166e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount            }
167e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        }
168e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount
169e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        return null;
170e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount    }
171e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount
17278bf1d329a4c0210394f846be1fd1390314aefc0Alan Viverette}
173