diff options
Diffstat (limited to 'src/com')
-rw-r--r-- | src/com/android/launcher2/PagedView.java | 82 | ||||
-rw-r--r-- | src/com/android/launcher2/SmoothPagedView.java | 89 | ||||
-rw-r--r-- | src/com/android/launcher2/Workspace.java | 38 |
3 files changed, 131 insertions, 78 deletions
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java index 264e83907..09133e0a4 100644 --- a/src/com/android/launcher2/PagedView.java +++ b/src/com/android/launcher2/PagedView.java @@ -36,6 +36,7 @@ import android.view.ViewGroup; import android.view.ViewParent; import android.view.animation.Animation; import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; import android.view.animation.Animation.AnimationListener; import android.widget.Checkable; import android.widget.Scroller; @@ -55,10 +56,12 @@ public abstract class PagedView extends ViewGroup { // The min drag distance to trigger a page shift (regardless of velocity) private static final int MIN_LENGTH_FOR_MOVE = 200; - private static final int PAGE_SNAP_ANIMATION_DURATION = 750; + private static final int PAGE_SNAP_ANIMATION_DURATION = 550; protected static final float NANOTIME_DIV = 1000000000.0f; - private static final float OVERSCROLL_DAMP_FACTOR = 0.22f; + private static final float OVERSCROLL_DAMP_FACTOR = 0.08f; + private static final int MINIMUM_SNAP_VELOCITY = 2200; + private static final int MIN_FLING_VELOCITY = 250; // the velocity at which a fling gesture will cause us to snap to the next page protected int mSnapVelocity = 500; @@ -209,7 +212,7 @@ public abstract class PagedView extends ViewGroup { mDirtyPageContent = new ArrayList<Boolean>(); mDirtyPageContent.ensureCapacity(32); mPageViewIconCache = new PagedViewIconCache(); - mScroller = new Scroller(getContext()); + mScroller = new Scroller(getContext(), new ScrollInterpolator()); mCurrentPage = 0; mCenterPagesVertically = true; @@ -827,8 +830,22 @@ public abstract class PagedView extends ViewGroup { return false; } + // This curve determines how the effect of scrolling over the limits of the page dimishes + // as the user pulls further and further from the bounds + private float overScrollInfluenceCurve(float f) { + f -= 1.0f; + return f * f * f + 1.0f; + } + protected void overScroll(float amount) { - int overScrollAmount = (int) Math.round(OVERSCROLL_DAMP_FACTOR * amount); + int screenSize = getMeasuredWidth(); + + float f = (amount / screenSize); + + if (f == 0) return; + f = f / (Math.abs(f)) * (overScrollInfluenceCurve(Math.abs(f))); + + int overScrollAmount = (int) Math.round(OVERSCROLL_DAMP_FACTOR * f * screenSize); if (amount < 0) { mScrollX = overScrollAmount; } else { @@ -902,8 +919,7 @@ public abstract class PagedView extends ViewGroup { final int snapVelocity = mSnapVelocity; if ((isSignificantMove && deltaX > 0 || - (isfling && velocityX > snapVelocity)) && - mCurrentPage > 0) { + (isfling && velocityX > snapVelocity)) && mCurrentPage > 0) { snapToPageWithVelocity(mCurrentPage - 1, velocityX); } else if ((isSignificantMove && deltaX < 0 || (isfling && velocityX < -snapVelocity)) && @@ -1048,10 +1064,58 @@ public abstract class PagedView extends ViewGroup { snapToPage(getPageNearestToCenterOfScreen(), PAGE_SNAP_ANIMATION_DURATION); } + private static class ScrollInterpolator implements Interpolator { + public ScrollInterpolator() { + } + + public float getInterpolation(float t) { + t -= 1.0f; + return t*t*t*t*t + 1; + } + } + + // We want the duration of the page snap animation to be influenced by the distance that + // the screen has to travel, however, we don't want this duration to be effected in a + // purely linear fashion. Instead, we use this method to moderate the effect that the distance + // of travel has on the overall snap duration. + float distanceInfluenceForSnapDuration(float f) { + f -= 0.5f; // center the values about 0. + f *= 0.3f * Math.PI / 2.0f; + return (float) Math.sin(f); + } + protected void snapToPageWithVelocity(int whichPage, int velocity) { - // We ignore velocity in this implementation, but children (e.g. SmoothPagedView) - // can use it - snapToPage(whichPage); + whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1)); + int halfScreenSize = getMeasuredWidth() / 2; + + final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage); + int delta = newX - mUnboundedScrollX; + int duration = 0; + + if (Math.abs(velocity) < MIN_FLING_VELOCITY) { + // 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); + return; + } + + // Here we compute a "distance" that will be used in the computation of the overall + // snap duration. This is a function of the actual distance that needs to be traveled; + // we keep this value close to half screen size in order to reduce the variance in snap + // duration as a function of the distance the page needs to travel. + float distanceRatio = 1.0f * Math.abs(delta) / 2 * halfScreenSize; + float distance = halfScreenSize + halfScreenSize * + distanceInfluenceForSnapDuration(distanceRatio); + + velocity = Math.abs(velocity); + velocity = Math.max(MINIMUM_SNAP_VELOCITY, velocity); + + // we want the page's snap velocity to approximately match the velocity at which the + // user flings, so we scale the duration by a value near to the derivative of the scroll + // interpolator at zero, ie. 5. We use 6 to make it a little slower. + duration = 6 * Math.round(1000 * Math.abs(distance / velocity)); + + snapToPage(whichPage, delta, duration); } protected void snapToPage(int whichPage) { diff --git a/src/com/android/launcher2/SmoothPagedView.java b/src/com/android/launcher2/SmoothPagedView.java index ee8bca20e..8b0a83502 100644 --- a/src/com/android/launcher2/SmoothPagedView.java +++ b/src/com/android/launcher2/SmoothPagedView.java @@ -21,7 +21,6 @@ import android.util.AttributeSet; import android.view.animation.Interpolator; import android.widget.Scroller; - public abstract class SmoothPagedView extends PagedView { private static final float SMOOTHING_SPEED = 0.75f; private static final float SMOOTHING_CONSTANT = (float) (0.016 / Math.log(SMOOTHING_SPEED)); @@ -29,8 +28,8 @@ public abstract class SmoothPagedView extends PagedView { private float mBaseLineFlingVelocity; private float mFlingVelocityInfluence; - static final int OVERSHOOT_MODE = 0; - static final int QUINTIC_MODE = 1; + static final int DEFAULT_MODE = 0; + static final int X_LARGE_MODE = 1; int mScrollMode; @@ -60,16 +59,6 @@ public abstract class SmoothPagedView extends PagedView { } } - private static class QuinticInterpolator implements Interpolator { - public QuinticInterpolator() { - } - - public float getInterpolation(float t) { - t -= 1.0f; - return t*t*t*t*t + 1; - } - } - /** * Used to inflate the Workspace from XML. * @@ -93,12 +82,12 @@ public abstract class SmoothPagedView extends PagedView { mUsePagingTouchSlop = false; // This means that we'll take care of updating the scroll parameter ourselves (we do it - // in computeScroll) - mDeferScrollUpdate = true; + // in computeScroll), we only do this in the OVERSHOOT_MODE, ie. on phones + mDeferScrollUpdate = mScrollMode != X_LARGE_MODE; } protected int getScrollMode() { - return OVERSHOOT_MODE; + return DEFAULT_MODE; } /** @@ -109,26 +98,30 @@ public abstract class SmoothPagedView extends PagedView { super.init(); mScrollMode = getScrollMode(); - if (mScrollMode == QUINTIC_MODE) { - mBaseLineFlingVelocity = 700.0f; - mFlingVelocityInfluence = 0.8f; - mScrollInterpolator = new QuinticInterpolator(); - } else { // QUINTIC_MODE + if (mScrollMode == DEFAULT_MODE) { mBaseLineFlingVelocity = 2500.0f; mFlingVelocityInfluence = 0.4f; mScrollInterpolator = new WorkspaceOvershootInterpolator(); + mScroller = new Scroller(getContext(), mScrollInterpolator); } - mScroller = new Scroller(getContext(), mScrollInterpolator); } @Override protected void snapToDestination() { - snapToPageWithVelocity(getPageNearestToCenterOfScreen(), 0); + if (mScrollMode == X_LARGE_MODE) { + super.snapToDestination(); + } else { + snapToPageWithVelocity(getPageNearestToCenterOfScreen(), 0); + } } @Override protected void snapToPageWithVelocity(int whichPage, int velocity) { - snapToPageWithVelocity(whichPage, 0, true); + if (mScrollMode == X_LARGE_MODE) { + super.snapToPageWithVelocity(whichPage, velocity); + } else { + snapToPageWithVelocity(whichPage, 0, true); + } } private void snapToPageWithVelocity(int whichPage, int velocity, boolean settle) { @@ -139,23 +132,16 @@ public abstract class SmoothPagedView extends PagedView { final int screenDelta = Math.max(1, Math.abs(whichPage - mCurrentPage)); final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage); final int delta = newX - mUnboundedScrollX; - int duration; - if (mScrollMode == OVERSHOOT_MODE) { - duration = (screenDelta + 1) * 100; - } else { // QUINTIC_MODE - duration = Math.round(Math.abs(delta) * 0.6f); - } + int duration = (screenDelta + 1) * 100; if (!mScroller.isFinished()) { mScroller.abortAnimation(); } - if (mScrollMode == OVERSHOOT_MODE) { - if (settle) { - ((WorkspaceOvershootInterpolator) mScrollInterpolator).setDistance(screenDelta); - } else { - ((WorkspaceOvershootInterpolator) mScrollInterpolator).disableSettle(); - } + if (settle) { + ((WorkspaceOvershootInterpolator) mScrollInterpolator).setDistance(screenDelta); + } else { + ((WorkspaceOvershootInterpolator) mScrollInterpolator).disableSettle(); } velocity = Math.abs(velocity); @@ -170,26 +156,33 @@ public abstract class SmoothPagedView extends PagedView { @Override protected void snapToPage(int whichPage) { - snapToPageWithVelocity(whichPage, 0, false); + if (mScrollMode == X_LARGE_MODE) { + super.snapToPage(whichPage); + } else { + snapToPageWithVelocity(whichPage, 0, false); + } } @Override public void computeScroll() { - boolean scrollComputed = computeScrollHelper(); + if (mScrollMode == X_LARGE_MODE) { + super.computeScroll(); + } else { + boolean scrollComputed = computeScrollHelper(); - if (!scrollComputed && mTouchState == TOUCH_STATE_SCROLLING) { - final float now = System.nanoTime() / NANOTIME_DIV; - final float e = (float) Math.exp((now - mSmoothingTime) / SMOOTHING_CONSTANT); + if (!scrollComputed && mTouchState == TOUCH_STATE_SCROLLING) { + final float now = System.nanoTime() / NANOTIME_DIV; + final float e = (float) Math.exp((now - mSmoothingTime) / SMOOTHING_CONSTANT); - final float dx = mTouchX - mUnboundedScrollX; - scrollTo(Math.round(mUnboundedScrollX + dx * e), mScrollY); - mSmoothingTime = now; + final float dx = mTouchX - mUnboundedScrollX; + scrollTo(Math.round(mUnboundedScrollX + dx * e), mScrollY); + mSmoothingTime = now; - // Keep generating points as long as we're more than 1px away from the target - if (dx > 1.f || dx < -1.f) { - invalidate(); + // Keep generating points as long as we're more than 1px away from the target + if (dx > 1.f || dx < -1.f) { + invalidate(); + } } } - } } diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index a79d236b0..0a3f9154f 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -109,6 +109,7 @@ public class Workspace extends SmoothPagedView private Drawable mBackground; private float mBackgroundAlpha = 0; private float mOverScrollMaxBackgroundAlpha = 0.0f; + private int mOverScrollPageIndex = -1; private final WallpaperManager mWallpaperManager; @@ -268,9 +269,9 @@ public class Workspace extends SmoothPagedView @Override protected int getScrollMode() { if (LauncherApplication.isScreenXLarge()) { - return SmoothPagedView.QUINTIC_MODE; + return SmoothPagedView.X_LARGE_MODE; } else { - return SmoothPagedView.OVERSHOOT_MODE; + return SmoothPagedView.DEFAULT_MODE; } } @@ -516,6 +517,7 @@ public class Workspace extends SmoothPagedView mAnimOnPageEndMoving = null; } mOverScrollMaxBackgroundAlpha = 0.0f; + mOverScrollPageIndex = -1; mPageMoving = false; } @@ -653,7 +655,7 @@ public class Workspace extends SmoothPagedView } float overScrollBackgroundAlphaInterpolator(float r) { - float threshold = 0.1f; + float threshold = 0.08f; if (r > mOverScrollMaxBackgroundAlpha) { mOverScrollMaxBackgroundAlpha = r; @@ -664,23 +666,6 @@ public class Workspace extends SmoothPagedView return Math.min(r / threshold, 1.0f); } - protected void overScroll(float amount) { - final int lastChildIndex = getChildCount() - 1; - - CellLayout cl; - if (amount < 0) { - cl = (CellLayout) getChildAt(0); - } else { - cl = (CellLayout) getChildAt(lastChildIndex); - } - - final int totalDistance = cl.getMeasuredWidth() + mPageSpacing; - float r = 1.0f * amount / totalDistance; - float rotation = -WORKSPACE_ROTATION * r; - cl.setBackgroundAlphaMultiplier(overScrollBackgroundAlphaInterpolator(Math.abs(r))); - cl.setRotationY(rotation); - } - @Override protected void screenScrolled(int screenCenter) { final int halfScreenSize = getMeasuredWidth() / 2; @@ -696,7 +681,18 @@ public class Workspace extends SmoothPagedView scrollProgress = Math.min(scrollProgress, 1.0f); scrollProgress = Math.max(scrollProgress, -1.0f); - cl.setBackgroundAlphaMultiplier(backgroundAlphaInterpolator(Math.abs(scrollProgress))); + // If the current page (i) is being overscrolled, we use a different + // set of rules for setting the background alpha multiplier. + if ((mScrollX < 0 && i == 0) || (mScrollX > mMaxScrollX && + i == getChildCount() -1 )) { + cl.setBackgroundAlphaMultiplier( + overScrollBackgroundAlphaInterpolator(Math.abs(scrollProgress))); + mOverScrollPageIndex = i; + } else if (mOverScrollPageIndex != i) { + cl.setBackgroundAlphaMultiplier( + backgroundAlphaInterpolator(Math.abs(scrollProgress))); + + } float rotation = WORKSPACE_ROTATION * scrollProgress; float translationX = getOffsetXForRotation(rotation, cl.getWidth(), cl.getHeight()); |