summaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/com')
-rw-r--r--src/com/android/launcher2/PagedView.java82
-rw-r--r--src/com/android/launcher2/SmoothPagedView.java89
-rw-r--r--src/com/android/launcher2/Workspace.java38
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());