Tweaking fast scroller to follow touch closer.
- Issue: The fast scroller currently does not follow the touch input
because fundamentally, the fixed scrollbar height and the mapping
of the scroll space to the scrollbar space is fundamentally incompatible.
- This CL changes the fast scroller to allow it to detach when the user
fast-scrolls, then re-attaches after the user scrolls the screen and
the current scroll position for the scrollbar picks up the thumb position.
- Since the scroll position and the fast scroller thumb is now detached,
we can change the distribution of the fast scroll letters to make it
independent of the rows for each section and instead uniformly distribute
it along the scrollbar, which allows for more stability.
- There are edge cases where this fails, especially when there are few
apps, which we can investigate further.
Bug: 20035978
Change-Id: I8322f862107e6f330deff692885233706564bffd
diff --git a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
index 2c4184d..29e234d 100644
--- a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
+++ b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
@@ -56,9 +56,12 @@
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.
@@ -84,7 +87,15 @@
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;
}
@@ -95,8 +106,12 @@
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,
@@ -104,7 +119,7 @@
mRv.invalidate(mInvalidateRect);
}
- public int getWidth() {
+ public int getThumbWidth() {
return mThumbWidth;
}
@@ -127,10 +142,18 @@
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).
@@ -152,6 +175,9 @@
Math.abs(y - downY) > config.getScaledTouchSlop()) {
mRv.getParent().requestDisallowInterceptTouchEvent(true);
mIsDragging = true;
+ if (mCanThumbDetach) {
+ mIsThumbDetached = true;
+ }
mTouchOffset += (lastY - downY);
mPopup.animateVisibility(true);
animateScrollbar(true);
@@ -166,11 +192,13 @@
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);
@@ -205,7 +233,7 @@
}
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);