Add overscroll to the top of All Apps.
* Overscroll at the top of all apps will occur when the user scrolls up, hits the top, and continues to scroll up. * Fixed bug where All Apps jumps when the user enters overscroll from a scroll that doesn't start at the bottom. * Fix bug where AllAppsRecyclerView stays translated even after the user has finished dragging. Bug: 62628421 Change-Id: Ia1d230a7cc07a7cf8c1a7c5211a025034ae5f6df
This commit is contained in:
parent
35005ef213
commit
2b35905ea7
|
@ -410,22 +410,19 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
|
|||
|
||||
@Override
|
||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||
if (mScrollState == RecyclerView.SCROLL_STATE_DRAGGING
|
||||
|| (dx == 0 && dy == 0)) {
|
||||
if (mScrollState == RecyclerView.SCROLL_STATE_DRAGGING || (dx == 0 && dy == 0)) {
|
||||
if (mSpringAnimationHandler.isRunning()){
|
||||
mSpringAnimationHandler.skipToEnd();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int first = mLayoutManager.findFirstVisibleItemPosition();
|
||||
int last = mLayoutManager.findLastVisibleItemPosition();
|
||||
|
||||
// We only show the spring animation when at the top or bottom, so we wait until the
|
||||
// first or last row is visible to ensure that all animations run in sync.
|
||||
boolean scrollUp = dy < 0;
|
||||
if ((first == 0 && scrollUp) || (last == mAdapter.getItemCount() - 1 && dy > 0)) {
|
||||
mSpringAnimationHandler.animateToFinalPosition(0, scrollUp ? 1 : -1);
|
||||
// We only start the spring animation when we fling and hit the top/bottom, to ensure
|
||||
// that all of the animations start at the same time.
|
||||
if (dy < 0 && !mAppsRecyclerView.canScrollVertically(-1)) {
|
||||
mSpringAnimationHandler.animateToFinalPosition(0, 1);
|
||||
} else if (dy > 0 && !mAppsRecyclerView.canScrollVertically(1)) {
|
||||
mSpringAnimationHandler.animateToFinalPosition(0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -96,8 +96,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
|
|||
mOverScrollHelper = new OverScrollHelper();
|
||||
mPullDetector = new VerticalPullDetector(getContext());
|
||||
mPullDetector.setListener(mOverScrollHelper);
|
||||
mPullDetector.setDetectableScrollConditions(VerticalPullDetector.DIRECTION_UP
|
||||
| VerticalPullDetector.DIRECTION_DOWN, true);
|
||||
mPullDetector.setDetectableScrollConditions(VerticalPullDetector.DIRECTION_BOTH, true);
|
||||
}
|
||||
|
||||
public void setSpringAnimationHandler(SpringAnimationHandler springAnimationHandler) {
|
||||
|
@ -487,28 +486,53 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
|
|||
|
||||
private boolean mIsInOverScroll;
|
||||
|
||||
// We use this value to calculate the actual amount the user has overscrolled.
|
||||
private float mFirstDisplacement = 0;
|
||||
|
||||
private boolean mAlreadyScrollingUp;
|
||||
private int mFirstScrollYOnScrollUp;
|
||||
|
||||
@Override
|
||||
public void onDragStart(boolean start) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDrag(float displacement, float velocity) {
|
||||
// We are in overscroll iff we are trying to drag further down when we're already at
|
||||
// the bottom of All Apps.
|
||||
mIsInOverScroll = !canScrollVertically(1) && displacement < 0
|
||||
&& !mScrollbar.isDraggingThumb();
|
||||
boolean isScrollingUp = displacement > 0;
|
||||
if (isScrollingUp) {
|
||||
if (!mAlreadyScrollingUp) {
|
||||
mFirstScrollYOnScrollUp = getCurrentScrollY();
|
||||
mAlreadyScrollingUp = true;
|
||||
}
|
||||
} else {
|
||||
mAlreadyScrollingUp = false;
|
||||
}
|
||||
|
||||
// Only enter overscroll if the user is interacting with the RecyclerView directly
|
||||
// and if one of the following criteria are met:
|
||||
// - User scrolls down when they're already at the bottom.
|
||||
// - User starts scrolling up, hits the top, and continues scrolling up.
|
||||
mIsInOverScroll = !mScrollbar.isDraggingThumb() &&
|
||||
((!canScrollVertically(1) && displacement < 0) ||
|
||||
(!canScrollVertically(-1) && isScrollingUp && mFirstScrollYOnScrollUp != 0));
|
||||
|
||||
if (mIsInOverScroll) {
|
||||
displacement = getDampedOverScroll(displacement);
|
||||
setContentTranslationY(displacement);
|
||||
if (Float.compare(mFirstDisplacement, 0) == 0) {
|
||||
// Because users can scroll before entering overscroll, we need to
|
||||
// subtract the amount where the user was not in overscroll.
|
||||
mFirstDisplacement = displacement;
|
||||
}
|
||||
float overscrollY = displacement - mFirstDisplacement;
|
||||
setContentTranslationY(getDampedOverScroll(overscrollY));
|
||||
}
|
||||
|
||||
return mIsInOverScroll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDragEnd(float velocity, boolean fling) {
|
||||
float y = getContentTranslationY();
|
||||
if (mIsInOverScroll && Float.compare(y, 0) != 0) {
|
||||
if (Float.compare(y, 0) != 0) {
|
||||
if (FeatureFlags.LAUNCHER3_PHYSICS) {
|
||||
// We calculate our own velocity to give the springs the desired effect.
|
||||
velocity = y / getDampedOverScroll(getHeight()) * MAX_RELEASE_VELOCITY;
|
||||
|
@ -523,6 +547,9 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
|
|||
.start();
|
||||
}
|
||||
mIsInOverScroll = false;
|
||||
mFirstDisplacement = 0;
|
||||
mFirstScrollYOnScrollUp = 0;
|
||||
mAlreadyScrollingUp = false;
|
||||
}
|
||||
|
||||
public boolean isInOverScroll() {
|
||||
|
|
Loading…
Reference in New Issue