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

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

Merge "Fix misc. bugs in AbsListView smooth scrolling." into jb-dev

parents 401d93f0 e69370e1
Loading
Loading
Loading
Loading
+93 −11
Original line number Diff line number Diff line
@@ -3985,7 +3985,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
    }

    class PositionScroller implements Runnable {
        private static final int SCROLL_DURATION = 400;
        private static final int SCROLL_DURATION = 200;

        private static final int MOVE_DOWN_POS = 1;
        private static final int MOVE_UP_POS = 2;
@@ -4006,21 +4006,35 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
            mExtraScroll = ViewConfiguration.get(mContext).getScaledFadingEdgeLength();
        }

        void start(int position) {
        void start(final int position) {
            stop();

            final int childCount = getChildCount();
            if (childCount == 0) {
                // Can't scroll without children.
                if (mDataChanged) {
                    // But we might have something in a minute.
                    post(new Runnable() {
                        @Override public void run() {
                            start(position);
                        }
                    });
                }
                return;
            }

            final int firstPos = mFirstPosition;
            final int lastPos = firstPos + getChildCount() - 1;
            final int lastPos = firstPos + childCount - 1;

            int viewTravelCount;
            if (position <= firstPos) {
            if (position < firstPos) {
                viewTravelCount = firstPos - position + 1;
                mMode = MOVE_UP_POS;
            } else if (position >= lastPos) {
            } else if (position > lastPos) {
                viewTravelCount = position - lastPos + 1;
                mMode = MOVE_DOWN_POS;
            } else {
                // Already on screen, nothing to do
                scrollToVisible(position, INVALID_POSITION, SCROLL_DURATION);
                return;
            }

@@ -4036,7 +4050,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
            postOnAnimation(this);
        }

        void start(int position, int boundPosition) {
        void start(final int position, final int boundPosition) {
            stop();

            if (boundPosition == INVALID_POSITION) {
@@ -4044,11 +4058,25 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                return;
            }

            final int childCount = getChildCount();
            if (childCount == 0) {
                // Can't scroll without children.
                if (mDataChanged) {
                    // But we might have something in a minute.
                    post(new Runnable() {
                        @Override public void run() {
                            start(position, boundPosition);
                        }
                    });
                }
                return;
            }

            final int firstPos = mFirstPosition;
            final int lastPos = firstPos + getChildCount() - 1;
            final int lastPos = firstPos + childCount - 1;

            int viewTravelCount;
            if (position <= firstPos) {
            if (position < firstPos) {
                final int boundPosFromLast = lastPos - boundPosition;
                if (boundPosFromLast < 1) {
                    // Moving would shift our bound position off the screen. Abort.
@@ -4064,7 +4092,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                    viewTravelCount = posTravel;
                    mMode = MOVE_UP_POS;
                }
            } else if (position >= lastPos) {
            } else if (position > lastPos) {
                final int boundPosFromFirst = boundPosition - firstPos;
                if (boundPosFromFirst < 1) {
                    // Moving would shift our bound position off the screen. Abort.
@@ -4081,7 +4109,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                    mMode = MOVE_DOWN_POS;
                }
            } else {
                // Already on screen, nothing to do
                scrollToVisible(position, boundPosition, SCROLL_DURATION);
                return;
            }

@@ -4137,6 +4165,60 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
            postOnAnimation(this);
        }

        /**
         * Scroll such that targetPos is in the visible padded region without scrolling
         * boundPos out of view. Assumes targetPos is onscreen.
         */
        void scrollToVisible(int targetPos, int boundPos, int duration) {
            final int firstPos = mFirstPosition;
            final int childCount = getChildCount();
            final int lastPos = firstPos + childCount - 1;
            final int paddedTop = mListPadding.top;
            final int paddedBottom = getHeight() - mListPadding.bottom;

            if (targetPos < firstPos || targetPos > lastPos) {
                Log.w(TAG, "scrollToVisible called with targetPos " + targetPos +
                        " not visible [" + firstPos + ", " + lastPos + "]");
            }
            if (boundPos < firstPos || boundPos > lastPos) {
                // boundPos doesn't matter, it's already offscreen.
                boundPos = INVALID_POSITION;
            }

            final View targetChild = getChildAt(targetPos - firstPos);
            final int targetTop = targetChild.getTop();
            final int targetBottom = targetChild.getBottom();
            int scrollBy = 0;

            if (targetBottom > paddedBottom) {
                scrollBy = targetBottom - paddedBottom;
            }
            if (targetTop < paddedTop) {
                scrollBy = targetTop - paddedTop;
            }

            if (scrollBy == 0) {
                return;
            }

            if (boundPos >= 0) {
                final View boundChild = getChildAt(boundPos - firstPos);
                final int boundTop = boundChild.getTop();
                final int boundBottom = boundChild.getBottom();
                final int absScroll = Math.abs(scrollBy);

                if (scrollBy < 0 && boundBottom + absScroll > paddedBottom) {
                    // Don't scroll the bound view off the bottom of the screen.
                    scrollBy = Math.max(0, boundBottom - paddedBottom);
                } else if (scrollBy > 0 && boundTop - absScroll < paddedTop) {
                    // Don't scroll the bound view off the top of the screen.
                    scrollBy = Math.min(0, boundTop - paddedTop);
                }
            }

            smoothScrollBy(scrollBy, duration);
        }

        void stop() {
            removeCallbacks(this);
        }