Ensuring that fast scrolling to predictions scrolls list to the top

- Fixes a long standing issue with fast-scrolling to the predicted apps
  not quite scrolling the list to the top of the screen.
- Fixes an issue where we don’t scroll exactly to the fast scroll 
  position due to rounding
- Also fixes a small issue where the thumb would not update when the 
  fast scroll popup was no longer showing, even while dragging.

Bug: 30023608

Change-Id: I6b5080c6aea521ff03dca24317f0405c02725061
This commit is contained in:
Winson
2016-07-12 14:10:50 -07:00
committed by Winson Chung
parent b029e9fd66
commit e8eaa9c94c
5 changed files with 30 additions and 32 deletions
@@ -246,13 +246,18 @@ public abstract class BaseRecyclerView extends RecyclerView
(int) (((float) scrollY / availableScrollHeight) * availableScrollBarHeight);
// Calculate the position and size of the scroll bar
int scrollBarX;
mScrollbar.setThumbOffset(getScrollBarX(), scrollBarY);
}
/**
* @return the x position for the scrollbar thumb
*/
protected int getScrollBarX() {
if (Utilities.isRtl(getResources())) {
scrollBarX = mBackgroundPadding.left;
return mBackgroundPadding.left;
} else {
scrollBarX = getWidth() - mBackgroundPadding.right - mScrollbar.getThumbWidth();
return getWidth() - mBackgroundPadding.right - mScrollbar.getThumbWidth();
}
mScrollbar.setThumbOffset(scrollBarX, scrollBarY);
}
/**
@@ -156,10 +156,6 @@ public class BaseRecyclerViewFastScrollBar {
return mThumbMaxWidth;
}
public float getLastTouchY() {
return mLastTouchY;
}
public boolean isDraggingThumb() {
return mIsDragging;
}
@@ -210,6 +206,7 @@ public class BaseRecyclerViewFastScrollBar {
mPopup.animateVisibility(!sectionName.isEmpty());
mRv.invalidate(mPopup.updateFastScrollerBounds(lastY));
mLastTouchY = boundedY;
setThumbOffset(mRv.getScrollBarX(), (int) mLastTouchY);
}
break;
case MotionEvent.ACTION_UP:
@@ -23,6 +23,7 @@ import com.android.launcher3.FastBitmapDrawable;
import com.android.launcher3.util.Thunk;
import java.util.HashSet;
import java.util.List;
public class AllAppsFastScrollHelper implements AllAppsGridAdapter.BindViewCallback {
@@ -142,13 +143,22 @@ public class AllAppsFastScrollHelper implements AllAppsGridAdapter.BindViewCallb
}
// Calculate the full animation from the current scroll position to the final scroll
// position, and then run the animation for the duration.
// position, and then run the animation for the duration. If we are scrolling to the
// first fast scroll section, then just scroll to the top of the list itself.
List<AlphabeticalAppsList.FastScrollSectionInfo> fastScrollSections =
mApps.getFastScrollerSections();
int newPosition = info.fastScrollToItem.position;
int newScrollY = Math.min(availableScrollHeight, mRv.getCurrentScrollY(newPosition, 0));
int newScrollY = fastScrollSections.size() > 0 && fastScrollSections.get(0) == info
? 0
: Math.min(availableScrollHeight, mRv.getCurrentScrollY(newPosition, 0));
int numFrames = mFastScrollFrames.length;
int deltaY = newScrollY - scrollY;
float ySign = Math.signum(deltaY);
int step = (int) (ySign * Math.ceil((float) Math.abs(deltaY) / numFrames));
for (int i = 0; i < numFrames; i++) {
// TODO(winsonc): We can interpolate this as well.
mFastScrollFrames[i] = (newScrollY - scrollY) / numFrames;
mFastScrollFrames[i] = (int) (ySign * Math.min(Math.abs(step), Math.abs(deltaY)));
deltaY -= step;
}
mFastScrollFrameIndex = 0;
mRv.postOnAnimation(mSmoothSnapNextFrameRunnable);
@@ -377,10 +377,6 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
return isViewType(viewType, VIEW_TYPE_MASK_ICON);
}
public static boolean isPredictionIconViewType(int viewType) {
return isViewType(viewType, VIEW_TYPE_PREDICTION_ICON);
}
public static boolean isViewType(int viewType, int viewTypeMask) {
return (viewType & viewTypeMask) != 0;
}
@@ -325,25 +325,15 @@ public class AllAppsRecyclerView extends BaseRecyclerView
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 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()) {
// 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 scrollBarX = getScrollBarX();
int scrollBarY = mBackgroundPadding.top +
(int) (((float) scrollY / availableScrollHeight) * availableScrollBarHeight);
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) {