Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8876e444 authored by Alan Viverette's avatar Alan Viverette Committed by Android Git Automerger
Browse files

am 14823d60: am 72a04431: am 71b0cb04: Merge "Add scroll indicators on View,...

am 14823d60: am 72a04431: am 71b0cb04: Merge "Add scroll indicators on View, use in AlertDialog" into mnc-dev

* commit '14823d60':
  Add scroll indicators on View, use in AlertDialog
parents 23c60a22 14823d60
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -1050,6 +1050,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
@@ -36214,6 +36215,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();
@@ -36295,6 +36297,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();
@@ -36494,6 +36497,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);
@@ -36619,6 +36624,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
+11 −0
Original line number Diff line number Diff line
@@ -1122,6 +1122,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
@@ -38425,6 +38426,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();
@@ -38506,6 +38508,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();
@@ -38705,6 +38708,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);
@@ -38830,6 +38835,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
+339 −0
Original line number Diff line number Diff line
@@ -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;
+16 −0
Original line number Diff line number Diff line
@@ -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.
+18 −56
Original line number Diff line number Diff line
@@ -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) {
Loading