diff options
-rwxr-xr-x | core/java/android/widget/DatePickerCalendarDelegate.java | 12 | ||||
-rw-r--r-- | core/java/android/widget/DayPickerView.java | 92 | ||||
-rw-r--r-- | core/java/android/widget/SimpleMonthView.java | 18 | ||||
-rw-r--r-- | core/java/android/widget/TextView.java | 1 | ||||
-rw-r--r-- | core/java/android/widget/YearPickerView.java | 27 | ||||
-rw-r--r-- | core/java/com/android/internal/widget/DialogViewAnimator.java | 141 | ||||
-rw-r--r-- | core/java/com/android/internal/widget/ViewPager.java | 2 | ||||
-rw-r--r-- | core/res/res/anim/date_picker_fade_in_material.xml | 22 | ||||
-rw-r--r-- | core/res/res/anim/date_picker_fade_out_material.xml | 22 | ||||
-rw-r--r-- | core/res/res/layout/date_picker_material.xml | 4 | ||||
-rw-r--r-- | core/res/res/layout/date_picker_view_animator_material.xml | 18 |
11 files changed, 315 insertions, 44 deletions
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java index a157087..06a5bd2 100755 --- a/core/java/android/widget/DatePickerCalendarDelegate.java +++ b/core/java/android/widget/DatePickerCalendarDelegate.java @@ -534,22 +534,23 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate { @Override public void onRestoreInstanceState(Parcelable state) { - SavedState ss = (SavedState) state; + final SavedState ss = (SavedState) state; // TODO: Move instance state into DayPickerView, YearPickerView. mCurrentDate.set(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay()); - mCurrentView = ss.getCurrentView(); mMinDate.setTimeInMillis(ss.getMinDate()); mMaxDate.setTimeInMillis(ss.getMaxDate()); onCurrentDateChanged(false); - setCurrentView(mCurrentView); + + final int currentView = ss.getCurrentView(); + setCurrentView(currentView); final int listPosition = ss.getListPosition(); if (listPosition != -1) { - if (mCurrentView == VIEW_MONTH_DAY) { + if (currentView == VIEW_MONTH_DAY) { mDayPickerView.setCurrentItem(listPosition); - } else if (mCurrentView == VIEW_YEAR) { + } else if (currentView == VIEW_YEAR) { final int listPositionOffset = ss.getListPositionOffset(); mYearPickerView.setSelectionFromTop(listPosition, listPositionOffset); } @@ -601,7 +602,6 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate { * Class for managing state storing/restoring. */ private static class SavedState extends View.BaseSavedState { - private final int mSelectedYear; private final int mSelectedMonth; private final int mSelectedDay; diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java index ec2528f..0e0b2d3 100644 --- a/core/java/android/widget/DayPickerView.java +++ b/core/java/android/widget/DayPickerView.java @@ -22,9 +22,12 @@ import com.android.internal.R; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.MathUtils; +import android.view.View; +import java.util.ArrayList; import java.util.Calendar; import java.util.Locale; @@ -41,6 +44,8 @@ class DayPickerView extends ViewPager { private final Calendar mMinDate = Calendar.getInstance(); private final Calendar mMaxDate = Calendar.getInstance(); + private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1); + private final DayPickerAdapter mAdapter; /** Temporary calendar used for date calculations. */ @@ -140,6 +145,93 @@ class DayPickerView extends ViewPager { }); } + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + populate(); + + // Everything below is mostly copied from FrameLayout. + int count = getChildCount(); + + final boolean measureMatchParentChildren = + MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY || + MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY; + + int maxHeight = 0; + int maxWidth = 0; + int childState = 0; + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + measureChild(child, widthMeasureSpec, heightMeasureSpec); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + maxWidth = Math.max(maxWidth, child.getMeasuredWidth()); + maxHeight = Math.max(maxHeight, child.getMeasuredHeight()); + childState = combineMeasuredStates(childState, child.getMeasuredState()); + if (measureMatchParentChildren) { + if (lp.width == LayoutParams.MATCH_PARENT || + lp.height == LayoutParams.MATCH_PARENT) { + mMatchParentChildren.add(child); + } + } + } + } + + // Account for padding too + maxWidth += getPaddingLeft() + getPaddingRight(); + maxHeight += getPaddingTop() + getPaddingBottom(); + + // Check against our minimum height and width + maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); + maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); + + // Check against our foreground's minimum height and width + final Drawable drawable = getForeground(); + if (drawable != null) { + maxHeight = Math.max(maxHeight, drawable.getMinimumHeight()); + maxWidth = Math.max(maxWidth, drawable.getMinimumWidth()); + } + + setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState), + resolveSizeAndState(maxHeight, heightMeasureSpec, + childState << MEASURED_HEIGHT_STATE_SHIFT)); + + count = mMatchParentChildren.size(); + if (count > 1) { + for (int i = 0; i < count; i++) { + final View child = mMatchParentChildren.get(i); + + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + final int childWidthMeasureSpec; + final int childHeightMeasureSpec; + + if (lp.width == LayoutParams.MATCH_PARENT) { + childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( + getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), + MeasureSpec.EXACTLY); + } else { + childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, + getPaddingLeft() + getPaddingRight(), + lp.width); + } + + if (lp.height == LayoutParams.MATCH_PARENT) { + childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( + getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), + MeasureSpec.EXACTLY); + } else { + childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, + getPaddingTop() + getPaddingBottom(), + lp.height); + } + + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + } + } + + mMatchParentChildren.clear(); + } + public void setDayOfWeekTextAppearance(int resId) { mAdapter.setDayOfWeekTextAppearance(resId); } diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java index d9f1f0e..aa7f0b6 100644 --- a/core/java/android/widget/SimpleMonthView.java +++ b/core/java/android/widget/SimpleMonthView.java @@ -585,7 +585,6 @@ class SimpleMonthView extends View { mToday = day; } } - mNumWeeks = calculateNumRows(); // Invalidate the old title. mTitle = null; @@ -616,18 +615,6 @@ class SimpleMonthView extends View { } } - public void reuse() { - mNumWeeks = MAX_WEEKS_IN_MONTH; - requestLayout(); - } - - private int calculateNumRows() { - final int offset = findDayOffset(); - final int dividend = (offset + mDaysInMonth) / DAYS_IN_WEEK; - final int remainder = (offset + mDaysInMonth) % DAYS_IN_WEEK; - return dividend + (remainder > 0 ? 1 : 0); - } - private boolean sameDay(int day, Calendar today) { return mYear == today.get(Calendar.YEAR) && mMonth == today.get(Calendar.MONTH) && day == today.get(Calendar.DAY_OF_MONTH); @@ -635,8 +622,9 @@ class SimpleMonthView extends View { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final int preferredHeight = mDesiredDayHeight * mNumWeeks + mDesiredDayOfWeekHeight - + mDesiredMonthHeight + getPaddingTop() + getPaddingBottom(); + final int preferredHeight = mDesiredDayHeight * MAX_WEEKS_IN_MONTH + + mDesiredDayOfWeekHeight + mDesiredMonthHeight + + getPaddingTop() + getPaddingBottom(); final int preferredWidth = mDesiredCellWidth * DAYS_IN_WEEK + getPaddingStart() + getPaddingEnd(); final int resolvedWidth = resolveSize(preferredWidth, widthMeasureSpec); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 9caa584..2fd2ec9 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -534,6 +534,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private Layout mLayout; private boolean mLocaleChanged = false; + @ViewDebug.ExportedProperty(category = "text") private int mGravity = Gravity.TOP | Gravity.START; private boolean mHorizontallyScrolling; diff --git a/core/java/android/widget/YearPickerView.java b/core/java/android/widget/YearPickerView.java index 7182414..89e59f9 100644 --- a/core/java/android/widget/YearPickerView.java +++ b/core/java/android/widget/YearPickerView.java @@ -178,24 +178,29 @@ class YearPickerView extends ListView { @Override public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = mInflater.inflate(ITEM_LAYOUT, parent, false); + final TextView v; + final boolean hasNewView = convertView == null; + if (hasNewView) { + v = (TextView) mInflater.inflate(ITEM_LAYOUT, parent, false); + } else { + v = (TextView) convertView; } final int year = getYearForPosition(position); final boolean activated = mActivatedYear == year; - final int textAppearanceResId; - if (activated && ITEM_TEXT_ACTIVATED_APPEARANCE != 0) { - textAppearanceResId = ITEM_TEXT_ACTIVATED_APPEARANCE; - } else { - textAppearanceResId = ITEM_TEXT_APPEARANCE; + if (hasNewView || v.isActivated() != activated) { + final int textAppearanceResId; + if (activated && ITEM_TEXT_ACTIVATED_APPEARANCE != 0) { + textAppearanceResId = ITEM_TEXT_ACTIVATED_APPEARANCE; + } else { + textAppearanceResId = ITEM_TEXT_APPEARANCE; + } + v.setTextAppearance(textAppearanceResId); + v.setActivated(activated); } - final TextView v = (TextView) convertView; - v.setText("" + year); - v.setTextAppearance(v.getContext(), textAppearanceResId); - v.setActivated(activated); + v.setText(Integer.toString(year)); return v; } diff --git a/core/java/com/android/internal/widget/DialogViewAnimator.java b/core/java/com/android/internal/widget/DialogViewAnimator.java new file mode 100644 index 0000000..bdfc1af --- /dev/null +++ b/core/java/com/android/internal/widget/DialogViewAnimator.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.widget; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ViewAnimator; + +import java.util.ArrayList; + +/** + * ViewAnimator with a more reasonable handling of MATCH_PARENT. + */ +public class DialogViewAnimator extends ViewAnimator { + private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1); + + public DialogViewAnimator(Context context) { + super(context); + } + + public DialogViewAnimator(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + final boolean measureMatchParentChildren = + MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY || + MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY; + + int maxHeight = 0; + int maxWidth = 0; + int childState = 0; + + // First measure all children and record maximum dimensions where the + // spec isn't MATCH_PARENT. + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (getMeasureAllChildren() || child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + final boolean matchWidth = lp.width == LayoutParams.MATCH_PARENT; + final boolean matchHeight = lp.height == LayoutParams.MATCH_PARENT; + if (measureMatchParentChildren && (matchWidth || matchHeight)) { + mMatchParentChildren.add(child); + } + + measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); + + // Measured dimensions only count against the maximum + // dimensions if they're not MATCH_PARENT. + int state = 0; + + if (measureMatchParentChildren && !matchWidth) { + maxWidth = Math.max(maxWidth, child.getMeasuredWidth() + + lp.leftMargin + lp.rightMargin); + state |= child.getMeasuredWidthAndState() & MEASURED_STATE_MASK; + } + + if (measureMatchParentChildren && !matchHeight) { + maxHeight = Math.max(maxHeight, child.getMeasuredHeight() + + lp.topMargin + lp.bottomMargin); + state |= (child.getMeasuredHeightAndState() >> MEASURED_HEIGHT_STATE_SHIFT) + & (MEASURED_STATE_MASK >> MEASURED_HEIGHT_STATE_SHIFT); + } + + childState = combineMeasuredStates(childState, state); + } + } + + // Account for padding too. + maxWidth += getPaddingLeft() + getPaddingRight(); + maxHeight += getPaddingTop() + getPaddingBottom(); + + // Check against our minimum height and width. + maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); + maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); + + // Check against our foreground's minimum height and width. + final Drawable drawable = getForeground(); + if (drawable != null) { + maxHeight = Math.max(maxHeight, drawable.getMinimumHeight()); + maxWidth = Math.max(maxWidth, drawable.getMinimumWidth()); + } + + setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState), + resolveSizeAndState(maxHeight, heightMeasureSpec, + childState << MEASURED_HEIGHT_STATE_SHIFT)); + + // Measure remaining MATCH_PARENT children again using real dimensions. + final int matchCount = mMatchParentChildren.size(); + for (int i = 0; i < matchCount; i++) { + final View child = mMatchParentChildren.get(i); + final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); + + final int childWidthMeasureSpec; + if (lp.width == LayoutParams.MATCH_PARENT) { + childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( + getMeasuredWidth() - getPaddingLeft() - getPaddingRight() + - lp.leftMargin - lp.rightMargin, + MeasureSpec.EXACTLY); + } else { + childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, + getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin, + lp.width); + } + + final int childHeightMeasureSpec; + if (lp.height == LayoutParams.MATCH_PARENT) { + childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( + getMeasuredHeight() - getPaddingTop() - getPaddingBottom() + - lp.topMargin - lp.bottomMargin, + MeasureSpec.EXACTLY); + } else { + childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, + getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin, + lp.height); + } + + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + } + + mMatchParentChildren.clear(); + } +} diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java index 8d66191..5c08daf 100644 --- a/core/java/com/android/internal/widget/ViewPager.java +++ b/core/java/com/android/internal/widget/ViewPager.java @@ -889,7 +889,7 @@ public class ViewPager extends ViewGroup { } } - void populate() { + public void populate() { populate(mCurItem); } diff --git a/core/res/res/anim/date_picker_fade_in_material.xml b/core/res/res/anim/date_picker_fade_in_material.xml new file mode 100644 index 0000000..12e7ce3 --- /dev/null +++ b/core/res/res/anim/date_picker_fade_in_material.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<alpha xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@interpolator/accelerate_quad" + android:fromAlpha="0.0" + android:toAlpha="1.0" + android:duration="250" /> diff --git a/core/res/res/anim/date_picker_fade_out_material.xml b/core/res/res/anim/date_picker_fade_out_material.xml new file mode 100644 index 0000000..4084605 --- /dev/null +++ b/core/res/res/anim/date_picker_fade_out_material.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<alpha xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@interpolator/decelerate_quad" + android:fromAlpha="1.0" + android:toAlpha="0.0" + android:duration="250" /> diff --git a/core/res/res/layout/date_picker_material.xml b/core/res/res/layout/date_picker_material.xml index a1c97ff..763f2a4 100644 --- a/core/res/res/layout/date_picker_material.xml +++ b/core/res/res/layout/date_picker_material.xml @@ -16,8 +16,8 @@ --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:orientation="vertical"> <include diff --git a/core/res/res/layout/date_picker_view_animator_material.xml b/core/res/res/layout/date_picker_view_animator_material.xml index 620ddfa..e863b28 100644 --- a/core/res/res/layout/date_picker_view_animator_material.xml +++ b/core/res/res/layout/date_picker_view_animator_material.xml @@ -15,23 +15,23 @@ limitations under the License. --> -<ViewAnimator xmlns:android="http://schemas.android.com/apk/res/android" +<com.android.internal.widget.DialogViewAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/animator" android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" - android:gravity="center"> + android:layout_height="wrap_content" + android:gravity="center" + android:inAnimation="@anim/date_picker_fade_in_material" + android:outAnimation="@anim/date_picker_fade_out_material" + android:measureAllChildren="true"> <android.widget.DayPickerView android:id="@+id/date_picker_day_picker" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:inAnimation="@anim/fade_in" - android:outAnimation="@anim/fade_out" /> + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> <android.widget.YearPickerView android:id="@+id/date_picker_year_picker" android:layout_width="match_parent" android:layout_height="match_parent" /> -</ViewAnimator> +</com.android.internal.widget.DialogViewAnimator> |