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

Commit 30dc0721 authored by Gus Prevas's avatar Gus Prevas Committed by Android (Google) Code Review
Browse files

Merge changes I636dbbc4,Idd0711a7

* changes:
  Implements flinging for anchor-based scrolling.
  Implements basic anchor-based scrolling.
parents f72ad8d0 cdc98344
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -538,6 +538,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
                    - getIntrinsicHeight());
                    - getIntrinsicHeight());
        }
        }
        float viewEnd = viewStart + fullHeight;
        float viewEnd = viewStart + fullHeight;
        // TODO: fix this check for anchor scrolling.
        if (expandingAnimated && mAmbientState.getScrollY() == 0
        if (expandingAnimated && mAmbientState.getScrollY() == 0
                && !mAmbientState.isOnKeyguard() && !iconState.isLastExpandIcon) {
                && !mAmbientState.isOnKeyguard() && !iconState.isLastExpandIcon) {
            // We are expanding animated. Because we switch to a linear interpolation in this case,
            // We are expanding animated. Because we switch to a linear interpolation in this case,
+23 −0
Original line number Original line Diff line number Diff line
@@ -42,6 +42,8 @@ public class AmbientState {


    private ArrayList<ExpandableView> mDraggedViews = new ArrayList<>();
    private ArrayList<ExpandableView> mDraggedViews = new ArrayList<>();
    private int mScrollY;
    private int mScrollY;
    private int mAnchorViewIndex;
    private int mAnchorViewY;
    private boolean mDimmed;
    private boolean mDimmed;
    private ActivatableNotificationView mActivatedChild;
    private ActivatableNotificationView mActivatedChild;
    private float mOverScrollTopAmount;
    private float mOverScrollTopAmount;
@@ -130,6 +132,27 @@ public class AmbientState {
        this.mScrollY = scrollY;
        this.mScrollY = scrollY;
    }
    }


    /**
     * Index of the child view whose Y position on screen is returned by {@link #getAnchorViewY()}.
     * Other views are laid out outwards from this view in both directions.
     */
    public int getAnchorViewIndex() {
        return mAnchorViewIndex;
    }

    public void setAnchorViewIndex(int anchorViewIndex) {
        mAnchorViewIndex = anchorViewIndex;
    }

    /** Current Y position of the view at {@link #getAnchorViewIndex()}. */
    public int getAnchorViewY() {
        return mAnchorViewY;
    }

    public void setAnchorViewY(int anchorViewY) {
        mAnchorViewY = anchorViewY;
    }

    /** Call when dragging begins. */
    /** Call when dragging begins. */
    public void onBeginDrag(ExpandableView view) {
    public void onBeginDrag(ExpandableView view) {
        mDraggedViews.add(view);
        mDraggedViews.add(view);
+699 −215

File changed.

Preview size limit exceeded, changes collapsed.

+83 −13
Original line number Original line Diff line number Diff line
@@ -41,6 +41,8 @@ import java.util.List;
 */
 */
public class StackScrollAlgorithm {
public class StackScrollAlgorithm {


    static final boolean ANCHOR_SCROLLING = false;

    private static final String LOG_TAG = "StackScrollAlgorithm";
    private static final String LOG_TAG = "StackScrollAlgorithm";
    private final ViewGroup mHostView;
    private final ViewGroup mHostView;


@@ -236,6 +238,10 @@ public class StackScrollAlgorithm {
        scrollY = Math.max(0, scrollY);
        scrollY = Math.max(0, scrollY);
        state.scrollY = (int) (scrollY + bottomOverScroll);
        state.scrollY = (int) (scrollY + bottomOverScroll);


        if (ANCHOR_SCROLLING) {
            state.anchorViewY = (int) (ambientState.getAnchorViewY() - bottomOverScroll);
        }

        //now init the visible children and update paddings
        //now init the visible children and update paddings
        int childCount = hostView.getChildCount();
        int childCount = hostView.getChildCount();
        state.visibleChildren.clear();
        state.visibleChildren.clear();
@@ -252,6 +258,11 @@ public class StackScrollAlgorithm {
        // iterating over it again, it's filled with the actual resolved value.
        // iterating over it again, it's filled with the actual resolved value.


        for (int i = 0; i < childCount; i++) {
        for (int i = 0; i < childCount; i++) {
            if (ANCHOR_SCROLLING) {
                if (i == ambientState.getAnchorViewIndex()) {
                    state.anchorViewIndex = state.visibleChildren.size();
                }
            }
            ExpandableView v = (ExpandableView) hostView.getChildAt(i);
            ExpandableView v = (ExpandableView) hostView.getChildAt(i);
            if (v.getVisibility() != View.GONE) {
            if (v.getVisibility() != View.GONE) {
                if (v == ambientState.getShelf()) {
                if (v == ambientState.getShelf()) {
@@ -350,28 +361,74 @@ public class StackScrollAlgorithm {
    private void updatePositionsForState(StackScrollAlgorithmState algorithmState,
    private void updatePositionsForState(StackScrollAlgorithmState algorithmState,
            AmbientState ambientState) {
            AmbientState ambientState) {


        if (ANCHOR_SCROLLING) {
            float currentYPosition = algorithmState.anchorViewY;
            int childCount = algorithmState.visibleChildren.size();
            for (int i = algorithmState.anchorViewIndex; i < childCount; i++) {
                if (i > algorithmState.anchorViewIndex && ambientState.beginsNewSection(i)) {
                    currentYPosition += mGapHeight;
                }
                currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition,
                        false /* reverse */);
            }
            currentYPosition = algorithmState.anchorViewY;
            for (int i = algorithmState.anchorViewIndex - 1; i >= 0; i--) {
                if (ambientState.beginsNewSection(i + 1)) {
                    currentYPosition -= mGapHeight;
                }
                currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition,
                        true /* reverse */);
            }
        } else {
            // The y coordinate of the current child.
            // The y coordinate of the current child.
            float currentYPosition = -algorithmState.scrollY;
            float currentYPosition = -algorithmState.scrollY;
            int childCount = algorithmState.visibleChildren.size();
            int childCount = algorithmState.visibleChildren.size();
            for (int i = 0; i < childCount; i++) {
            for (int i = 0; i < childCount; i++) {
            currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition);
                if (ambientState.beginsNewSection(i)) {
                    currentYPosition += mGapHeight;
                }
                currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition,
                        false /* reverse */);
            }
        }
        }
    }
    }


    /**
     * Populates the {@link ExpandableViewState} for a single child.
     *
     * @param i                The index of the child in
     * {@link StackScrollAlgorithmState#visibleChildren}.
     * @param algorithmState   The overall output state of the algorithm.
     * @param ambientState     The input state provided to the algorithm.
     * @param currentYPosition The Y position of the current pass of the algorithm.  For a forward
     *                         pass, this should be the top of the child; for a reverse pass, the
     *                         bottom of the child.
     * @param reverse          Whether we're laying out children in the reverse direction (Y
     *                         positions
     *                         decreasing) instead of the forward direction (Y positions
     *                         increasing).
     * @return The Y position after laying out the child.  This will be the {@code currentYPosition}
     * for the next call to this method, after adjusting for any gaps between children.
     */
    protected float updateChild(
    protected float updateChild(
            int i,
            int i,
            StackScrollAlgorithmState algorithmState,
            StackScrollAlgorithmState algorithmState,
            AmbientState ambientState,
            AmbientState ambientState,
            float currentYPosition) {
            float currentYPosition,
            boolean reverse) {
        ExpandableView child = algorithmState.visibleChildren.get(i);
        ExpandableView child = algorithmState.visibleChildren.get(i);
        ExpandableViewState childViewState = child.getViewState();
        ExpandableViewState childViewState = child.getViewState();
        childViewState.location = ExpandableViewState.LOCATION_UNKNOWN;
        childViewState.location = ExpandableViewState.LOCATION_UNKNOWN;
        int paddingAfterChild = getPaddingAfterChild(algorithmState, child);
        int paddingAfterChild = getPaddingAfterChild(algorithmState, child);
        int childHeight = getMaxAllowedChildHeight(child);
        int childHeight = getMaxAllowedChildHeight(child);
        if (ambientState.beginsNewSection(i)) {
        if (reverse) {
            currentYPosition += mGapHeight;
            childViewState.yTranslation = currentYPosition - (childHeight + paddingAfterChild);
            if (currentYPosition <= 0) {
                childViewState.location = ExpandableViewState.LOCATION_HIDDEN_TOP;
            }
            }
        } else {
            childViewState.yTranslation = currentYPosition;
            childViewState.yTranslation = currentYPosition;
        }
        boolean isFooterView = child instanceof FooterView;
        boolean isFooterView = child instanceof FooterView;
        boolean isEmptyShadeView = child instanceof EmptyShadeView;
        boolean isEmptyShadeView = child instanceof EmptyShadeView;


@@ -396,10 +453,14 @@ public class StackScrollAlgorithm {
            clampPositionToShelf(child, childViewState, ambientState);
            clampPositionToShelf(child, childViewState, ambientState);
        }
        }


        if (reverse) {
            currentYPosition = childViewState.yTranslation;
        } else {
            currentYPosition = childViewState.yTranslation + childHeight + paddingAfterChild;
            currentYPosition = childViewState.yTranslation + childHeight + paddingAfterChild;
            if (currentYPosition <= 0) {
            if (currentYPosition <= 0) {
                childViewState.location = ExpandableViewState.LOCATION_HIDDEN_TOP;
                childViewState.location = ExpandableViewState.LOCATION_HIDDEN_TOP;
            }
            }
        }
        if (childViewState.location == ExpandableViewState.LOCATION_UNKNOWN) {
        if (childViewState.location == ExpandableViewState.LOCATION_UNKNOWN) {
            Log.wtf(LOG_TAG, "Failed to assign location for child " + i);
            Log.wtf(LOG_TAG, "Failed to assign location for child " + i);
        }
        }
@@ -464,6 +525,7 @@ public class StackScrollAlgorithm {
                // To check if the row need to do translation according to scroll Y
                // To check if the row need to do translation according to scroll Y
                // heads up show full of row's content and any scroll y indicate that the
                // heads up show full of row's content and any scroll y indicate that the
                // translationY need to move up the HUN.
                // translationY need to move up the HUN.
                // TODO: fix this check for anchor scrolling.
                if (!mIsExpanded && isTopEntry && ambientState.getScrollY() > 0) {
                if (!mIsExpanded && isTopEntry && ambientState.getScrollY() > 0) {
                    childState.yTranslation -= ambientState.getScrollY();
                    childState.yTranslation -= ambientState.getScrollY();
                }
                }
@@ -607,10 +669,18 @@ public class StackScrollAlgorithm {
    public class StackScrollAlgorithmState {
    public class StackScrollAlgorithmState {


        /**
        /**
         * The scroll position of the algorithm
         * The scroll position of the algorithm (absolute scrolling).
         */
         */
        public int scrollY;
        public int scrollY;


        /** The index of the anchor view (anchor scrolling). */
        public int anchorViewIndex;

        /**
         * The Y position, relative to the top of the screen, of the anchor view (anchor scrolling).
         */
        public int anchorViewY;

        /**
        /**
         * The children from the host view which are not gone.
         * The children from the host view which are not gone.
         */
         */