diff options
| author | 2015-05-05 17:18:27 -0700 | |
|---|---|---|
| committer | 2015-05-06 10:09:35 -0700 | |
| commit | 922e1c6ed28da4c5b7ff6b1d4448fe3e8c11652f (patch) | |
| tree | 1e1a54eb7f114f626faf534068abc175716723f4 | |
| parent | 444eda0836095f58388456355e80cf3b9b127bf4 (diff) | |
Add scroll indicators on View, use in AlertDialog
Also updates default fade duration for scrollbars to match Material
spec and moves around some padding in AlertDialog so that scrolling
text and list items aren't so close to the title.
Bug: 19098033
Change-Id: I40dca6a931480c4c48463e3ea5b8361534cbd8d7
| -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 193407e8830f..cf365ff99296 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 2738bdb05081..e08ffd4514a0 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 75dc0a2d1509..f62e6a2f1449 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 f240fd6ad2a4..babb4e9066be 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 b8110e3a3ac8..61ee00c55fe0 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 64e6c69e3b12..f58ab03bc7dd 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 000000000000..63cd584ef2b7 --- /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 1eea4e124af3..6e102f35b2b8 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 bf1e383ed72f..95c24599a738 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 291481782684..1c4b5f7ec7c8 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 83ac6c1c038b..297b30272d7e 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 a57b3b80e347..28ffbfa18352 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 e679e0a7fd83..f02fed150460 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> |