Loading proguard.flags +2 −2 Original line number Diff line number Diff line Loading @@ -3,8 +3,8 @@ } -keep class com.android.launcher3.BaseRecyclerViewFastScrollBar { public void setWidth(int); public int getWidth(); public void setThumbWidth(int); public int getThumbWidth(); public void setTrackAlpha(int); public int getTrackAlpha(); } Loading src/com/android/launcher3/BaseRecyclerView.java +23 −17 Original line number Diff line number Diff line Loading @@ -92,7 +92,13 @@ public abstract class BaseRecyclerView extends RecyclerView // TODO(winsonc): If we want to animate the section heads while scrolling, we can // initiate that here if the recycler view scroll state is not // RecyclerView.SCROLL_STATE_IDLE. onUpdateScrollbar(dy); } } public void reset() { mScrollbar.reattachThumbToScroll(); } @Override Loading Loading @@ -143,7 +149,7 @@ public abstract class BaseRecyclerView extends RecyclerView mScrollbar.handleTouchEvent(ev, mDownX, mDownY, mLastY); break; } return mScrollbar.isDragging(); return mScrollbar.isDraggingThumb(); } public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { Loading Loading @@ -185,12 +191,10 @@ public abstract class BaseRecyclerView extends RecyclerView * AvailableScrollHeight = Total height of the all items - last page height * * This assumes that all rows are the same height. * * @param yOffset the offset from the top of the recycler view to start tracking. */ protected int getAvailableScrollHeight(int rowCount, int rowHeight, int yOffset) { protected int getAvailableScrollHeight(int rowCount, int rowHeight) { int visibleHeight = getHeight() - mBackgroundPadding.top - mBackgroundPadding.bottom; int scrollHeight = getPaddingTop() + yOffset + rowCount * rowHeight + getPaddingBottom(); int scrollHeight = getPaddingTop() + rowCount * rowHeight + getPaddingBottom(); int availableScrollHeight = scrollHeight - visibleHeight; return availableScrollHeight; } Loading Loading @@ -222,7 +226,7 @@ public abstract class BaseRecyclerView extends RecyclerView @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); onUpdateScrollbar(); onUpdateScrollbar(0); mScrollbar.draw(canvas); } Loading @@ -234,24 +238,21 @@ public abstract class BaseRecyclerView extends RecyclerView * @param scrollPosState the current scroll position * @param rowCount the number of rows, used to calculate the total scroll height (assumes that * all rows are the same height) * @param yOffset the offset to start tracking in the recycler view (only used for all apps) */ protected void synchronizeScrollBarThumbOffsetToViewScroll(ScrollPositionState scrollPosState, int rowCount, int yOffset) { int availableScrollHeight = getAvailableScrollHeight(rowCount, scrollPosState.rowHeight, yOffset); int availableScrollBarHeight = getAvailableScrollBarHeight(); int rowCount) { // Only show the scrollbar if there is height to be scrolled int availableScrollBarHeight = getAvailableScrollBarHeight(); int availableScrollHeight = getAvailableScrollHeight(rowCount, scrollPosState.rowHeight); if (availableScrollHeight <= 0) { mScrollbar.setScrollbarThumbOffset(-1, -1); mScrollbar.setThumbOffset(-1, -1); return; } // Calculate the current scroll position, the scrollY of the recycler view accounts for the // view padding, while the scrollBarY is drawn right up to the background padding (ignoring // padding) int scrollY = getPaddingTop() + yOffset + int scrollY = getPaddingTop() + (scrollPosState.rowIndex * scrollPosState.rowHeight) - scrollPosState.rowTopOffset; int scrollBarY = mBackgroundPadding.top + (int) (((float) scrollY / availableScrollHeight) * availableScrollBarHeight); Loading @@ -261,9 +262,9 @@ public abstract class BaseRecyclerView extends RecyclerView if (Utilities.isRtl(getResources())) { scrollBarX = mBackgroundPadding.left; } else { scrollBarX = getWidth() - mBackgroundPadding.right - mScrollbar.getWidth(); scrollBarX = getWidth() - mBackgroundPadding.right - mScrollbar.getThumbWidth(); } mScrollbar.setScrollbarThumbOffset(scrollBarX, scrollBarY); mScrollbar.setThumbOffset(scrollBarX, scrollBarY); } /** Loading @@ -276,10 +277,15 @@ public abstract class BaseRecyclerView extends RecyclerView * Updates the bounds for the scrollbar. * <p>Override in each subclass of this base class. */ public abstract void onUpdateScrollbar(); public abstract void onUpdateScrollbar(int dy); /** * <p>Override in each subclass of this base class. */ public void onFastScrollCompleted() {} /** * Returns information about the item that the recycler view is currently scrolled to. */ protected abstract void getCurScrollState(ScrollPositionState stateOut); } No newline at end of file src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java +33 −5 Original line number Diff line number Diff line Loading @@ -56,9 +56,12 @@ public class BaseRecyclerViewFastScrollBar { private int mThumbMaxWidth; @Thunk int mThumbWidth; @Thunk int mThumbHeight; private float mLastTouchY; // The inset is the buffer around which a point will still register as a click on the scrollbar private int mTouchInset; private boolean mIsDragging; private boolean mIsThumbDetached; private boolean mCanThumbDetach; // This is the offset from the top of the scrollbar when the user first starts touching. To // prevent jumping, this offset is applied as the user scrolls. Loading @@ -84,7 +87,15 @@ public class BaseRecyclerViewFastScrollBar { mTouchInset = res.getDimensionPixelSize(R.dimen.container_fastscroll_thumb_touch_inset); } public void setScrollbarThumbOffset(int x, int y) { public void setDetachThumbOnFastScroll() { mCanThumbDetach = true; } public void reattachThumbToScroll() { mIsThumbDetached = false; } public void setThumbOffset(int x, int y) { if (mThumbOffset.x == x && mThumbOffset.y == y) { return; } Loading @@ -95,8 +106,12 @@ public class BaseRecyclerViewFastScrollBar { mRv.invalidate(mInvalidateRect); } public Point getThumbOffset() { return mThumbOffset; } // Setter/getter for the search bar width for animations public void setWidth(int width) { public void setThumbWidth(int width) { mInvalidateRect.set(mThumbOffset.x, 0, mThumbOffset.x + mThumbWidth, mRv.getHeight()); mThumbWidth = width; mInvalidateRect.union(new Rect(mThumbOffset.x, 0, mThumbOffset.x + mThumbWidth, Loading @@ -104,7 +119,7 @@ public class BaseRecyclerViewFastScrollBar { mRv.invalidate(mInvalidateRect); } public int getWidth() { public int getThumbWidth() { return mThumbWidth; } Loading @@ -127,10 +142,18 @@ public class BaseRecyclerViewFastScrollBar { return mThumbMaxWidth; } public boolean isDragging() { public float getLastTouchY() { return mLastTouchY; } public boolean isDraggingThumb() { return mIsDragging; } public boolean isThumbDetached() { return mIsThumbDetached; } /** * Handles the touch event and determines whether to show the fast scroller (or updates it if * it is already showing). Loading @@ -152,6 +175,9 @@ public class BaseRecyclerViewFastScrollBar { Math.abs(y - downY) > config.getScaledTouchSlop()) { mRv.getParent().requestDisallowInterceptTouchEvent(true); mIsDragging = true; if (mCanThumbDetach) { mIsThumbDetached = true; } mTouchOffset += (lastY - downY); mPopup.animateVisibility(true); animateScrollbar(true); Loading @@ -166,11 +192,13 @@ public class BaseRecyclerViewFastScrollBar { mPopup.setSectionName(sectionName); mPopup.animateVisibility(!sectionName.isEmpty()); mRv.invalidate(mPopup.updateFastScrollerBounds(mRv, lastY)); mLastTouchY = boundedY; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mTouchOffset = 0; mLastTouchY = 0; if (mIsDragging) { mIsDragging = false; mPopup.animateVisibility(false); Loading Loading @@ -205,7 +233,7 @@ public class BaseRecyclerViewFastScrollBar { } ObjectAnimator trackAlphaAnim = ObjectAnimator.ofInt(this, "trackAlpha", isScrolling ? MAX_TRACK_ALPHA : 0); ObjectAnimator thumbWidthAnim = ObjectAnimator.ofInt(this, "width", ObjectAnimator thumbWidthAnim = ObjectAnimator.ofInt(this, "thumbWidth", isScrolling ? mThumbMaxWidth : mThumbMinWidth); ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), mThumbPaint.getColor(), isScrolling ? mThumbActiveColor : mThumbInactiveColor); Loading src/com/android/launcher3/allapps/AllAppsContainerView.java +2 −1 Original line number Diff line number Diff line Loading @@ -555,8 +555,9 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc @Override public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) { if (toWorkspace) { // Reset the search bar after transitioning home // Reset the search bar and base recycler view after transitioning home mSearchBarController.reset(); mAppsRecyclerView.reset(); } } Loading src/com/android/launcher3/allapps/AllAppsRecyclerView.java +59 −9 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView public AllAppsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr); mScrollbar.setDetachThumbOnFastScroll(); } /** Loading Loading @@ -168,8 +169,8 @@ public class AllAppsRecyclerView extends BaseRecyclerView } // Map the touch position back to the scroll of the recycler view getCurScrollState(mScrollPosState, mApps.getAdapterItems()); int availableScrollHeight = getAvailableScrollHeight(rowCount, mScrollPosState.rowHeight, 0); getCurScrollState(mScrollPosState); int availableScrollHeight = getAvailableScrollHeight(rowCount, mScrollPosState.rowHeight); LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager(); if (mFastScrollMode == FAST_SCROLL_MODE_FREE_SCROLL) { layoutManager.scrollToPositionWithOffset(0, (int) -(availableScrollHeight * touchFraction)); Loading Loading @@ -216,24 +217,73 @@ public class AllAppsRecyclerView extends BaseRecyclerView * Updates the bounds for the scrollbar. */ @Override public void onUpdateScrollbar() { public void onUpdateScrollbar(int dy) { List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems(); // Skip early if there are no items or we haven't been measured if (items.isEmpty() || mNumAppsPerRow == 0) { mScrollbar.setScrollbarThumbOffset(-1, -1); mScrollbar.setThumbOffset(-1, -1); return; } // Find the index and height of the first visible row (all rows have the same height) int rowCount = mApps.getNumAppRows(); getCurScrollState(mScrollPosState, items); getCurScrollState(mScrollPosState); if (mScrollPosState.rowIndex < 0) { mScrollbar.setScrollbarThumbOffset(-1, -1); mScrollbar.setThumbOffset(-1, -1); return; } synchronizeScrollBarThumbOffsetToViewScroll(mScrollPosState, rowCount, 0); // Only show the scrollbar if there is height to be scrolled int availableScrollBarHeight = getAvailableScrollBarHeight(); int availableScrollHeight = getAvailableScrollHeight(mApps.getNumAppRows(), mScrollPosState.rowHeight); if (availableScrollHeight <= 0) { mScrollbar.setThumbOffset(-1, -1); return; } // Calculate the current scroll position, the scrollY of the recycler view accounts for the // view padding, while the scrollBarY is drawn right up to the background padding (ignoring // padding) int scrollY = getPaddingTop() + (mScrollPosState.rowIndex * mScrollPosState.rowHeight) - mScrollPosState.rowTopOffset; int scrollBarY = mBackgroundPadding.top + (int) (((float) scrollY / availableScrollHeight) * availableScrollBarHeight); if (mScrollbar.isThumbDetached()) { int scrollBarX; if (Utilities.isRtl(getResources())) { scrollBarX = mBackgroundPadding.left; } else { scrollBarX = getWidth() - mBackgroundPadding.right - mScrollbar.getThumbWidth(); } if (mScrollbar.isDraggingThumb()) { // If the thumb is detached, then just update the thumb to the current // touch position mScrollbar.setThumbOffset(scrollBarX, (int) mScrollbar.getLastTouchY()); } else { int thumbScrollY = mScrollbar.getThumbOffset().y; int diffScrollY = scrollBarY - thumbScrollY; if (diffScrollY * dy > 0f) { // User is scrolling in the same direction the thumb needs to catch up to the // current scroll position. thumbScrollY += dy < 0 ? Math.max(dy, diffScrollY) : Math.min(dy, diffScrollY); thumbScrollY = Math.max(0, Math.min(availableScrollBarHeight, thumbScrollY)); mScrollbar.setThumbOffset(scrollBarX, thumbScrollY); if (scrollBarY == thumbScrollY) { mScrollbar.reattachThumbToScroll(); } } else { // User is scrolling in an opposite direction to the direction that the thumb // needs to catch up to the scroll position. Do nothing except for updating // the scroll bar x to match the thumb width. mScrollbar.setThumbOffset(scrollBarX, thumbScrollY); } } } else { synchronizeScrollBarThumbOffsetToViewScroll(mScrollPosState, rowCount); } } /** Loading Loading @@ -285,13 +335,13 @@ public class AllAppsRecyclerView extends BaseRecyclerView /** * Returns the current scroll state of the apps rows. */ private void getCurScrollState(ScrollPositionState stateOut, List<AlphabeticalAppsList.AdapterItem> items) { protected void getCurScrollState(ScrollPositionState stateOut) { stateOut.rowIndex = -1; stateOut.rowTopOffset = -1; stateOut.rowHeight = -1; // Return early if there are no items or we haven't been measured List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems(); if (items.isEmpty() || mNumAppsPerRow == 0) { return; } Loading Loading
proguard.flags +2 −2 Original line number Diff line number Diff line Loading @@ -3,8 +3,8 @@ } -keep class com.android.launcher3.BaseRecyclerViewFastScrollBar { public void setWidth(int); public int getWidth(); public void setThumbWidth(int); public int getThumbWidth(); public void setTrackAlpha(int); public int getTrackAlpha(); } Loading
src/com/android/launcher3/BaseRecyclerView.java +23 −17 Original line number Diff line number Diff line Loading @@ -92,7 +92,13 @@ public abstract class BaseRecyclerView extends RecyclerView // TODO(winsonc): If we want to animate the section heads while scrolling, we can // initiate that here if the recycler view scroll state is not // RecyclerView.SCROLL_STATE_IDLE. onUpdateScrollbar(dy); } } public void reset() { mScrollbar.reattachThumbToScroll(); } @Override Loading Loading @@ -143,7 +149,7 @@ public abstract class BaseRecyclerView extends RecyclerView mScrollbar.handleTouchEvent(ev, mDownX, mDownY, mLastY); break; } return mScrollbar.isDragging(); return mScrollbar.isDraggingThumb(); } public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { Loading Loading @@ -185,12 +191,10 @@ public abstract class BaseRecyclerView extends RecyclerView * AvailableScrollHeight = Total height of the all items - last page height * * This assumes that all rows are the same height. * * @param yOffset the offset from the top of the recycler view to start tracking. */ protected int getAvailableScrollHeight(int rowCount, int rowHeight, int yOffset) { protected int getAvailableScrollHeight(int rowCount, int rowHeight) { int visibleHeight = getHeight() - mBackgroundPadding.top - mBackgroundPadding.bottom; int scrollHeight = getPaddingTop() + yOffset + rowCount * rowHeight + getPaddingBottom(); int scrollHeight = getPaddingTop() + rowCount * rowHeight + getPaddingBottom(); int availableScrollHeight = scrollHeight - visibleHeight; return availableScrollHeight; } Loading Loading @@ -222,7 +226,7 @@ public abstract class BaseRecyclerView extends RecyclerView @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); onUpdateScrollbar(); onUpdateScrollbar(0); mScrollbar.draw(canvas); } Loading @@ -234,24 +238,21 @@ public abstract class BaseRecyclerView extends RecyclerView * @param scrollPosState the current scroll position * @param rowCount the number of rows, used to calculate the total scroll height (assumes that * all rows are the same height) * @param yOffset the offset to start tracking in the recycler view (only used for all apps) */ protected void synchronizeScrollBarThumbOffsetToViewScroll(ScrollPositionState scrollPosState, int rowCount, int yOffset) { int availableScrollHeight = getAvailableScrollHeight(rowCount, scrollPosState.rowHeight, yOffset); int availableScrollBarHeight = getAvailableScrollBarHeight(); int rowCount) { // Only show the scrollbar if there is height to be scrolled int availableScrollBarHeight = getAvailableScrollBarHeight(); int availableScrollHeight = getAvailableScrollHeight(rowCount, scrollPosState.rowHeight); if (availableScrollHeight <= 0) { mScrollbar.setScrollbarThumbOffset(-1, -1); mScrollbar.setThumbOffset(-1, -1); return; } // Calculate the current scroll position, the scrollY of the recycler view accounts for the // view padding, while the scrollBarY is drawn right up to the background padding (ignoring // padding) int scrollY = getPaddingTop() + yOffset + int scrollY = getPaddingTop() + (scrollPosState.rowIndex * scrollPosState.rowHeight) - scrollPosState.rowTopOffset; int scrollBarY = mBackgroundPadding.top + (int) (((float) scrollY / availableScrollHeight) * availableScrollBarHeight); Loading @@ -261,9 +262,9 @@ public abstract class BaseRecyclerView extends RecyclerView if (Utilities.isRtl(getResources())) { scrollBarX = mBackgroundPadding.left; } else { scrollBarX = getWidth() - mBackgroundPadding.right - mScrollbar.getWidth(); scrollBarX = getWidth() - mBackgroundPadding.right - mScrollbar.getThumbWidth(); } mScrollbar.setScrollbarThumbOffset(scrollBarX, scrollBarY); mScrollbar.setThumbOffset(scrollBarX, scrollBarY); } /** Loading @@ -276,10 +277,15 @@ public abstract class BaseRecyclerView extends RecyclerView * Updates the bounds for the scrollbar. * <p>Override in each subclass of this base class. */ public abstract void onUpdateScrollbar(); public abstract void onUpdateScrollbar(int dy); /** * <p>Override in each subclass of this base class. */ public void onFastScrollCompleted() {} /** * Returns information about the item that the recycler view is currently scrolled to. */ protected abstract void getCurScrollState(ScrollPositionState stateOut); } No newline at end of file
src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java +33 −5 Original line number Diff line number Diff line Loading @@ -56,9 +56,12 @@ public class BaseRecyclerViewFastScrollBar { private int mThumbMaxWidth; @Thunk int mThumbWidth; @Thunk int mThumbHeight; private float mLastTouchY; // The inset is the buffer around which a point will still register as a click on the scrollbar private int mTouchInset; private boolean mIsDragging; private boolean mIsThumbDetached; private boolean mCanThumbDetach; // This is the offset from the top of the scrollbar when the user first starts touching. To // prevent jumping, this offset is applied as the user scrolls. Loading @@ -84,7 +87,15 @@ public class BaseRecyclerViewFastScrollBar { mTouchInset = res.getDimensionPixelSize(R.dimen.container_fastscroll_thumb_touch_inset); } public void setScrollbarThumbOffset(int x, int y) { public void setDetachThumbOnFastScroll() { mCanThumbDetach = true; } public void reattachThumbToScroll() { mIsThumbDetached = false; } public void setThumbOffset(int x, int y) { if (mThumbOffset.x == x && mThumbOffset.y == y) { return; } Loading @@ -95,8 +106,12 @@ public class BaseRecyclerViewFastScrollBar { mRv.invalidate(mInvalidateRect); } public Point getThumbOffset() { return mThumbOffset; } // Setter/getter for the search bar width for animations public void setWidth(int width) { public void setThumbWidth(int width) { mInvalidateRect.set(mThumbOffset.x, 0, mThumbOffset.x + mThumbWidth, mRv.getHeight()); mThumbWidth = width; mInvalidateRect.union(new Rect(mThumbOffset.x, 0, mThumbOffset.x + mThumbWidth, Loading @@ -104,7 +119,7 @@ public class BaseRecyclerViewFastScrollBar { mRv.invalidate(mInvalidateRect); } public int getWidth() { public int getThumbWidth() { return mThumbWidth; } Loading @@ -127,10 +142,18 @@ public class BaseRecyclerViewFastScrollBar { return mThumbMaxWidth; } public boolean isDragging() { public float getLastTouchY() { return mLastTouchY; } public boolean isDraggingThumb() { return mIsDragging; } public boolean isThumbDetached() { return mIsThumbDetached; } /** * Handles the touch event and determines whether to show the fast scroller (or updates it if * it is already showing). Loading @@ -152,6 +175,9 @@ public class BaseRecyclerViewFastScrollBar { Math.abs(y - downY) > config.getScaledTouchSlop()) { mRv.getParent().requestDisallowInterceptTouchEvent(true); mIsDragging = true; if (mCanThumbDetach) { mIsThumbDetached = true; } mTouchOffset += (lastY - downY); mPopup.animateVisibility(true); animateScrollbar(true); Loading @@ -166,11 +192,13 @@ public class BaseRecyclerViewFastScrollBar { mPopup.setSectionName(sectionName); mPopup.animateVisibility(!sectionName.isEmpty()); mRv.invalidate(mPopup.updateFastScrollerBounds(mRv, lastY)); mLastTouchY = boundedY; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mTouchOffset = 0; mLastTouchY = 0; if (mIsDragging) { mIsDragging = false; mPopup.animateVisibility(false); Loading Loading @@ -205,7 +233,7 @@ public class BaseRecyclerViewFastScrollBar { } ObjectAnimator trackAlphaAnim = ObjectAnimator.ofInt(this, "trackAlpha", isScrolling ? MAX_TRACK_ALPHA : 0); ObjectAnimator thumbWidthAnim = ObjectAnimator.ofInt(this, "width", ObjectAnimator thumbWidthAnim = ObjectAnimator.ofInt(this, "thumbWidth", isScrolling ? mThumbMaxWidth : mThumbMinWidth); ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), mThumbPaint.getColor(), isScrolling ? mThumbActiveColor : mThumbInactiveColor); Loading
src/com/android/launcher3/allapps/AllAppsContainerView.java +2 −1 Original line number Diff line number Diff line Loading @@ -555,8 +555,9 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc @Override public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) { if (toWorkspace) { // Reset the search bar after transitioning home // Reset the search bar and base recycler view after transitioning home mSearchBarController.reset(); mAppsRecyclerView.reset(); } } Loading
src/com/android/launcher3/allapps/AllAppsRecyclerView.java +59 −9 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView public AllAppsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr); mScrollbar.setDetachThumbOnFastScroll(); } /** Loading Loading @@ -168,8 +169,8 @@ public class AllAppsRecyclerView extends BaseRecyclerView } // Map the touch position back to the scroll of the recycler view getCurScrollState(mScrollPosState, mApps.getAdapterItems()); int availableScrollHeight = getAvailableScrollHeight(rowCount, mScrollPosState.rowHeight, 0); getCurScrollState(mScrollPosState); int availableScrollHeight = getAvailableScrollHeight(rowCount, mScrollPosState.rowHeight); LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager(); if (mFastScrollMode == FAST_SCROLL_MODE_FREE_SCROLL) { layoutManager.scrollToPositionWithOffset(0, (int) -(availableScrollHeight * touchFraction)); Loading Loading @@ -216,24 +217,73 @@ public class AllAppsRecyclerView extends BaseRecyclerView * Updates the bounds for the scrollbar. */ @Override public void onUpdateScrollbar() { public void onUpdateScrollbar(int dy) { List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems(); // Skip early if there are no items or we haven't been measured if (items.isEmpty() || mNumAppsPerRow == 0) { mScrollbar.setScrollbarThumbOffset(-1, -1); mScrollbar.setThumbOffset(-1, -1); return; } // Find the index and height of the first visible row (all rows have the same height) int rowCount = mApps.getNumAppRows(); getCurScrollState(mScrollPosState, items); getCurScrollState(mScrollPosState); if (mScrollPosState.rowIndex < 0) { mScrollbar.setScrollbarThumbOffset(-1, -1); mScrollbar.setThumbOffset(-1, -1); return; } synchronizeScrollBarThumbOffsetToViewScroll(mScrollPosState, rowCount, 0); // Only show the scrollbar if there is height to be scrolled int availableScrollBarHeight = getAvailableScrollBarHeight(); int availableScrollHeight = getAvailableScrollHeight(mApps.getNumAppRows(), mScrollPosState.rowHeight); if (availableScrollHeight <= 0) { mScrollbar.setThumbOffset(-1, -1); return; } // Calculate the current scroll position, the scrollY of the recycler view accounts for the // view padding, while the scrollBarY is drawn right up to the background padding (ignoring // padding) int scrollY = getPaddingTop() + (mScrollPosState.rowIndex * mScrollPosState.rowHeight) - mScrollPosState.rowTopOffset; int scrollBarY = mBackgroundPadding.top + (int) (((float) scrollY / availableScrollHeight) * availableScrollBarHeight); if (mScrollbar.isThumbDetached()) { int scrollBarX; if (Utilities.isRtl(getResources())) { scrollBarX = mBackgroundPadding.left; } else { scrollBarX = getWidth() - mBackgroundPadding.right - mScrollbar.getThumbWidth(); } if (mScrollbar.isDraggingThumb()) { // If the thumb is detached, then just update the thumb to the current // touch position mScrollbar.setThumbOffset(scrollBarX, (int) mScrollbar.getLastTouchY()); } else { int thumbScrollY = mScrollbar.getThumbOffset().y; int diffScrollY = scrollBarY - thumbScrollY; if (diffScrollY * dy > 0f) { // User is scrolling in the same direction the thumb needs to catch up to the // current scroll position. thumbScrollY += dy < 0 ? Math.max(dy, diffScrollY) : Math.min(dy, diffScrollY); thumbScrollY = Math.max(0, Math.min(availableScrollBarHeight, thumbScrollY)); mScrollbar.setThumbOffset(scrollBarX, thumbScrollY); if (scrollBarY == thumbScrollY) { mScrollbar.reattachThumbToScroll(); } } else { // User is scrolling in an opposite direction to the direction that the thumb // needs to catch up to the scroll position. Do nothing except for updating // the scroll bar x to match the thumb width. mScrollbar.setThumbOffset(scrollBarX, thumbScrollY); } } } else { synchronizeScrollBarThumbOffsetToViewScroll(mScrollPosState, rowCount); } } /** Loading Loading @@ -285,13 +335,13 @@ public class AllAppsRecyclerView extends BaseRecyclerView /** * Returns the current scroll state of the apps rows. */ private void getCurScrollState(ScrollPositionState stateOut, List<AlphabeticalAppsList.AdapterItem> items) { protected void getCurScrollState(ScrollPositionState stateOut) { stateOut.rowIndex = -1; stateOut.rowTopOffset = -1; stateOut.rowHeight = -1; // Return early if there are no items or we haven't been measured List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems(); if (items.isEmpty() || mNumAppsPerRow == 0) { return; } Loading