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

Commit 46ca5060 authored by Adam Powell's avatar Adam Powell Committed by Android (Google) Code Review
Browse files

Merge "Nested scrolling!"

parents d2cd53d4 10ba2773
Loading
Loading
Loading
Loading
+31 −6
Original line number Diff line number Diff line
@@ -826,6 +826,7 @@ package android {
    field public static final int name = 16842755; // 0x1010003
    field public static final int navigationMode = 16843471; // 0x10102cf
    field public static final int negativeButtonText = 16843254; // 0x10101f6
    field public static final int nestedScrollingEnabled = 16843843; // 0x1010443
    field public static final int nextFocusDown = 16842980; // 0x10100e4
    field public static final int nextFocusForward = 16843580; // 0x101033c
    field public static final int nextFocusLeft = 16842977; // 0x10100e1
@@ -1286,8 +1287,8 @@ package android {
    field public static final int windowActionBar = 16843469; // 0x10102cd
    field public static final int windowActionBarOverlay = 16843492; // 0x10102e4
    field public static final int windowActionModeOverlay = 16843485; // 0x10102dd
    field public static final int windowAllowEnterTransitionOverlap = 16843848; // 0x1010448
    field public static final int windowAllowExitTransitionOverlap = 16843847; // 0x1010447
    field public static final int windowAllowEnterTransitionOverlap = 16843849; // 0x1010449
    field public static final int windowAllowExitTransitionOverlap = 16843848; // 0x1010448
    field public static final int windowAnimationStyle = 16842926; // 0x10100ae
    field public static final int windowBackground = 16842836; // 0x1010054
    field public static final int windowCloseOnTouchOutside = 16843611; // 0x101035b
@@ -1297,9 +1298,9 @@ package android {
    field public static final int windowDisablePreview = 16843298; // 0x1010222
    field public static final int windowEnableSplitTouch = 16843543; // 0x1010317
    field public static final int windowEnterAnimation = 16842932; // 0x10100b4
    field public static final int windowEnterTransition = 16843843; // 0x1010443
    field public static final int windowEnterTransition = 16843844; // 0x1010444
    field public static final int windowExitAnimation = 16842933; // 0x10100b5
    field public static final int windowExitTransition = 16843844; // 0x1010444
    field public static final int windowExitTransition = 16843845; // 0x1010445
    field public static final int windowFrame = 16842837; // 0x1010055
    field public static final int windowFullscreen = 16843277; // 0x101020d
    field public static final int windowHideAnimation = 16842935; // 0x10100b7
@@ -1310,8 +1311,8 @@ package android {
    field public static final int windowNoDisplay = 16843294; // 0x101021e
    field public static final int windowNoTitle = 16842838; // 0x1010056
    field public static final int windowOverscan = 16843727; // 0x10103cf
    field public static final int windowSharedElementEnterTransition = 16843845; // 0x1010445
    field public static final int windowSharedElementExitTransition = 16843846; // 0x1010446
    field public static final int windowSharedElementEnterTransition = 16843846; // 0x1010446
    field public static final int windowSharedElementExitTransition = 16843847; // 0x1010447
    field public static final int windowShowAnimation = 16842934; // 0x10100b6
    field public static final int windowShowWallpaper = 16843410; // 0x1010292
    field public static final int windowSoftInputMode = 16843307; // 0x101022b
@@ -29984,6 +29985,9 @@ package android.view {
    method public boolean dispatchKeyEvent(android.view.KeyEvent);
    method public boolean dispatchKeyEventPreIme(android.view.KeyEvent);
    method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
    method public boolean dispatchNestedFling(float, float);
    method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
    method public boolean dispatchNestedScroll(int, int, int, int, int[]);
    method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
    method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
    method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
@@ -30133,6 +30137,7 @@ package android.view {
    method public float getY();
    method public boolean hasFocus();
    method public boolean hasFocusable();
    method public boolean hasNestedScrollingParent();
    method public boolean hasOnClickListeners();
    method public boolean hasOverlappingRendering();
    method public boolean hasTransientState();
@@ -30168,6 +30173,7 @@ package android.view {
    method public boolean isLayoutDirectionResolved();
    method public boolean isLayoutRequested();
    method public boolean isLongClickable();
    method public boolean isNestedScrollingEnabled();
    method public boolean isOpaque();
    method protected boolean isPaddingOffsetRequired();
    method public boolean isPaddingRelative();
@@ -30319,6 +30325,7 @@ package android.view {
    method protected final void setMeasuredDimension(int, int);
    method public void setMinimumHeight(int);
    method public void setMinimumWidth(int);
    method public void setNestedScrollingEnabled(boolean);
    method public void setNextFocusDownId(int);
    method public void setNextFocusForwardId(int);
    method public void setNextFocusLeftId(int);
@@ -30383,6 +30390,8 @@ package android.view {
    method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback);
    method public void startAnimation(android.view.animation.Animation);
    method public final boolean startDrag(android.content.ClipData, android.view.View.DragShadowBuilder, java.lang.Object, int);
    method public boolean startNestedScroll(int);
    method public void stopNestedScroll();
    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
    method public void unscheduleDrawable(android.graphics.drawable.Drawable);
    method protected boolean verifyDrawable(android.graphics.drawable.Drawable);
@@ -30471,6 +30480,9 @@ package android.view {
    field public static final int SCROLLBAR_POSITION_DEFAULT = 0; // 0x0
    field public static final int SCROLLBAR_POSITION_LEFT = 1; // 0x1
    field public static final int SCROLLBAR_POSITION_RIGHT = 2; // 0x2
    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 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
@@ -30740,6 +30752,7 @@ package android.view {
    method public android.view.animation.Animation.AnimationListener getLayoutAnimationListener();
    method public int getLayoutMode();
    method public android.animation.LayoutTransition getLayoutTransition();
    method public int getNestedScrollAxes();
    method public int getPersistentDrawingCache();
    method public int indexOfChild(android.view.View);
    method public final void invalidateChild(android.view.View, android.graphics.Rect);
@@ -30760,8 +30773,14 @@ package android.view {
    method public boolean onInterceptHoverEvent(android.view.MotionEvent);
    method public boolean onInterceptTouchEvent(android.view.MotionEvent);
    method protected abstract void onLayout(boolean, int, int, int, int);
    method public boolean onNestedFling(android.view.View, float, float);
    method public void onNestedPreScroll(android.view.View, int, int, int[]);
    method public void onNestedScroll(android.view.View, int, int, int, int);
    method public void onNestedScrollAccepted(android.view.View, android.view.View, int);
    method protected boolean onRequestFocusInDescendants(int, android.graphics.Rect);
    method public boolean onRequestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
    method public boolean onStartNestedScroll(android.view.View, android.view.View, int);
    method public void onStopNestedScroll(android.view.View);
    method public void recomputeViewAttributes(android.view.View);
    method public void removeAllViews();
    method public void removeAllViewsInLayout();
@@ -30892,6 +30911,12 @@ package android.view {
    method public abstract boolean isTextAlignmentResolved();
    method public abstract boolean isTextDirectionResolved();
    method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
    method public abstract boolean onNestedFling(android.view.View, float, float);
    method public abstract void onNestedPreScroll(android.view.View, int, int, int[]);
    method public abstract void onNestedScroll(android.view.View, int, int, int, int);
    method public abstract void onNestedScrollAccepted(android.view.View, android.view.View, int);
    method public abstract boolean onStartNestedScroll(android.view.View, android.view.View, int);
    method public abstract void onStopNestedScroll(android.view.View);
    method public abstract void recomputeViewAttributes(android.view.View);
    method public abstract void requestChildFocus(android.view.View, android.view.View);
    method public abstract boolean requestChildRectangleOnScreen(android.view.View, android.graphics.Rect, boolean);
+300 −7
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Insets;
import android.graphics.Interpolator;
@@ -2395,6 +2394,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x100;
    /**
     * Flag indicating that nested scrolling is enabled for this view.
     * The view will optionally cooperate with views up its parent chain to allow for
     * integrated nested scrolling along the same axis.
     */
    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x200;
    /* End of masks for mPrivateFlags3 */
    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
@@ -2846,6 +2852,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    public static final int SCREEN_STATE_ON = 0x1;
    /**
     * Indicates no axis of view scrolling.
     */
    public static final int SCROLL_AXIS_NONE = 0;
    /**
     * Indicates scrolling along the horizontal axis.
     */
    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
    /**
     * Indicates scrolling along the vertical axis.
     */
    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
    /**
     * Controls the over-scroll mode for this view.
     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
@@ -3472,6 +3493,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    ViewOverlay mOverlay;
    /**
     * The currently active parent view for receiving delegated nested scrolling events.
     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
     * by {@link #stopNestedScroll()} at the same point where we clear
     * requestDisallowInterceptTouchEvent.
     */
    private ViewParent mNestedScrollingParent;
    /**
     * Consistency verifier for debugging purposes.
     * @hide
@@ -3482,6 +3511,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
    private int[] mTempNestedScrollConsumed;
    /**
     * Simple constructor to use when creating a view from code.
     *
@@ -3963,6 +3994,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                case R.styleable.View_sharedElementName:
                    setSharedElementName(a.getString(attr));
                    break;
                case R.styleable.View_nestedScrollingEnabled:
                    setNestedScrollingEnabled(a.getBoolean(attr, false));
                    break;
            }
        }
@@ -7976,27 +8010,46 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @return True if the event was handled by the view, false otherwise.
     */
    public boolean dispatchTouchEvent(MotionEvent event) {
        boolean result = false;
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
        }
        final int actionMasked = event.getActionMasked();
        if (actionMasked == MotionEvent.ACTION_DOWN) {
            // Defensive cleanup for new gesture
            stopNestedScroll();
        }
        if (onFilterTouchEventForSecurity(event)) {
            //noinspection SimplifiableIfStatement
            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
                return true;
                result = true;
            }
            if (onTouchEvent(event)) {
                return true;
            if (!result && onTouchEvent(event)) {
                result = true;
            }
        }
        if (mInputEventConsistencyVerifier != null) {
        if (!result && mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
        }
        return false;
        // Clean up after nested scrolls if this is the end of a gesture;
        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
        // of the gesture.
        if (actionMasked == MotionEvent.ACTION_UP ||
                actionMasked == MotionEvent.ACTION_CANCEL ||
                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
            stopNestedScroll();
        }
        return result;
    }
    /**
@@ -12735,6 +12788,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        removeLongPressCallback();
        removePerformClickCallback();
        removeSendViewScrolledAccessibilityEventCallback();
        stopNestedScroll();
        destroyDrawingCache();
        destroyLayer(false);
@@ -17900,6 +17954,245 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        mOverScrollMode = overScrollMode;
    }
    /**
     * Enable or disable nested scrolling for this view.
     *
     * <p>If this property is set to true the view will be permitted to initiate nested
     * scrolling operations with a compatible parent view in the current hierarchy. If this
     * view does not implement nested scrolling this will have no effect.</p>
     *
     * @param enabled true to enable nested scrolling, false to disable
     *
     * @see #isNestedScrollingEnabled()
     */
    public void setNestedScrollingEnabled(boolean enabled) {
        if (enabled) {
            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
        } else {
            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
        }
    }
    /**
     * Returns true if nested scrolling is enabled for this view.
     *
     * <p>If nested scrolling is enabled and this View class implementation supports it,
     * this view will act as a nested scrolling child view when applicable, forwarding data
     * about the scroll operation in progress to a compatible and cooperating nested scrolling
     * parent.</p>
     *
     * @return true if nested scrolling is enabled
     *
     * @see #setNestedScrollingEnabled(boolean)
     */
    public boolean isNestedScrollingEnabled() {
        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
                PFLAG3_NESTED_SCROLLING_ENABLED;
    }
    /**
     * Begin a nestable scroll operation along the given axes.
     *
     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
     *
     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
     * In the case of touch scrolling the nested scroll will be terminated automatically in
     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
     * In the event of programmatic scrolling the caller must explicitly call
     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
     *
     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
     * If it returns false the caller may ignore the rest of this contract until the next scroll.
     * </p>
     *
     * <p>At each incremental step of the scroll the caller should invoke
     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
     * parent at least partially consumed the scroll and the caller should adjust the amount it
     * scrolls by.</p>
     *
     * <p>After applying the remainder of the scroll delta the caller should invoke
     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
     * </p>
     *
     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
     *             {@link #SCROLL_AXIS_VERTICAL}.
     * @return true if a cooperative parent was found and nested scrolling has been enabled for
     *         the current gesture.
     *
     * @see #stopNestedScroll()
     * @see #dispatchNestedPreScroll(int, int, int[], int[])
     * @see #dispatchNestedScroll(int, int, int, int, int[])
     */
    public boolean startNestedScroll(int axes) {
        if (isNestedScrollingEnabled()) {
            ViewParent p = getParent();
            View child = this;
            while (p != null) {
                try {
                    if (p.onStartNestedScroll(child, this, axes)) {
                        mNestedScrollingParent = p;
                        p.onNestedScrollAccepted(child, this, axes);
                        return true;
                    }
                } catch (AbstractMethodError e) {
                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
                            "method onStartNestedScroll", e);
                    // Allow the search upward to continue
                }
                if (p instanceof View) {
                    child = (View) p;
                }
                p = p.getParent();
            }
        }
        return false;
    }
    /**
     * Stop a nested scroll in progress.
     *
     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
     *
     * @see #startNestedScroll(int)
     */
    public void stopNestedScroll() {
        if (mNestedScrollingParent != null) {
            mNestedScrollingParent.onStopNestedScroll(this);
            mNestedScrollingParent = null;
        }
    }
    /**
     * Returns true if this view has a nested scrolling parent.
     *
     * <p>The presence of a nested scrolling parent indicates that this view has initiated
     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
     *
     * @return whether this view has a nested scrolling parent
     */
    public boolean hasNestedScrollingParent() {
        return mNestedScrollingParent != null;
    }
    /**
     * Dispatch one step of a nested scroll in progress.
     *
     * <p>Implementations of views that support nested scrolling should call this to report
     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
     * is not currently in progress or nested scrolling is not
     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
     *
     * <p>Compatible View implementations should also call
     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
     * consuming a component of the scroll event themselves.</p>
     *
     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
     * @param offsetInWindow Optional. If not null, on return this will contain the offset
     *                       in local view coordinates of this view from before this operation
     *                       to after it completes. View implementations may use this to adjust
     *                       expected input coordinate tracking.
     * @return true if the event was dispatched, false if it could not be dispatched.
     * @see #dispatchNestedPreScroll(int, int, int[], int[])
     */
    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
            int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
            int startX = 0;
            int startY = 0;
            if (offsetInWindow != null) {
                getLocationInWindow(offsetInWindow);
                startX = offsetInWindow[0];
                startY = offsetInWindow[1];
            }
            mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
                    dxUnconsumed, dyUnconsumed);
            if (offsetInWindow != null) {
                getLocationInWindow(offsetInWindow);
                offsetInWindow[0] -= startX;
                offsetInWindow[1] -= startY;
            }
            return true;
        }
        return false;
    }
    /**
     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
     *
     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
     * scrolling operation to consume some or all of the scroll operation before the child view
     * consumes it.</p>
     *
     * @param dx Horizontal scroll distance in pixels
     * @param dy Vertical scroll distance in pixels
     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
     *                 and consumed[1] the consumed dy.
     * @param offsetInWindow Optional. If not null, on return this will contain the offset
     *                       in local view coordinates of this view from before this operation
     *                       to after it completes. View implementations may use this to adjust
     *                       expected input coordinate tracking.
     * @return true if the parent consumed some or all of the scroll delta
     * @see #dispatchNestedScroll(int, int, int, int, int[])
     */
    public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
            int startX = 0;
            int startY = 0;
            if (offsetInWindow != null) {
                getLocationInWindow(offsetInWindow);
                startX = offsetInWindow[0];
                startY = offsetInWindow[1];
            }
            if (consumed == null) {
                if (mTempNestedScrollConsumed == null) {
                    mTempNestedScrollConsumed = new int[2];
                }
                consumed = mTempNestedScrollConsumed;
            }
            consumed[0] = 0;
            consumed[1] = 0;
            mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
            if (offsetInWindow != null) {
                getLocationInWindow(offsetInWindow);
                offsetInWindow[0] -= startX;
                offsetInWindow[1] -= startY;
            }
            return consumed[0] != 0 || consumed[1] != 0;
        }
        return false;
    }
    /**
     * Dispatch a fling to a nested scrolling parent.
     *
     * <p>If a nested scrolling child view would normally fling but it is at the edge of its
     * own content it should use this method to delegate the fling to its nested scrolling parent.
     * The view implementation can use a {@link VelocityTracker} to obtain the velocity values
     * to pass.</p>
     *
     * @param velocityX Horizontal fling velocity in pixels per second
     * @param velocityY Vertical fling velocity in pixels per second
     * @return true if the nested scrolling parent consumed the fling
     */
    public boolean dispatchNestedFling(float velocityX, float velocityY) {
        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY);
        }
        return false;
    }
    /**
     * Gets a scale factor that determines the distance the view should scroll
     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
+76 −0

File changed.

Preview size limit exceeded, changes collapsed.

+115 −0

File changed.

Preview size limit exceeded, changes collapsed.

+27 −0
Original line number Diff line number Diff line
@@ -6090,6 +6090,33 @@ public final class ViewRootImpl implements ViewParent,
        // Do nothing.
    }

    @Override
    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
        return false;
    }

    @Override
    public void onStopNestedScroll(View target) {
    }

    @Override
    public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) {
    }

    @Override
    public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
            int dxUnconsumed, int dyUnconsumed) {
    }

    @Override
    public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
    }

    @Override
    public boolean onNestedFling(View target, float velocityX, float velocityY) {
        return false;
    }

    void changeCanvasOpacity(boolean opaque) {
        // TODO(romainguy): recreate Canvas (software or hardware) to reflect the opacity change.
        Log.d(TAG, "changeCanvasOpacity: opaque=" + opaque);
Loading