diff options
author | Alan Viverette <alanv@google.com> | 2015-05-06 17:11:23 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-05-06 17:11:24 +0000 |
commit | 71b0cb043f410d7f0a7852b2f297124fa9aed0e2 (patch) | |
tree | 92a9165e97c5c754e528793500f46317831242f0 | |
parent | c97b922abae0b66fcbd6138f803c9d8a23024e6e (diff) | |
parent | 922e1c6ed28da4c5b7ff6b1d4448fe3e8c11652f (diff) | |
download | frameworks_base-71b0cb043f410d7f0a7852b2f297124fa9aed0e2.zip frameworks_base-71b0cb043f410d7f0a7852b2f297124fa9aed0e2.tar.gz frameworks_base-71b0cb043f410d7f0a7852b2f297124fa9aed0e2.tar.bz2 |
Merge "Add scroll indicators on View, use in AlertDialog" into mnc-dev
-rw-r--r-- | api/current.txt | 11 | ||||
-rw-r--r-- | api/system-current.txt | 11 | ||||
-rw-r--r-- | core/java/android/view/View.java | 339 | ||||
-rw-r--r-- | core/java/android/view/ViewGroup.java | 16 | ||||
-rw-r--r-- | core/java/com/android/internal/app/AlertController.java | 74 | ||||
-rw-r--r-- | core/java/com/android/internal/widget/ButtonBarLayout.java | 38 | ||||
-rw-r--r-- | core/res/res/drawable/scroll_indicator_material.xml | 23 | ||||
-rw-r--r-- | core/res/res/layout/alert_dialog_button_bar_material.xml | 3 | ||||
-rw-r--r-- | core/res/res/layout/alert_dialog_material.xml | 53 | ||||
-rw-r--r-- | core/res/res/values/attrs.xml | 29 | ||||
-rw-r--r-- | core/res/res/values/public.xml | 2 | ||||
-rwxr-xr-x | core/res/res/values/symbols.xml | 4 | ||||
-rw-r--r-- | core/res/res/values/themes_material.xml | 8 |
13 files changed, 502 insertions, 109 deletions
diff --git a/api/current.txt b/api/current.txt index 193407e..cf365ff 100644 --- a/api/current.txt +++ b/api/current.txt @@ -1049,6 +1049,7 @@ package android { field public static final int screenOrientation = 16842782; // 0x101001e field public static final int screenSize = 16843466; // 0x10102ca field public static final int scrollHorizontally = 16843099; // 0x101015b + field public static final int scrollIndicators = 16844023; // 0x10104f7 field public static final int scrollViewStyle = 16842880; // 0x1010080 field public static final int scrollX = 16842962; // 0x10100d2 field public static final int scrollY = 16842963; // 0x10100d3 @@ -36200,6 +36201,7 @@ package android.view { method public int getScrollBarFadeDuration(); method public int getScrollBarSize(); method public int getScrollBarStyle(); + method public int getScrollIndicators(); method public final int getScrollX(); method public final int getScrollY(); method public int getSolidColor(); @@ -36281,6 +36283,7 @@ package android.view { method public boolean isSaveEnabled(); method public boolean isSaveFromParentEnabled(); method public boolean isScrollContainer(); + method public boolean isScrollIndicatorEnabled(int); method public boolean isScrollbarFadingEnabled(); method public boolean isSelected(); method public boolean isShown(); @@ -36480,6 +36483,8 @@ package android.view { method public void setScrollBarSize(int); method public void setScrollBarStyle(int); method public void setScrollContainer(boolean); + method public void setScrollIndicators(int); + method public void setScrollIndicators(int, int); method public void setScrollX(int); method public void setScrollY(int); method public void setScrollbarFadingEnabled(boolean); @@ -36605,6 +36610,12 @@ package android.view { field public static final int SCROLL_AXIS_HORIZONTAL = 1; // 0x1 field public static final int SCROLL_AXIS_NONE = 0; // 0x0 field public static final int SCROLL_AXIS_VERTICAL = 2; // 0x2 + field public static final int SCROLL_INDICATOR_BOTTOM = 2; // 0x2 + field public static final int SCROLL_INDICATOR_END = 32; // 0x20 + field public static final int SCROLL_INDICATOR_LEFT = 4; // 0x4 + field public static final int SCROLL_INDICATOR_RIGHT = 8; // 0x8 + field public static final int SCROLL_INDICATOR_START = 16; // 0x10 + field public static final int SCROLL_INDICATOR_TOP = 1; // 0x1 field protected static final int[] SELECTED_STATE_SET; field protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET; field public static final int SOUND_EFFECTS_ENABLED = 134217728; // 0x8000000 diff --git a/api/system-current.txt b/api/system-current.txt index 2738bdb..e08ffd4 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1121,6 +1121,7 @@ package android { field public static final int screenOrientation = 16842782; // 0x101001e field public static final int screenSize = 16843466; // 0x10102ca field public static final int scrollHorizontally = 16843099; // 0x101015b + field public static final int scrollIndicators = 16844023; // 0x10104f7 field public static final int scrollViewStyle = 16842880; // 0x1010080 field public static final int scrollX = 16842962; // 0x10100d2 field public static final int scrollY = 16842963; // 0x10100d3 @@ -38411,6 +38412,7 @@ package android.view { method public int getScrollBarFadeDuration(); method public int getScrollBarSize(); method public int getScrollBarStyle(); + method public int getScrollIndicators(); method public final int getScrollX(); method public final int getScrollY(); method public int getSolidColor(); @@ -38492,6 +38494,7 @@ package android.view { method public boolean isSaveEnabled(); method public boolean isSaveFromParentEnabled(); method public boolean isScrollContainer(); + method public boolean isScrollIndicatorEnabled(int); method public boolean isScrollbarFadingEnabled(); method public boolean isSelected(); method public boolean isShown(); @@ -38691,6 +38694,8 @@ package android.view { method public void setScrollBarSize(int); method public void setScrollBarStyle(int); method public void setScrollContainer(boolean); + method public void setScrollIndicators(int); + method public void setScrollIndicators(int, int); method public void setScrollX(int); method public void setScrollY(int); method public void setScrollbarFadingEnabled(boolean); @@ -38816,6 +38821,12 @@ package android.view { field public static final int SCROLL_AXIS_HORIZONTAL = 1; // 0x1 field public static final int SCROLL_AXIS_NONE = 0; // 0x0 field public static final int SCROLL_AXIS_VERTICAL = 2; // 0x2 + field public static final int SCROLL_INDICATOR_BOTTOM = 2; // 0x2 + field public static final int SCROLL_INDICATOR_END = 32; // 0x20 + field public static final int SCROLL_INDICATOR_LEFT = 4; // 0x4 + field public static final int SCROLL_INDICATOR_RIGHT = 8; // 0x8 + field public static final int SCROLL_INDICATOR_START = 16; // 0x10 + field public static final int SCROLL_INDICATOR_TOP = 1; // 0x1 field protected static final int[] SELECTED_STATE_SET; field protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET; field public static final int SOUND_EFFECTS_ENABLED = 134217728; // 0x8000000 diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 75dc0a2..f62e6a2 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -2395,10 +2395,143 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80; + /** + * Flag indicating that the bottom scroll indicator should be displayed + * when this view can scroll up. + */ + static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100; + + /** + * Flag indicating that the bottom scroll indicator should be displayed + * when this view can scroll down. + */ + static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200; + + /** + * Flag indicating that the left scroll indicator should be displayed + * when this view can scroll left. + */ + static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400; + + /** + * Flag indicating that the right scroll indicator should be displayed + * when this view can scroll right. + */ + static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800; + + /** + * Flag indicating that the start scroll indicator should be displayed + * when this view can scroll in the start direction. + */ + static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000; + + /** + * Flag indicating that the end scroll indicator should be displayed + * when this view can scroll in the end direction. + */ + static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000; + /* End of masks for mPrivateFlags3 */ static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED; + static final int SCROLL_INDICATORS_NONE = 0x0000; + + /** + * Mask for use with setFlags indicating bits used for indicating which + * scroll indicators are enabled. + */ + static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP + | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT + | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START + | PFLAG3_SCROLL_INDICATOR_END; + + /** + * Left-shift required to translate between public scroll indicator flags + * and internal PFLAGS3 flags. When used as a right-shift, translates + * PFLAGS3 flags to public flags. + */ + static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, + value = { + SCROLL_INDICATOR_TOP, + SCROLL_INDICATOR_BOTTOM, + SCROLL_INDICATOR_LEFT, + SCROLL_INDICATOR_RIGHT, + SCROLL_INDICATOR_START, + SCROLL_INDICATOR_END, + }) + public @interface ScrollIndicators {} + + /** + * Scroll indicator direction for the top edge of the view. + * + * @see #setScrollIndicators(int) + * @see #setScrollIndicators(int, int) + * @see #getScrollIndicators() + */ + public static final int SCROLL_INDICATOR_TOP = + PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + + /** + * Scroll indicator direction for the bottom edge of the view. + * + * @see #setScrollIndicators(int) + * @see #setScrollIndicators(int, int) + * @see #getScrollIndicators() + */ + public static final int SCROLL_INDICATOR_BOTTOM = + PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + + /** + * Scroll indicator direction for the left edge of the view. + * + * @see #setScrollIndicators(int) + * @see #setScrollIndicators(int, int) + * @see #getScrollIndicators() + */ + public static final int SCROLL_INDICATOR_LEFT = + PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + + /** + * Scroll indicator direction for the right edge of the view. + * + * @see #setScrollIndicators(int) + * @see #setScrollIndicators(int, int) + * @see #getScrollIndicators() + */ + public static final int SCROLL_INDICATOR_RIGHT = + PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + + /** + * Scroll indicator direction for the starting edge of the view. + * <p> + * Resolved according to the view's layout direction, see + * {@link #getLayoutDirection()} for more information. + * + * @see #setScrollIndicators(int) + * @see #setScrollIndicators(int, int) + * @see #getScrollIndicators() + */ + public static final int SCROLL_INDICATOR_START = + PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + + /** + * Scroll indicator direction for the ending edge of the view. + * <p> + * Resolved according to the view's layout direction, see + * {@link #getLayoutDirection()} for more information. + * + * @see #setScrollIndicators(int) + * @see #setScrollIndicators(int, int) + * @see #getScrollIndicators() + */ + public static final int SCROLL_INDICATOR_END = + PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + /** * <p>Indicates that we are allowing {@link android.view.ViewAssistStructure} to traverse * into this view.<p> @@ -3217,6 +3350,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_") private ForegroundInfo mForegroundInfo; + private Drawable mScrollIndicatorDrawable; + /** * RenderNode used for backgrounds. * <p> @@ -3769,6 +3904,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY; int overScrollMode = mOverScrollMode; boolean initializeScrollbars = false; + boolean initializeScrollIndicators = false; boolean startPaddingDefined = false; boolean endPaddingDefined = false; @@ -4135,6 +4271,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } mForegroundInfo.mInsidePadding = a.getBoolean(attr, mForegroundInfo.mInsidePadding); + case R.styleable.View_scrollIndicators: + final int scrollIndicators = + a.getInt(attr, SCROLL_INDICATORS_NONE) & SCROLL_INDICATORS_PFLAG3_MASK; + if (scrollIndicators != 0) { + viewFlagValues |= scrollIndicators; + viewFlagMasks |= SCROLL_INDICATORS_PFLAG3_MASK; + initializeScrollIndicators = true; + } break; } } @@ -4211,6 +4355,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, initializeScrollbarsInternal(a); } + if (initializeScrollIndicators) { + initializeScrollIndicatorsInternal(); + } + a.recycle(); // Needs to be called after mViewFlags is set @@ -4682,6 +4830,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, resolvePadding(); } + private void initializeScrollIndicatorsInternal() { + // Some day maybe we'll break this into top/left/start/etc. and let the + // client control it. Until then, you can have any scroll indicator you + // want as long as it's a 1dp foreground-colored rectangle. + if (mScrollIndicatorDrawable == null) { + mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material); + } + } + /** * <p> * Initalizes the scrollability cache if necessary. @@ -4721,6 +4878,118 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return mVerticalScrollbarPosition; } + /** + * Sets the state of all scroll indicators. + * <p> + * See {@link #setScrollIndicators(int, int)} for usage information. + * + * @param indicators a bitmask of indicators that should be enabled, or + * {@code 0} to disable all indicators + * @see #setScrollIndicators(int, int) + * @see #getScrollIndicators() + * @attr ref android.R.styleable#View_scrollIndicators + */ + public void setScrollIndicators(@ScrollIndicators int indicators) { + setScrollIndicators(indicators, SCROLL_INDICATORS_PFLAG3_MASK); + } + + /** + * Sets the state of the scroll indicators specified by the mask. To change + * all scroll indicators at once, see {@link #setScrollIndicators(int)}. + * <p> + * When a scroll indicator is enabled, it will be displayed if the view + * can scroll in the direction of the indicator. + * <p> + * Multiple indicator types may be enabled or disabled by passing the + * logical OR of the desired types. If multiple types are specified, they + * will all be set to the same enabled state. + * <p> + * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators + * + * @param indicators the indicator direction, or the logical OR of multiple + * indicator directions. One or more of: + * <ul> + * <li>{@link #SCROLL_INDICATOR_TOP}</li> + * <li>{@link #SCROLL_INDICATOR_BOTTOM}</li> + * <li>{@link #SCROLL_INDICATOR_LEFT}</li> + * <li>{@link #SCROLL_INDICATOR_RIGHT}</li> + * <li>{@link #SCROLL_INDICATOR_START}</li> + * <li>{@link #SCROLL_INDICATOR_END}</li> + * </ul> + * @see #setScrollIndicators(int) + * @see #getScrollIndicators() + * @attr ref android.R.styleable#View_scrollIndicators + */ + public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) { + // Shift and sanitize mask. + mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + mask &= SCROLL_INDICATORS_PFLAG3_MASK; + + // Shift and mask indicators. + indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + indicators &= mask; + + // Merge with non-masked flags. + final int updatedFlags = indicators | (mPrivateFlags3 & ~mask); + + if (mPrivateFlags3 != updatedFlags) { + mPrivateFlags3 = updatedFlags; + + if (indicators != 0) { + initializeScrollIndicatorsInternal(); + } + invalidate(); + } + } + + /** + * Returns a bitmask representing the enabled scroll indicators. + * <p> + * For example, if the top and left scroll indicators are enabled and all + * other indicators are disabled, the return value will be + * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}. + * <p> + * To check whether the bottom scroll indicator is enabled, use the value + * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}. + * + * @return a bitmask representing the enabled scroll indicators + */ + @ScrollIndicators + public int getScrollIndicators() { + return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) + >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + } + + /** + * Returns whether the specified scroll indicator is enabled. + * <p> + * Multiple indicator types may be queried by passing the logical OR of the + * desired types. If multiple types are specified, the return value + * represents whether they are all enabled. + * + * @param direction the indicator direction, or the logical OR of multiple + * indicator directions. One or more of: + * <ul> + * <li>{@link #SCROLL_INDICATOR_TOP}</li> + * <li>{@link #SCROLL_INDICATOR_BOTTOM}</li> + * <li>{@link #SCROLL_INDICATOR_LEFT}</li> + * <li>{@link #SCROLL_INDICATOR_RIGHT}</li> + * <li>{@link #SCROLL_INDICATOR_START}</li> + * <li>{@link #SCROLL_INDICATOR_END}</li> + * </ul> + * @return {@code true} if the specified indicator(s) are enabled, + * {@code false} otherwise + * @attr ref android.R.styleable#View_scrollIndicators + */ + public boolean isScrollIndicatorEnabled(int direction) { + // Shift and sanitize input. + direction <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; + direction &= SCROLL_INDICATORS_PFLAG3_MASK; + + // All of the flags must be set. + return (mPrivateFlags3 & direction) == direction; + } + ListenerInfo getListenerInfo() { if (mListenerInfo != null) { return mListenerInfo; @@ -13444,6 +13713,75 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } + void getScrollIndicatorBounds(@NonNull Rect out) { + out.left = mScrollX; + out.right = mScrollX + mRight - mLeft; + out.top = mScrollY; + out.bottom = mScrollY + mBottom - mTop; + } + + private void onDrawScrollIndicators(Canvas c) { + if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) { + // No scroll indicators enabled. + return; + } + + final Drawable dr = mScrollIndicatorDrawable; + if (dr == null) { + // Scroll indicators aren't supported here. + return; + } + + final int h = dr.getIntrinsicHeight(); + final int w = dr.getIntrinsicWidth(); + final Rect rect = mAttachInfo.mTmpInvalRect; + getScrollIndicatorBounds(rect); + + if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) { + final boolean canScrollUp = canScrollVertically(-1); + if (canScrollUp) { + dr.setBounds(rect.left, rect.top, rect.right, rect.top + h); + dr.draw(c); + } + } + + if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) { + final boolean canScrollDown = canScrollVertically(1); + if (canScrollDown) { + dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom); + dr.draw(c); + } + } + + final int leftRtl; + final int rightRtl; + if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) { + leftRtl = PFLAG3_SCROLL_INDICATOR_END; + rightRtl = PFLAG3_SCROLL_INDICATOR_START; + } else { + leftRtl = PFLAG3_SCROLL_INDICATOR_START; + rightRtl = PFLAG3_SCROLL_INDICATOR_END; + } + + final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl; + if ((mPrivateFlags3 & leftMask) != 0) { + final boolean canScrollLeft = canScrollHorizontally(-1); + if (canScrollLeft) { + dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom); + dr.draw(c); + } + } + + final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl; + if ((mPrivateFlags3 & rightMask) != 0) { + final boolean canScrollRight = canScrollHorizontally(1); + if (canScrollRight) { + dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom); + dr.draw(c); + } + } + } + /** * <p>Request the drawing of the horizontal and the vertical scrollbar. The * scrollbars are painted only if they have been awakened first.</p> @@ -17272,6 +17610,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param canvas canvas to draw into */ public void onDrawForeground(Canvas canvas) { + onDrawScrollIndicators(canvas); onDrawScrollBars(canvas); final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index f240fd6..babb4e9 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -18,6 +18,7 @@ package android.view; import android.animation.LayoutTransition; import android.annotation.IdRes; +import android.annotation.NonNull; import android.annotation.UiThread; import android.content.Context; import android.content.Intent; @@ -3547,6 +3548,21 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return child.draw(canvas, this, drawingTime); } + @Override + void getScrollIndicatorBounds(@NonNull Rect out) { + super.getScrollIndicatorBounds(out); + + // If we have padding and we're supposed to clip children to that + // padding, offset the scroll indicators to match our clip bounds. + final boolean clipToPadding = (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK; + if (clipToPadding) { + out.left += mPaddingLeft; + out.right -= mPaddingRight; + out.top += mPaddingTop; + out.bottom -= mPaddingBottom; + } + } + /** * Returns whether this group's children are clipped to their bounds before drawing. * The default value is true. diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java index b8110e3..61ee00c 100644 --- a/core/java/com/android/internal/app/AlertController.java +++ b/core/java/com/android/internal/app/AlertController.java @@ -526,11 +526,15 @@ public class AlertController { mWindow.setCloseOnTouchOutsideIfNotSet(true); } - // Only display the divider if we have a title and a custom view or a - // message. if (hasTopPanel) { + // Only clip scrolling content to padding if we have a title. + if (mScrollView != null) { + mScrollView.setClipToPadding(true); + } + + // Only show the divider if we have a title. final View divider; - if (mMessage != null || hasCustomPanel || mListView != null) { + if (mMessage != null || mListView != null || hasCustomPanel) { divider = topPanel.findViewById(R.id.titleDivider); } else { divider = topPanel.findViewById(R.id.titleDividerTop); @@ -541,6 +545,17 @@ public class AlertController { } } + // Update scroll indicators as needed. + if (!hasCustomPanel) { + final View content = mListView != null ? mListView : mScrollView; + if (content != null) { + final int indicators = (hasTopPanel ? View.SCROLL_INDICATOR_TOP : 0) + | (hasButtonPanel ? View.SCROLL_INDICATOR_BOTTOM : 0); + content.setScrollIndicators(indicators, + View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM); + } + } + final TypedArray a = mContext.obtainStyledAttributes( null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0); setBackground(a, topPanel, contentPanel, customPanel, buttonPanel, @@ -654,59 +669,6 @@ public class AlertController { contentPanel.setVisibility(View.GONE); } } - - // Set up scroll indicators (if present). - final View indicatorUp = contentPanel.findViewById(R.id.scrollIndicatorUp); - final View indicatorDown = contentPanel.findViewById(R.id.scrollIndicatorDown); - if (indicatorUp != null || indicatorDown != null) { - if (mMessage != null) { - // We're just showing the ScrollView, set up listener. - mScrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() { - @Override - public void onScrollChange(View v, int scrollX, int scrollY, - int oldScrollX, int oldScrollY) { - manageScrollIndicators(v, indicatorUp, indicatorDown); - } - }); - // Set up the indicators following layout. - mScrollView.post(new Runnable() { - @Override - public void run() { - manageScrollIndicators(mScrollView, indicatorUp, indicatorDown); - } - }); - - } else if (mListView != null) { - // We're just showing the AbsListView, set up listener. - mListView.setOnScrollListener(new AbsListView.OnScrollListener() { - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - // That's cool, I guess? - } - - @Override - public void onScroll(AbsListView v, int firstVisibleItem, - int visibleItemCount, int totalItemCount) { - manageScrollIndicators(v, indicatorUp, indicatorDown); - } - }); - // Set up the indicators following layout. - mListView.post(new Runnable() { - @Override - public void run() { - manageScrollIndicators(mListView, indicatorUp, indicatorDown); - } - }); - } else { - // We don't have any content to scroll, remove the indicators. - if (indicatorUp != null) { - contentPanel.removeView(indicatorUp); - } - if (indicatorDown != null) { - contentPanel.removeView(indicatorDown); - } - } - } } private static void manageScrollIndicators(View v, View upIndicator, View downIndicator) { diff --git a/core/java/com/android/internal/widget/ButtonBarLayout.java b/core/java/com/android/internal/widget/ButtonBarLayout.java index 64e6c69..f58ab03 100644 --- a/core/java/com/android/internal/widget/ButtonBarLayout.java +++ b/core/java/com/android/internal/widget/ButtonBarLayout.java @@ -17,6 +17,7 @@ package com.android.internal.widget; import android.content.Context; +import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; @@ -29,37 +30,39 @@ import com.android.internal.R; * orientation when it can't fit its child views horizontally. */ public class ButtonBarLayout extends LinearLayout { - /** Spacer used in horizontal orientation. */ - private final View mSpacer; - /** Whether the current configuration allows stacking. */ - private final boolean mAllowStacked; + private final boolean mAllowStacking; /** Whether the layout is currently stacked. */ private boolean mStacked; + private int mLastWidthSize = -1; + public ButtonBarLayout(Context context, AttributeSet attrs) { super(context, attrs); - mAllowStacked = context.getResources().getBoolean(R.bool.allow_stacked_button_bar); - mSpacer = findViewById(R.id.spacer); + final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ButtonBarLayout); + mAllowStacking = ta.getBoolean(R.styleable.ButtonBarLayout_allowStacking, false); + ta.recycle(); + + mStacked = getOrientation() == VERTICAL; } @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (mAllowStacking) { + final int widthSize = MeasureSpec.getSize(widthMeasureSpec); + if (widthSize > mLastWidthSize && mStacked) { + // We're being measured wider this time, try un-stacking. + setStacked(false); + } - // Maybe we can fit the content now? - if (w > oldw && mStacked) { - setStacked(false); + mLastWidthSize = widthSize; } - } - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - if (mAllowStacked && getOrientation() == LinearLayout.HORIZONTAL) { + if (mAllowStacking && !mStacked) { final int measuredWidth = getMeasuredWidthAndState(); final int measuredWidthState = measuredWidth & MEASURED_STATE_MASK; if (measuredWidthState == MEASURED_STATE_TOO_SMALL) { @@ -75,8 +78,9 @@ public class ButtonBarLayout extends LinearLayout { setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL); setGravity(stacked ? Gravity.RIGHT : Gravity.BOTTOM); - if (mSpacer != null) { - mSpacer.setVisibility(stacked ? View.GONE : View.INVISIBLE); + final View spacer = findViewById(R.id.spacer); + if (spacer != null) { + spacer.setVisibility(stacked ? View.GONE : View.INVISIBLE); } // Reverse the child order. This is specific to the Material button diff --git a/core/res/res/drawable/scroll_indicator_material.xml b/core/res/res/drawable/scroll_indicator_material.xml new file mode 100644 index 0000000..63cd584 --- /dev/null +++ b/core/res/res/drawable/scroll_indicator_material.xml @@ -0,0 +1,23 @@ +<?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. +--> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:tint="?attr/colorForeground"> + <solid android:color="#1f000000" /> + <size + android:height="1dp" + android:width="1dp" /> +</shape> diff --git a/core/res/res/layout/alert_dialog_button_bar_material.xml b/core/res/res/layout/alert_dialog_button_bar_material.xml index 1eea4e1..6e102f3 100644 --- a/core/res/res/layout/alert_dialog_button_bar_material.xml +++ b/core/res/res/layout/alert_dialog_button_bar_material.xml @@ -27,6 +27,7 @@ android:paddingTop="4dp" android:paddingBottom="4dp" android:gravity="bottom" + android:allowStacking="@bool/allow_stacked_button_bar" style="?attr/buttonBarStyle"> <Button @@ -53,4 +54,4 @@ style="?attr/buttonBarPositiveButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" /> -</com.android.internal.widget.ButtonBarLayout>
\ No newline at end of file +</com.android.internal.widget.ButtonBarLayout> diff --git a/core/res/res/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml index bf1e383..95c2459 100644 --- a/core/res/res/layout/alert_dialog_material.xml +++ b/core/res/res/layout/alert_dialog_material.xml @@ -24,52 +24,51 @@ <include layout="@layout/alert_dialog_title_material" /> - <FrameLayout android:id="@+id/contentPanel" + <FrameLayout + android:id="@+id/contentPanel" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:minHeight="48dp"> - <View android:id="@+id/scrollIndicatorUp" - android:visibility="gone" - android:layout_width="match_parent" - android:layout_height="1dp" - android:layout_gravity="top" - android:background="@drawable/list_divider_material"/> - <ScrollView android:id="@+id/scrollView" + + <ScrollView + android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="wrap_content" + android:paddingTop="@dimen/dialog_padding_top_material" android:clipToPadding="false"> + <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> - <TextView android:id="@+id/message" - style="@style/TextAppearance.Material.Subhead" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingStart="?attr/dialogPreferredPadding" - android:paddingTop="@dimen/dialog_padding_top_material" - android:paddingEnd="?attr/dialogPreferredPadding" /> - <Space android:id="@+id/textSpacerNoButtons" - android:visibility="gone" - android:layout_width="0dp" - android:layout_height="@dimen/dialog_padding_top_material" /> + + <TextView + android:id="@+id/message" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingEnd="?attr/dialogPreferredPadding" + android:paddingStart="?attr/dialogPreferredPadding" + style="@style/TextAppearance.Material.Subhead" /> + + <Space + android:id="@+id/textSpacerNoButtons" + android:visibility="gone" + android:layout_width="0dp" + android:layout_height="@dimen/dialog_padding_top_material" /> </LinearLayout> </ScrollView> - <View android:id="@+id/scrollIndicatorDown" - android:visibility="gone" - android:layout_width="match_parent" - android:layout_height="1dp" - android:layout_gravity="bottom" - android:background="@drawable/list_divider_material"/> </FrameLayout> - <FrameLayout android:id="@+id/customPanel" + <FrameLayout + android:id="@+id/customPanel" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:minHeight="48dp"> - <FrameLayout android:id="@+id/custom" + + <FrameLayout + android:id="@+id/custom" android:layout_width="match_parent" android:layout_height="wrap_content" /> </FrameLayout> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 2914817..1c4b5f7 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -1998,6 +1998,13 @@ <attr name="needsDefaultBackgrounds" format="boolean" /> </declare-styleable> + <!-- @hide --> + <declare-styleable name="ButtonBarLayout"> + <!-- Whether to automatically stack the buttons when there is not + enough space to lay them out side-by-side. --> + <attr name="allowStacking" format="boolean" /> + </declare-styleable> + <!-- Fragment animation class attributes. --> <declare-styleable name="FragmentAnimation"> <attr name="fragmentOpenEnterAnimation" format="reference" /> @@ -2715,6 +2722,28 @@ <enum name="add" value="16" /> </attr> + <!-- Defines which scroll indicators should be displayed when the view + can be scrolled. Multiple values may be combined using logical OR, + for example "top|bottom". --> + <attr name="scrollIndicators"> + <!-- No scroll indicators are displayed. --> + <flag name="none" value="0x0000" /> + <!-- Displays top scroll indicator when view can be scrolled up. --> + <flag name="top" value="0x0100" /> + <!-- Displays bottom scroll indicator when vew can be scrolled down. --> + <flag name="bottom" value="0x0200" /> + <!-- Displays left scroll indicator when vew can be scrolled left. --> + <flag name="left" value="0x0400" /> + <!-- Displays right scroll indicator when vew can be scrolled right. --> + <flag name="right" value="0x0800" /> + <!-- Displays right scroll indicator when vew can be scrolled in the + start direction. --> + <flag name="start" value="0x1000" /> + <!-- Displays right scroll indicator when vew can be scrolled in the + end direction. --> + <flag name="end" value="0x2000" /> + </attr> + </declare-styleable> <!-- Attributes that can be assigned to a tag for a particular View. --> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 83ac6c1..297b302 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2623,7 +2623,6 @@ <public type="attr" name="fullBackupContent" /> <public type="style" name="Widget.Material.Button.Colored" /> - <public type="style" name="Theme.Material.DayNight" /> <public type="style" name="Theme.Material.DayNight.DarkActionBar" /> <public type="style" name="Theme.Material.DayNight.Dialog" /> @@ -2686,4 +2685,5 @@ <public type="attr" name="assistBlocked" /> <public type="attr" name="stylusButtonPressable" /> <public type="attr" name="supportsLaunchVoiceAssistFromKeyguard" /> + <public type="attr" name="scrollIndicators" /> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index a57b3b8..28ffbfa 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2180,8 +2180,6 @@ <java-symbol type="bool" name="config_defaultWindowFeatureContextMenu" /> <java-symbol type="layout" name="simple_account_item" /> - <java-symbol type="id" name="scrollIndicatorUp" /> - <java-symbol type="id" name="scrollIndicatorDown" /> <java-symbol type="array" name="config_sms_convert_destination_number_support" /> <java-symbol type="string" name="prohibit_manual_network_selection_in_gobal_mode" /> <java-symbol type="id" name="profile_button" /> @@ -2204,7 +2202,6 @@ <java-symbol type="string" name="usb_midi_peripheral_manufacturer_name" /> <java-symbol type="string" name="usb_midi_peripheral_product_name" /> - <java-symbol type="bool" name="allow_stacked_button_bar" /> <java-symbol type="id" name="spacer" /> <java-symbol type="xml" name="bookmarks" /> @@ -2258,4 +2255,5 @@ <java-symbol type="id" name="title_icon" /> <java-symbol type="id" name="day_picker_view_pager" /> <java-symbol type="layout" name="day_picker_content_material" /> + <java-symbol type="drawable" name="scroll_indicator_material" /> </resources> diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml index e679e0a..f02fed1 100644 --- a/core/res/res/values/themes_material.xml +++ b/core/res/res/values/themes_material.xml @@ -207,8 +207,8 @@ please see themes_device_defaults.xml. <!-- Scrollbar attributes --> <item name="scrollbarFadeDuration">250</item> - <item name="scrollbarDefaultDelayBeforeFade">300</item> - <item name="scrollbarSize">10dip</item> + <item name="scrollbarDefaultDelayBeforeFade">400</item> + <item name="scrollbarSize">10dp</item> <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_material</item> <item name="scrollbarThumbVertical">@drawable/scrollbar_handle_material</item> <item name="scrollbarTrackHorizontal">@null</item> @@ -563,8 +563,8 @@ please see themes_device_defaults.xml. <!-- Scrollbar attributes --> <item name="scrollbarFadeDuration">250</item> - <item name="scrollbarDefaultDelayBeforeFade">300</item> - <item name="scrollbarSize">10dip</item> + <item name="scrollbarDefaultDelayBeforeFade">400</item> + <item name="scrollbarSize">10dp</item> <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_material</item> <item name="scrollbarThumbVertical">@drawable/scrollbar_handle_material</item> <item name="scrollbarTrackHorizontal">@null</item> |