Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.widget;
     18 
     19 import android.content.Context;
     20 import android.graphics.drawable.Drawable;
     21 import android.util.AttributeSet;
     22 import android.view.View;
     23 
     24 import com.android.internal.widget.ViewPager;
     25 
     26 import java.util.ArrayList;
     27 import java.util.function.Predicate;
     28 
     29 /**
     30  * This displays a list of months in a calendar format with selectable days.
     31  */
     32 class DayPickerViewPager extends ViewPager {
     33     private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1);
     34 
     35     public DayPickerViewPager(Context context) {
     36         this(context, null);
     37     }
     38 
     39     public DayPickerViewPager(Context context, AttributeSet attrs) {
     40         this(context, attrs, 0);
     41     }
     42 
     43     public DayPickerViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
     44         this(context, attrs, defStyleAttr, 0);
     45     }
     46 
     47     public DayPickerViewPager(Context context, AttributeSet attrs, int defStyleAttr,
     48             int defStyleRes) {
     49         super(context, attrs, defStyleAttr, defStyleRes);
     50     }
     51 
     52     @Override
     53     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     54         populate();
     55 
     56         // Everything below is mostly copied from FrameLayout.
     57         int count = getChildCount();
     58 
     59         final boolean measureMatchParentChildren =
     60                 MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
     61                         MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
     62 
     63         int maxHeight = 0;
     64         int maxWidth = 0;
     65         int childState = 0;
     66 
     67         for (int i = 0; i < count; i++) {
     68             final View child = getChildAt(i);
     69             if (child.getVisibility() != GONE) {
     70                 measureChild(child, widthMeasureSpec, heightMeasureSpec);
     71                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
     72                 maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
     73                 maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
     74                 childState = combineMeasuredStates(childState, child.getMeasuredState());
     75                 if (measureMatchParentChildren) {
     76                     if (lp.width == LayoutParams.MATCH_PARENT ||
     77                             lp.height == LayoutParams.MATCH_PARENT) {
     78                         mMatchParentChildren.add(child);
     79                     }
     80                 }
     81             }
     82         }
     83 
     84         // Account for padding too
     85         maxWidth += getPaddingLeft() + getPaddingRight();
     86         maxHeight += getPaddingTop() + getPaddingBottom();
     87 
     88         // Check against our minimum height and width
     89         maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
     90         maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
     91 
     92         // Check against our foreground's minimum height and width
     93         final Drawable drawable = getForeground();
     94         if (drawable != null) {
     95             maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
     96             maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
     97         }
     98 
     99         setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
    100                 resolveSizeAndState(maxHeight, heightMeasureSpec,
    101                         childState << MEASURED_HEIGHT_STATE_SHIFT));
    102 
    103         count = mMatchParentChildren.size();
    104         if (count > 1) {
    105             for (int i = 0; i < count; i++) {
    106                 final View child = mMatchParentChildren.get(i);
    107 
    108                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
    109                 final int childWidthMeasureSpec;
    110                 final int childHeightMeasureSpec;
    111 
    112                 if (lp.width == LayoutParams.MATCH_PARENT) {
    113                     childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
    114                             getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
    115                             MeasureSpec.EXACTLY);
    116                 } else {
    117                     childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
    118                             getPaddingLeft() + getPaddingRight(),
    119                             lp.width);
    120                 }
    121 
    122                 if (lp.height == LayoutParams.MATCH_PARENT) {
    123                     childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
    124                             getMeasuredHeight() - getPaddingTop() - getPaddingBottom(),
    125                             MeasureSpec.EXACTLY);
    126                 } else {
    127                     childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
    128                             getPaddingTop() + getPaddingBottom(),
    129                             lp.height);
    130                 }
    131 
    132                 child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    133             }
    134         }
    135 
    136         mMatchParentChildren.clear();
    137     }
    138 
    139     @Override
    140     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
    141             View childToSkip) {
    142         if (predicate.test(this)) {
    143             return (T) this;
    144         }
    145 
    146         // Always try the selected view first.
    147         final DayPickerPagerAdapter adapter = (DayPickerPagerAdapter) getAdapter();
    148         final SimpleMonthView current = adapter.getView(getCurrent());
    149         if (current != childToSkip && current != null) {
    150             final View v = current.findViewByPredicate(predicate);
    151             if (v != null) {
    152                 return (T) v;
    153             }
    154         }
    155 
    156         final int len = getChildCount();
    157         for (int i = 0; i < len; i++) {
    158             final View child = getChildAt(i);
    159 
    160             if (child != childToSkip && child != current) {
    161                 final View v = child.findViewByPredicate(predicate);
    162 
    163                 if (v != null) {
    164                     return (T) v;
    165                 }
    166             }
    167         }
    168 
    169         return null;
    170     }
    171 
    172 }
    173