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