Adding dampened snap back overscroll to Workspace and AppsCustomizePagedView
issue 15475254 Change-Id: I5eb9fc480167faf4be16bd17bf18e2d103f40f47
This commit is contained in:
@@ -190,16 +190,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
|
||||
private int mNumWidgetPages;
|
||||
private Rect mAllAppsPadding = new Rect();
|
||||
|
||||
// Relating to the scroll and overscroll effects
|
||||
Workspace.ZInterpolator mZInterpolator = new Workspace.ZInterpolator(0.5f);
|
||||
private static float CAMERA_DISTANCE = 6500;
|
||||
private static float TRANSITION_SCALE_FACTOR = 0.74f;
|
||||
private static float TRANSITION_PIVOT = 0.65f;
|
||||
private static float TRANSITION_MAX_ROTATION = 22;
|
||||
private static final boolean PERFORM_OVERSCROLL_ROTATION = false;
|
||||
private AccelerateInterpolator mAlphaInterpolator = new AccelerateInterpolator(0.9f);
|
||||
private DecelerateInterpolator mLeftScreenAlphaInterpolator = new DecelerateInterpolator(4);
|
||||
|
||||
// Previews & outlines
|
||||
ArrayList<AppsCustomizeAsyncTask> mRunningTasks;
|
||||
private static final int sPageSleepDelay = 200;
|
||||
@@ -1365,73 +1355,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
|
||||
// In apps customize, we have a scrolling effect which emulates pulling cards off of a stack.
|
||||
@Override
|
||||
protected void screenScrolled(int screenCenter) {
|
||||
final boolean isRtl = isLayoutRtl();
|
||||
super.screenScrolled(screenCenter);
|
||||
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View v = getPageAt(i);
|
||||
if (v != null) {
|
||||
float scrollProgress = getScrollProgress(screenCenter, v, i);
|
||||
|
||||
float interpolatedProgress;
|
||||
float translationX;
|
||||
float maxScrollProgress = Math.max(0, scrollProgress);
|
||||
float minScrollProgress = Math.min(0, scrollProgress);
|
||||
|
||||
if (isRtl) {
|
||||
translationX = maxScrollProgress * v.getMeasuredWidth();
|
||||
interpolatedProgress = mZInterpolator.getInterpolation(Math.abs(maxScrollProgress));
|
||||
} else {
|
||||
translationX = minScrollProgress * v.getMeasuredWidth();
|
||||
interpolatedProgress = mZInterpolator.getInterpolation(Math.abs(minScrollProgress));
|
||||
}
|
||||
float scale = (1 - interpolatedProgress) +
|
||||
interpolatedProgress * TRANSITION_SCALE_FACTOR;
|
||||
|
||||
float alpha;
|
||||
if (isRtl && (scrollProgress > 0)) {
|
||||
alpha = mAlphaInterpolator.getInterpolation(1 - Math.abs(maxScrollProgress));
|
||||
} else if (!isRtl && (scrollProgress < 0)) {
|
||||
alpha = mAlphaInterpolator.getInterpolation(1 - Math.abs(scrollProgress));
|
||||
} else {
|
||||
// On large screens we need to fade the page as it nears its leftmost position
|
||||
alpha = mLeftScreenAlphaInterpolator.getInterpolation(1 - scrollProgress);
|
||||
}
|
||||
|
||||
v.setCameraDistance(mDensity * CAMERA_DISTANCE);
|
||||
int pageWidth = v.getMeasuredWidth();
|
||||
int pageHeight = v.getMeasuredHeight();
|
||||
|
||||
if (PERFORM_OVERSCROLL_ROTATION) {
|
||||
float xPivot = isRtl ? 1f - TRANSITION_PIVOT : TRANSITION_PIVOT;
|
||||
boolean isOverscrollingFirstPage = isRtl ? scrollProgress > 0 : scrollProgress < 0;
|
||||
boolean isOverscrollingLastPage = isRtl ? scrollProgress < 0 : scrollProgress > 0;
|
||||
|
||||
if (i == 0 && isOverscrollingFirstPage) {
|
||||
// Overscroll to the left
|
||||
v.setPivotX(xPivot * pageWidth);
|
||||
v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
|
||||
scale = 1.0f;
|
||||
alpha = 1.0f;
|
||||
// On the first page, we don't want the page to have any lateral motion
|
||||
translationX = 0;
|
||||
} else if (i == getChildCount() - 1 && isOverscrollingLastPage) {
|
||||
// Overscroll to the right
|
||||
v.setPivotX((1 - xPivot) * pageWidth);
|
||||
v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
|
||||
scale = 1.0f;
|
||||
alpha = 1.0f;
|
||||
// On the last page, we don't want the page to have any lateral motion.
|
||||
translationX = 0;
|
||||
} else {
|
||||
v.setPivotY(pageHeight / 2.0f);
|
||||
v.setPivotX(pageWidth / 2.0f);
|
||||
v.setRotationY(0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enableHwLayersOnVisiblePages();
|
||||
}
|
||||
|
||||
@@ -1476,7 +1400,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
|
||||
}
|
||||
|
||||
protected void overScroll(float amount) {
|
||||
acceleratedOverScroll(amount);
|
||||
dampedOverScroll(amount);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -71,7 +71,6 @@ public class CellLayout extends ViewGroup {
|
||||
private int mWidthGap;
|
||||
private int mHeightGap;
|
||||
private int mMaxGap;
|
||||
private boolean mScrollingTransformsDirty = false;
|
||||
private boolean mDropPending = false;
|
||||
|
||||
// These are temporary variables to prevent having to allocate a new object just to
|
||||
@@ -388,23 +387,6 @@ public class CellLayout extends ViewGroup {
|
||||
return mIsDragOverlapping;
|
||||
}
|
||||
|
||||
protected void setOverscrollTransformsDirty(boolean dirty) {
|
||||
mScrollingTransformsDirty = dirty;
|
||||
}
|
||||
|
||||
protected void resetOverscrollTransforms() {
|
||||
if (mScrollingTransformsDirty) {
|
||||
setOverscrollTransformsDirty(false);
|
||||
setTranslationX(0);
|
||||
setRotationY(0);
|
||||
// It doesn't matter if we pass true or false here, the important thing is that we
|
||||
// pass 0, which results in the overscroll drawable not being drawn any more.
|
||||
setOverScrollAmount(0, false);
|
||||
setPivotX(getMeasuredWidth() / 2);
|
||||
setPivotY(getMeasuredHeight() / 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
// When we're large, we are either drawn in a "hover" state (ie when dragging an item to
|
||||
|
||||
@@ -74,11 +74,12 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
private static final int MIN_LENGTH_FOR_FLING = 25;
|
||||
|
||||
protected static final int PAGE_SNAP_ANIMATION_DURATION = 750;
|
||||
protected static final int OVER_SCROLL_PAGE_SNAP_ANIMATION_DURATION = 350;
|
||||
protected static final int SLOW_PAGE_SNAP_ANIMATION_DURATION = 950;
|
||||
protected static final float NANOTIME_DIV = 1000000000.0f;
|
||||
|
||||
private static final float OVERSCROLL_ACCELERATE_FACTOR = 2;
|
||||
private static final float OVERSCROLL_DAMP_FACTOR = 0.14f;
|
||||
private static final float OVERSCROLL_DAMP_FACTOR = 0.07f;
|
||||
|
||||
private static final float RETURN_TO_ORIGINAL_PAGE_THRESHOLD = 0.33f;
|
||||
// The page is moved more than halfway, automatically move to the next page on touch up.
|
||||
@@ -1601,29 +1602,20 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
return f * f * f + 1.0f;
|
||||
}
|
||||
|
||||
protected void acceleratedOverScroll(float amount) {
|
||||
protected float acceleratedOverFactor(float amount) {
|
||||
int screenSize = getViewportWidth();
|
||||
|
||||
// We want to reach the max over scroll effect when the user has
|
||||
// over scrolled half the size of the screen
|
||||
float f = OVERSCROLL_ACCELERATE_FACTOR * (amount / screenSize);
|
||||
|
||||
if (f == 0) return;
|
||||
if (f == 0) return 0;
|
||||
|
||||
// Clamp this factor, f, to -1 < f < 1
|
||||
if (Math.abs(f) >= 1) {
|
||||
f /= Math.abs(f);
|
||||
}
|
||||
|
||||
int overScrollAmount = (int) Math.round(f * screenSize);
|
||||
if (amount < 0) {
|
||||
mOverScrollX = overScrollAmount;
|
||||
super.scrollTo(0, getScrollY());
|
||||
} else {
|
||||
mOverScrollX = mMaxScrollX + overScrollAmount;
|
||||
super.scrollTo(mMaxScrollX, getScrollY());
|
||||
}
|
||||
invalidate();
|
||||
return f;
|
||||
}
|
||||
|
||||
protected void dampedOverScroll(float amount) {
|
||||
@@ -1642,10 +1634,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
int overScrollAmount = (int) Math.round(OVERSCROLL_DAMP_FACTOR * f * screenSize);
|
||||
if (amount < 0) {
|
||||
mOverScrollX = overScrollAmount;
|
||||
super.scrollTo(0, getScrollY());
|
||||
super.scrollTo(mOverScrollX, getScrollY());
|
||||
} else {
|
||||
mOverScrollX = mMaxScrollX + overScrollAmount;
|
||||
super.scrollTo(mMaxScrollX, getScrollY());
|
||||
super.scrollTo(mOverScrollX, getScrollY());
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
@@ -2145,8 +2137,20 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
return minDistanceFromScreenCenterIndex;
|
||||
}
|
||||
|
||||
protected boolean isInOverScroll() {
|
||||
return (mOverScrollX > mMaxScrollX || mOverScrollX < 0);
|
||||
}
|
||||
|
||||
protected int getPageSnapDuration() {
|
||||
if (isInOverScroll()) {
|
||||
return OVER_SCROLL_PAGE_SNAP_ANIMATION_DURATION;
|
||||
}
|
||||
return PAGE_SNAP_ANIMATION_DURATION;
|
||||
|
||||
}
|
||||
|
||||
protected void snapToDestination() {
|
||||
snapToPage(getPageNearestToCenterOfScreen(), PAGE_SNAP_ANIMATION_DURATION);
|
||||
snapToPage(getPageNearestToCenterOfScreen(), getPageSnapDuration());
|
||||
}
|
||||
|
||||
private static class ScrollInterpolator implements Interpolator {
|
||||
@@ -2177,10 +2181,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
int delta = newX - mUnboundedScrollX;
|
||||
int duration = 0;
|
||||
|
||||
if (Math.abs(velocity) < mMinFlingVelocity) {
|
||||
if (Math.abs(velocity) < mMinFlingVelocity || isInOverScroll()) {
|
||||
// If the velocity is low enough, then treat this more as an automatic page advance
|
||||
// as opposed to an apparent physical response to flinging
|
||||
snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
|
||||
snapToPage(whichPage, getPageSnapDuration());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2204,11 +2208,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
}
|
||||
|
||||
protected void snapToPage(int whichPage) {
|
||||
snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
|
||||
snapToPage(whichPage, getPageSnapDuration());
|
||||
}
|
||||
|
||||
protected void snapToPageImmediately(int whichPage) {
|
||||
snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION, true, null);
|
||||
snapToPage(whichPage, getPageSnapDuration(), true, null);
|
||||
}
|
||||
|
||||
protected void snapToPage(int whichPage, int duration) {
|
||||
|
||||
@@ -215,7 +215,7 @@ public class Workspace extends SmoothPagedView
|
||||
private final Rect mTempRect = new Rect();
|
||||
private final int[] mTempXY = new int[2];
|
||||
private int[] mTempVisiblePagesRange = new int[2];
|
||||
private boolean mOverscrollTransformsSet;
|
||||
private boolean mOverscrollEffectSet;
|
||||
public static final int DRAG_BITMAP_PADDING = 2;
|
||||
private boolean mWorkspaceFadeInAdjacentScreens;
|
||||
|
||||
@@ -281,6 +281,8 @@ public class Workspace extends SmoothPagedView
|
||||
private int mLastChildCount = -1;
|
||||
private float mTransitionProgress;
|
||||
|
||||
float mOverScrollEffect = 0f;
|
||||
|
||||
private Runnable mDeferredAction;
|
||||
private boolean mDeferDropAfterUninstall;
|
||||
private boolean mUninstallSuccessful;
|
||||
@@ -1683,14 +1685,11 @@ public class Workspace extends SmoothPagedView
|
||||
updateStateForCustomContent(screenCenter);
|
||||
enableHwLayersOnVisiblePages();
|
||||
|
||||
boolean shouldOverScroll = (mOverScrollX < 0 && (!hasCustomContent() || isLayoutRtl())) ||
|
||||
(mOverScrollX > mMaxScrollX && (!hasCustomContent() || !isLayoutRtl()));
|
||||
boolean shouldOverScroll = (mOverScrollEffect < 0 && (!hasCustomContent() || isLayoutRtl())) ||
|
||||
(mOverScrollEffect > 0 && (!hasCustomContent() || !isLayoutRtl()));
|
||||
|
||||
if (shouldOverScroll) {
|
||||
int index = 0;
|
||||
float pivotX = 0f;
|
||||
final float leftBiasedPivot = 0.25f;
|
||||
final float rightBiasedPivot = 0.75f;
|
||||
final int lowerIndex = 0;
|
||||
final int upperIndex = getChildCount() - 1;
|
||||
|
||||
@@ -1698,25 +1697,27 @@ public class Workspace extends SmoothPagedView
|
||||
index = (!isRtl && isLeftPage) || (isRtl && !isLeftPage) ? lowerIndex : upperIndex;
|
||||
|
||||
CellLayout cl = (CellLayout) getChildAt(index);
|
||||
float scrollProgress = getScrollProgress(screenCenter, cl, index);
|
||||
cl.setOverScrollAmount(Math.abs(scrollProgress), isLeftPage);
|
||||
float effect = Math.abs(mOverScrollEffect);
|
||||
cl.setOverScrollAmount(Math.abs(effect), isLeftPage);
|
||||
|
||||
if (!mOverscrollTransformsSet) {
|
||||
mOverscrollTransformsSet = true;
|
||||
cl.setOverscrollTransformsDirty(true);
|
||||
}
|
||||
mOverscrollEffectSet = true;
|
||||
} else {
|
||||
if (mOverscrollTransformsSet && getChildCount() > 0) {
|
||||
mOverscrollTransformsSet = false;
|
||||
((CellLayout) getChildAt(0)).resetOverscrollTransforms();
|
||||
((CellLayout) getChildAt(getChildCount() - 1)).resetOverscrollTransforms();
|
||||
if (mOverscrollEffectSet && getChildCount() > 0) {
|
||||
mOverscrollEffectSet = false;
|
||||
((CellLayout) getChildAt(0)).setOverScrollAmount(0, false);
|
||||
((CellLayout) getChildAt(getChildCount() - 1)).setOverScrollAmount(0, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void computeOverScrollEffect(float amount) {
|
||||
mOverScrollEffect = acceleratedOverFactor(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void overScroll(float amount) {
|
||||
acceleratedOverScroll(amount);
|
||||
computeOverScrollEffect(amount);
|
||||
dampedOverScroll(amount);
|
||||
}
|
||||
|
||||
protected void onAttachedToWindow() {
|
||||
|
||||
Reference in New Issue
Block a user