summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Viverette <alanv@google.com>2015-05-06 17:11:23 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-05-06 17:11:24 +0000
commit71b0cb043f410d7f0a7852b2f297124fa9aed0e2 (patch)
tree92a9165e97c5c754e528793500f46317831242f0
parentc97b922abae0b66fcbd6138f803c9d8a23024e6e (diff)
parent922e1c6ed28da4c5b7ff6b1d4448fe3e8c11652f (diff)
downloadframeworks_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.txt11
-rw-r--r--api/system-current.txt11
-rw-r--r--core/java/android/view/View.java339
-rw-r--r--core/java/android/view/ViewGroup.java16
-rw-r--r--core/java/com/android/internal/app/AlertController.java74
-rw-r--r--core/java/com/android/internal/widget/ButtonBarLayout.java38
-rw-r--r--core/res/res/drawable/scroll_indicator_material.xml23
-rw-r--r--core/res/res/layout/alert_dialog_button_bar_material.xml3
-rw-r--r--core/res/res/layout/alert_dialog_material.xml53
-rw-r--r--core/res/res/values/attrs.xml29
-rw-r--r--core/res/res/values/public.xml2
-rwxr-xr-xcore/res/res/values/symbols.xml4
-rw-r--r--core/res/res/values/themes_material.xml8
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>