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.annotation.Nullable;
     20 import android.content.Context;
     21 import android.graphics.Rect;
     22 import android.graphics.drawable.Drawable;
     23 import android.util.AttributeSet;
     24 import android.view.View;
     25 import android.view.ViewGroup;
     26 import android.view.ViewGroup.LayoutParams;
     27 
     28 import com.android.internal.util.Predicate;
     29 import com.android.internal.widget.PagerAdapter;
     30 import com.android.internal.widget.ViewPager;
     31 
     32 import java.util.ArrayList;
     33 
     34 /**
     35  * This displays a list of months in a calendar format with selectable days.
     36  */
     37 class DayPickerViewPager extends ViewPager {
     38     private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1);
     39 
     40     public DayPickerViewPager(Context context) {
     41         this(context, null);
     42     }
     43 
     44     public DayPickerViewPager(Context context, AttributeSet attrs) {
     45         this(context, attrs, 0);
     46     }
     47 
     48     public DayPickerViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
     49         this(context, attrs, defStyleAttr, 0);
     50     }
     51 
     52     public DayPickerViewPager(Context context, AttributeSet attrs, int defStyleAttr,
     53             int defStyleRes) {
     54         super(context, attrs, defStyleAttr, defStyleRes);
     55     }
     56 
     57     @Override
     58     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     59         populate();
     60 
     61         // Everything below is mostly copied from FrameLayout.
     62         int count = getChildCount();
     63 
     64         final boolean measureMatchParentChildren =
     65                 MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
     66                         MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
     67 
     68         int maxHeight = 0;
     69         int maxWidth = 0;
     70         int childState = 0;
     71 
     72         for (int i = 0; i < count; i++) {
     73             final View child = getChildAt(i);
     74             if (child.getVisibility() != GONE) {
     75                 measureChild(child, widthMeasureSpec, heightMeasureSpec);
     76                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
     77                 maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
     78                 maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
     79                 childState = combineMeasuredStates(childState, child.getMeasuredState());
     80                 if (measureMatchParentChildren) {
     81                     if (lp.width == LayoutParams.MATCH_PARENT ||
     82                             lp.height == LayoutParams.MATCH_PARENT) {
     83                         mMatchParentChildren.add(child);
     84                     }
     85                 }
     86             }
     87         }
     88 
     89         // Account for padding too
     90         maxWidth += getPaddingLeft() + getPaddingRight();
     91         maxHeight += getPaddingTop() + getPaddingBottom();
     92 
     93         // Check against our minimum height and width
     94         maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
     95         maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
     96 
     97         // Check against our foreground's minimum height and width
     98         final Drawable drawable = getForeground();
     99         if (drawable != null) {
    100             maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
    101             maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
    102         }
    103 
    104         setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
    105                 resolveSizeAndState(maxHeight, heightMeasureSpec,
    106                         childState << MEASURED_HEIGHT_STATE_SHIFT));
    107 
    108         count = mMatchParentChildren.size();
    109         if (count > 1) {
    110             for (int i = 0; i < count; i++) {
    111                 final View child = mMatchParentChildren.get(i);
    112 
    113                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
    114                 final int childWidthMeasureSpec;
    115                 final int childHeightMeasureSpec;
    116 
    117                 if (lp.width == LayoutParams.MATCH_PARENT) {
    118                     childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
    119                             getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
    120                             MeasureSpec.EXACTLY);
    121                 } else {
    122                     childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
    123                             getPaddingLeft() + getPaddingRight(),
    124                             lp.width);
    125                 }
    126 
    127                 if (lp.height == LayoutParams.MATCH_PARENT) {
    128                     childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
    129                             getMeasuredHeight() - getPaddingTop() - getPaddingBottom(),
    130                             MeasureSpec.EXACTLY);
    131                 } else {
    132                     childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
    133                             getPaddingTop() + getPaddingBottom(),
    134                             lp.height);
    135                 }
    136 
    137                 child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    138             }
    139         }
    140 
    141         mMatchParentChildren.clear();
    142     }
    143 
    144     @Override
    145     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
    146         if (predicate.apply(this)) {
    147             return this;
    148         }
    149 
    150         // Always try the selected view first.
    151         final DayPickerPagerAdapter adapter = (DayPickerPagerAdapter) getAdapter();
    152         final SimpleMonthView current = adapter.getView(getCurrent());
    153         if (current != childToSkip && current != null) {
    154             final View v = current.findViewByPredicate(predicate);
    155             if (v != null) {
    156                 return v;
    157             }
    158         }
    159 
    160         final int len = getChildCount();
    161         for (int i = 0; i < len; i++) {
    162             final View child = getChildAt(i);
    163 
    164             if (child != childToSkip && child != current) {
    165                 final View v = child.findViewByPredicate(predicate);
    166 
    167                 if (v != null) {
    168                     return v;
    169                 }
    170             }
    171         }
    172 
    173         return null;
    174     }
    175 
    176 }
    177