summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java2
-rw-r--r--quickstep/src/com/android/launcher3/uioverrides/OverviewState.java2
-rw-r--r--quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java169
-rw-r--r--quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java105
-rw-r--r--quickstep/src/com/android/quickstep/views/LauncherRecentsView.java37
-rw-r--r--src/com/android/launcher3/LauncherState.java4
-rw-r--r--src/com/android/launcher3/allapps/AllAppsTransitionController.java5
-rw-r--r--src/com/android/launcher3/anim/AnimatorSetBuilder.java15
-rw-r--r--src/com/android/launcher3/touch/AbstractStateChangeTouchController.java19
-rw-r--r--src_ui_overrides/com/android/launcher3/uioverrides/AllAppsState.java6
10 files changed, 266 insertions, 98 deletions
diff --git a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
index b580992c8..2ac932309 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
@@ -89,7 +89,7 @@ public class AllAppsState extends LauncherState {
}
@Override
- public float getOverviewTranslationX(Launcher launcher) {
+ public float getOverviewTranslationFactor(Launcher launcher) {
return 0;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index 0b69c582b..68322b0b1 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -58,7 +58,7 @@ public class OverviewState extends LauncherState {
}
@Override
- public float getOverviewTranslationX(Launcher launcher) {
+ public float getOverviewTranslationFactor(Launcher launcher) {
return 0;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
index 9f648edd1..1e006e575 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
@@ -18,16 +18,24 @@ package com.android.launcher3.uioverrides;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATION;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
+import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
import android.view.MotionEvent;
+import android.view.animation.Interpolator;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.touch.AbstractStateChangeTouchController;
import com.android.launcher3.touch.SwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
-import com.android.launcher3.touch.AbstractStateChangeTouchController;
import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.SysuiEventLogger;
@@ -36,6 +44,47 @@ import com.android.quickstep.util.SysuiEventLogger;
*/
public class PortraitStatesTouchController extends AbstractStateChangeTouchController {
+ private static final float TOTAL_DISTANCE_MULTIPLIER = 2f;
+ private static final float LINEAR_SCALE_LIMIT = 1 / TOTAL_DISTANCE_MULTIPLIER;
+
+ // Much be greater than LINEAR_SCALE_LIMIT;
+ private static final float MAXIMUM_DISTANCE_FACTOR = 0.9f;
+
+ // Maximum amount to overshoot.
+ private static final float MAX_OVERSHOOT = 0.3f;
+
+ private static final double PI_BY_2 = Math.PI / 2;
+
+ private InterpolatorWrapper mAllAppsInterpolatorWrapper = new InterpolatorWrapper();
+
+ // If > 0, the animation progress is clamped at that value as long as user is dragging.
+ private float mClampProgressUpdate = -1;
+
+ // If true, we will finish the current animation instantly on second touch.
+ private boolean mFinishFastOnSecondTouch;
+
+ private final Interpolator mAllAppsDampedInterpolator = new Interpolator() {
+
+ private final double mAngleMultiplier = Math.PI /
+ (2 * (MAXIMUM_DISTANCE_FACTOR - LINEAR_SCALE_LIMIT));
+
+ @Override
+ public float getInterpolation(float v) {
+ if (v <= LINEAR_SCALE_LIMIT) {
+ return v * TOTAL_DISTANCE_MULTIPLIER;
+ }
+ float overshoot = (v - LINEAR_SCALE_LIMIT);
+ return (float) (1 + MAX_OVERSHOOT * Math.sin(overshoot * mAngleMultiplier));
+ }
+ };
+
+ private final Interpolator mOverviewBoundInterpolator = (v) -> {
+ if (v >= MAXIMUM_DISTANCE_FACTOR) {
+ return 1;
+ }
+ return FAST_OUT_SLOW_IN.getInterpolation(v / MAXIMUM_DISTANCE_FACTOR);
+ };
+
public PortraitStatesTouchController(Launcher l) {
super(l, SwipeDetector.VERTICAL);
}
@@ -43,6 +92,11 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
@Override
protected boolean canInterceptTouch(MotionEvent ev) {
if (mCurrentAnimation != null) {
+ if (mFinishFastOnSecondTouch) {
+ // TODO: Animate to finish instead.
+ mCurrentAnimation.getAnimationPlayer().end();
+ }
+
// If we are already animating from a previous state, we can intercept.
return true;
}
@@ -100,17 +154,49 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
}
}
+ private AnimatorSetBuilder getNormalToOverviewAnimation() {
+ mAllAppsInterpolatorWrapper.baseInterpolator = mAllAppsDampedInterpolator;
+
+ AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ builder.setInterpolator(ANIM_VERTICAL_PROGRESS, mAllAppsInterpolatorWrapper);
+
+ builder.setInterpolator(ANIM_OVERVIEW_TRANSLATION, mOverviewBoundInterpolator);
+ return builder;
+ }
+
+ @Override
+ protected void updateProgress(float fraction) {
+ if (mClampProgressUpdate > 0) {
+ mCurrentAnimation.setPlayFraction(Math.min(fraction, mClampProgressUpdate));
+ } else {
+ super.updateProgress(fraction);
+ }
+ }
+
@Override
protected float initCurrentAnimation() {
float range = getShiftRange();
long maxAccuracy = (long) (2 * range);
- mCurrentAnimation = mLauncher.getStateManager()
- .createAnimationToNewWorkspace(mToState, maxAccuracy);
float startVerticalShift = mFromState.getVerticalProgress(mLauncher) * range;
float endVerticalShift = mToState.getVerticalProgress(mLauncher) * range;
float totalShift = endVerticalShift - startVerticalShift;
+
+ final AnimatorSetBuilder builder;
+
+ if (mFromState == NORMAL && mToState == OVERVIEW && totalShift != 0) {
+ builder = getNormalToOverviewAnimation();
+ totalShift = totalShift * TOTAL_DISTANCE_MULTIPLIER;
+ mClampProgressUpdate = MAXIMUM_DISTANCE_FACTOR;
+ } else {
+ builder = new AnimatorSetBuilder();
+ mClampProgressUpdate = -1;
+ }
+
+ mCurrentAnimation = mLauncher.getStateManager()
+ .createAnimationToNewWorkspace(mToState, builder, maxAccuracy);
+
if (totalShift == 0) {
totalShift = Math.signum(mFromState.ordinal - mToState.ordinal)
* OverviewState.getDefaultSwipeHeight(mLauncher);
@@ -119,10 +205,87 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
}
@Override
+ protected void updateSwipeCompleteAnimation(ValueAnimator animator, long expectedDuration,
+ LauncherState targetState, float velocity, boolean isFling) {
+ if (mFromState == NORMAL && mToState == OVERVIEW && targetState == OVERVIEW) {
+ mFinishFastOnSecondTouch = true;
+
+ // Update all apps interpolator
+ float currentFraction = mCurrentAnimation.getProgressFraction();
+ float absVelocity = Math.abs(velocity);
+ float currentValue = mAllAppsDampedInterpolator.getInterpolation(currentFraction);
+
+ if (isFling && absVelocity > 1 && currentFraction < LINEAR_SCALE_LIMIT) {
+
+ // TODO: Clean up these magic calculations
+ // Linearly interpolate the max value based on the velocity.
+ float maxValue = Math.max(absVelocity > 4 ? 1 + MAX_OVERSHOOT :
+ 1 + (absVelocity - 1) * MAX_OVERSHOOT / 3,
+ currentValue);
+ double angleToPeak = PI_BY_2 - Math.asin(currentValue / maxValue);
+
+ if (expectedDuration != 0 && angleToPeak != 0) {
+
+ float distanceLeft = 1 - currentFraction;
+ mAllAppsInterpolatorWrapper.baseInterpolator = (f) -> {
+ float scaledF = (f - currentFraction) / distanceLeft;
+
+ if (scaledF < 0.5f) {
+ double angle = PI_BY_2 - angleToPeak + scaledF * angleToPeak / 0.5f;
+ return (float) (maxValue * Math.sin(angle));
+ }
+
+ scaledF = ((scaledF - .5f) / .5f);
+ double angle = PI_BY_2 + 3 * scaledF * PI_BY_2;
+ float amplitude = (1 - scaledF) * (1 - scaledF) * (maxValue - 1);
+ return 1 + (float) (amplitude * Math.sin(angle));
+ };
+
+ animator.setDuration(expectedDuration).setInterpolator(LINEAR);
+ return;
+ }
+ }
+
+ if (currentFraction < LINEAR_SCALE_LIMIT) {
+ mAllAppsInterpolatorWrapper.baseInterpolator = LINEAR;
+ super.updateSwipeCompleteAnimation(animator, expectedDuration, targetState,
+ velocity, isFling);
+ return;
+ }
+ float extraValue = mAllAppsDampedInterpolator.getInterpolation(currentFraction) - 1;
+ float distanceLeft = 1 - currentFraction;
+
+ animator.setFloatValues(currentFraction, 1);
+ mAllAppsInterpolatorWrapper.baseInterpolator = (f) -> {
+ float scaledF = (f - currentFraction) / distanceLeft;
+
+ double angle = scaledF * 1.5 * Math.PI;
+ float amplitude = (1 - scaledF) * (1 - scaledF) * extraValue;
+ return 1 + (float) (amplitude * Math.sin(angle));
+ };
+ animator.setDuration(200).setInterpolator(LINEAR);
+ return;
+ }
+ mFinishFastOnSecondTouch = false;
+ super.updateSwipeCompleteAnimation(animator, expectedDuration, targetState,
+ velocity, isFling);
+ }
+
+ @Override
protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
super.onSwipeInteractionCompleted(targetState, logAction);
if (mFromState == NORMAL && targetState == OVERVIEW) {
SysuiEventLogger.writeDummyRecentsTransition(0);
}
}
+
+ private static class InterpolatorWrapper implements Interpolator {
+
+ public TimeInterpolator baseInterpolator = LINEAR;
+
+ @Override
+ public float getInterpolation(float v) {
+ return baseInterpolator.getInterpolation(v);
+ }
+ }
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index b68a3d845..ae747d881 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -16,32 +16,30 @@
package com.android.launcher3.uioverrides;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.anim.AlphaUpdateListener.updateVisibility;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATION;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled;
+import static com.android.quickstep.views.LauncherRecentsView.TRANSLATION_FACTOR;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.view.View;
+import android.animation.ValueAnimator;
+import android.annotation.TargetApi;
+import android.os.Build;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.PagedView;
-import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorSetBuilder;
-import com.android.launcher3.anim.Interpolators;
-import com.android.quickstep.AnimatedFloat;
-import com.android.quickstep.views.RecentsView;
+import com.android.launcher3.anim.PropertySetter;
+import com.android.quickstep.views.LauncherRecentsView;
+@TargetApi(Build.VERSION_CODES.O)
public class RecentsViewStateController implements StateHandler {
private final Launcher mLauncher;
- private final RecentsView mRecentsView;
-
- private final AnimatedFloat mTransitionProgress = new AnimatedFloat(this::onTransitionProgress);
- // The fraction representing the visibility of the RecentsView. This allows delaying the
- // overall transition while the RecentsView is being shown or hidden.
- private final AnimatedFloat mVisibilityMultiplier = new AnimatedFloat(this::onVisibilityProgress);
+ private final LauncherRecentsView mRecentsView;
public RecentsViewStateController(Launcher launcher) {
mLauncher = launcher;
@@ -50,14 +48,12 @@ public class RecentsViewStateController implements StateHandler {
@Override
public void setState(LauncherState state) {
- setVisibility(state.overviewUi);
- setTransitionProgress(state.overviewUi ? 1 : 0);
+ mRecentsView.setAlpha(state.overviewUi ? 1 : 0);
+ updateVisibility(mRecentsView, isAccessibilityEnabled(mLauncher));
+ mRecentsView.setTranslationFactor(state.getOverviewTranslationFactor(mLauncher));
if (state.overviewUi) {
mRecentsView.resetTaskVisuals();
}
- float overviewTranslationX = state.getOverviewTranslationX(mLauncher);
- int direction = mRecentsView.isRtl() ? -1 : 1;
- mRecentsView.setTranslationX(overviewTranslationX * direction);
}
@Override
@@ -76,73 +72,20 @@ public class RecentsViewStateController implements StateHandler {
builder.setStartDelay(snapDuration / 4);
}
- ObjectAnimator progressAnim =
- mTransitionProgress.animateToValue(toState.overviewUi ? 1 : 0);
- progressAnim.setDuration(config.duration);
- progressAnim.setInterpolator(Interpolators.LINEAR);
- builder.play(progressAnim);
-
- ObjectAnimator visibilityAnim = animateVisibility(toState.overviewUi);
- visibilityAnim.setDuration(config.duration);
- visibilityAnim.setInterpolator(Interpolators.LINEAR);
- builder.play(visibilityAnim);
+ PropertySetter setter = config.getProperSetter(builder);
+ setter.setFloat(mRecentsView, TRANSLATION_FACTOR,
+ toState.getOverviewTranslationFactor(mLauncher),
+ builder.getInterpolator(ANIM_OVERVIEW_TRANSLATION, LINEAR));
+ setter.setViewAlpha(mRecentsView, toState.overviewUi ? 1 : 0, LINEAR);
- int direction = mRecentsView.isRtl() ? -1 : 1;
- float fromTranslationX = fromState.getOverviewTranslationX(mLauncher) * direction;
- float toTranslationX = toState.getOverviewTranslationX(mLauncher) * direction;
- ObjectAnimator translationXAnim = ObjectAnimator.ofFloat(mRecentsView, View.TRANSLATION_X,
- fromTranslationX, toTranslationX);
- translationXAnim.setDuration(config.duration);
- translationXAnim.setInterpolator(Interpolators.ACCEL);
if (toState.overviewUi) {
- translationXAnim.addUpdateListener(valueAnimator -> {
+ ValueAnimator updateAnim = ValueAnimator.ofFloat(0, 1);
+ updateAnim.addUpdateListener(valueAnimator -> {
// While animating into recents, update the visible task data as needed
mRecentsView.loadVisibleTaskData();
});
+ updateAnim.setDuration(config.duration);
+ builder.play(updateAnim);
}
- builder.play(translationXAnim);
- }
-
- public void setVisibility(boolean isVisible) {
- mVisibilityMultiplier.cancelAnimation();
- mRecentsView.setVisibility(isVisible ? View.VISIBLE : View.GONE);
- mVisibilityMultiplier.updateValue(isVisible ? 1 : 0);
- }
-
- public ObjectAnimator animateVisibility(boolean isVisible) {
- ObjectAnimator anim = mVisibilityMultiplier.animateToValue(isVisible ? 1 : 0);
- if (isVisible) {
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- mRecentsView.setVisibility(View.VISIBLE);
- }
- });
- } else {
- anim.addListener(new AnimationSuccessListener() {
- @Override
- public void onAnimationSuccess(Animator animator) {
- mRecentsView.setVisibility(View.GONE);
- }
- });
- }
- return anim;
- }
-
- public void setTransitionProgress(float progress) {
- mTransitionProgress.cancelAnimation();
- mTransitionProgress.updateValue(progress);
- }
-
- private void onTransitionProgress() {
- applyProgress();
- }
-
- private void onVisibilityProgress() {
- applyProgress();
- }
-
- private void applyProgress() {
- mRecentsView.setAlpha(mTransitionProgress.value * mVisibilityMultiplier.value);
}
}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 7989e845c..d490f82b9 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -17,6 +17,7 @@ package com.android.quickstep.views;
import static com.android.launcher3.LauncherState.NORMAL;
+import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
@@ -30,7 +31,9 @@ import android.graphics.Shader;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.util.AttributeSet;
+import android.util.FloatProperty;
import android.widget.FrameLayout;
import com.android.launcher3.DeviceProfile;
@@ -41,14 +44,31 @@ import com.android.launcher3.R;
/**
* {@link RecentsView} used in Launcher activity
*/
+@TargetApi(Build.VERSION_CODES.O)
public class LauncherRecentsView extends RecentsView<Launcher> implements Insettable {
+ public static final FloatProperty<LauncherRecentsView> TRANSLATION_FACTOR =
+ new FloatProperty<LauncherRecentsView>("translationFactor") {
+
+ @Override
+ public void setValue(LauncherRecentsView view, float v) {
+ view.setTranslationFactor(v);
+ }
+
+ @Override
+ public Float get(LauncherRecentsView view) {
+ return view.mTranslationFactor;
+ }
+ };
+
private Bitmap mScrim;
private Paint mFadePaint;
private Shader mFadeShader;
private Matrix mFadeMatrix;
private boolean mScrimOnLeft;
+ private float mTranslationFactor;
+
public LauncherRecentsView(Context context) {
this(context, null);
}
@@ -131,4 +151,21 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements Insett
protected void onAllTasksRemoved() {
mActivity.getStateManager().goToState(NORMAL);
}
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+
+ int width = right - left;
+ setTranslationX(mTranslationFactor * (mIsRtl ? -width : width));
+ }
+
+ public void setTranslationFactor(float translationFactor) {
+ mTranslationFactor = translationFactor;
+ setTranslationX(translationFactor * (mIsRtl ? -getWidth() : getWidth()));
+ }
+
+ public float getTranslationFactor() {
+ return mTranslationFactor;
+ }
}
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 6185844cc..5c16ca990 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -180,8 +180,8 @@ public class LauncherState {
return new float[] {1, 0, 0};
}
- public float getOverviewTranslationX(Launcher launcher) {
- return launcher.getDragLayer().getMeasuredWidth();
+ public float getOverviewTranslationFactor(Launcher launcher) {
+ return 1;
}
public void onStateEnabled(Launcher launcher) {
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index fbd23d15a..9be123f97 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -3,6 +3,7 @@ package com.android.launcher3.allapps;
import static com.android.launcher3.LauncherState.ALL_APPS_CONTENT;
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER;
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
@@ -55,8 +56,6 @@ public class AllAppsTransitionController
}
};
- public static final float PARALLAX_COEFFICIENT = .125f;
-
private AllAppsContainerView mAppsView;
private final Launcher mLauncher;
@@ -169,7 +168,7 @@ public class AllAppsTransitionController
ObjectAnimator anim =
ObjectAnimator.ofFloat(this, ALL_APPS_PROGRESS, mProgress, targetProgress);
anim.setDuration(config.duration);
- anim.setInterpolator(interpolator);
+ anim.setInterpolator(builder.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));
anim.addListener(getProgressAnimatorListener());
builder.play(anim);
diff --git a/src/com/android/launcher3/anim/AnimatorSetBuilder.java b/src/com/android/launcher3/anim/AnimatorSetBuilder.java
index 7cd96512d..919104886 100644
--- a/src/com/android/launcher3/anim/AnimatorSetBuilder.java
+++ b/src/com/android/launcher3/anim/AnimatorSetBuilder.java
@@ -17,6 +17,8 @@ package com.android.launcher3.anim;
import android.animation.Animator;
import android.animation.AnimatorSet;
+import android.util.SparseArray;
+import android.view.animation.Interpolator;
import com.android.launcher3.LauncherAnimUtils;
@@ -27,7 +29,12 @@ import java.util.ArrayList;
*/
public class AnimatorSetBuilder {
+ public static final int ANIM_VERTICAL_PROGRESS = 0;
+ public static final int ANIM_OVERVIEW_TRANSLATION = 1;
+
protected final ArrayList<Animator> mAnims = new ArrayList<>();
+
+ private final SparseArray<Interpolator> mInterpolators = new SparseArray<>();
private long mStartDelay = 0;
/**
@@ -49,4 +56,12 @@ public class AnimatorSetBuilder {
anim.setStartDelay(mStartDelay);
return anim;
}
+
+ public Interpolator getInterpolator(int animId, Interpolator fallback) {
+ return mInterpolators.get(animId, fallback);
+ }
+
+ public void setInterpolator(int animId, Interpolator interpolator) {
+ mInterpolators.put(animId, interpolator);
+ }
}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index db5363436..a22f450e3 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -19,6 +19,7 @@ import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelo
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.util.Log;
import android.view.MotionEvent;
@@ -140,10 +141,14 @@ public abstract class AbstractStateChangeTouchController extends AnimatorListene
@Override
public boolean onDrag(float displacement, float velocity) {
float deltaProgress = mProgressMultiplier * displacement;
- mCurrentAnimation.setPlayFraction(deltaProgress + mStartProgress);
+ updateProgress(deltaProgress + mStartProgress);
return true;
}
+ protected void updateProgress(float fraction) {
+ mCurrentAnimation.setPlayFraction(fraction);
+ }
+
@Override
public void onDragEnd(float velocity, boolean fling) {
final int logAction;
@@ -173,7 +178,7 @@ public abstract class AbstractStateChangeTouchController extends AnimatorListene
startProgress = 1;
} else {
startProgress = Utilities.boundToRange(
- progress + velocity * SINGLE_FRAME_MS / getShiftRange(), 0f, 1f);
+ progress + velocity * SINGLE_FRAME_MS * mProgressMultiplier, 0f, 1f);
duration = SwipeDetector.calculateDuration(velocity,
endProgress - Math.max(progress, 0));
}
@@ -184,7 +189,7 @@ public abstract class AbstractStateChangeTouchController extends AnimatorListene
startProgress = 0;
} else {
startProgress = Utilities.boundToRange(
- progress + velocity * SINGLE_FRAME_MS / getShiftRange(), 0f, 1f);
+ progress + velocity * SINGLE_FRAME_MS * mProgressMultiplier, 0f, 1f);
duration = SwipeDetector.calculateDuration(velocity,
Math.min(progress, 1) - endProgress);
}
@@ -193,10 +198,16 @@ public abstract class AbstractStateChangeTouchController extends AnimatorListene
mCurrentAnimation.setEndAction(() -> onSwipeInteractionCompleted(targetState, logAction));
ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
anim.setFloatValues(startProgress, endProgress);
- anim.setDuration(duration).setInterpolator(scrollInterpolatorForVelocity(velocity));
+ updateSwipeCompleteAnimation(anim, duration, targetState, velocity, fling);
anim.start();
}
+ protected void updateSwipeCompleteAnimation(ValueAnimator animator, long expectedDuration,
+ LauncherState targetState, float velocity, boolean isFling) {
+ animator.setDuration(expectedDuration)
+ .setInterpolator(scrollInterpolatorForVelocity(velocity));
+ }
+
protected int getDirectionForLog() {
return mToState.ordinal > mFromState.ordinal ? Direction.UP : Direction.DOWN;
}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsState.java b/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsState.java
index c05d30ccd..121f13e7b 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsState.java
@@ -25,7 +25,6 @@ import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
/**
@@ -33,6 +32,8 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
*/
public class AllAppsState extends LauncherState {
+ private static final float PARALLAX_COEFFICIENT = .125f;
+
private static final int STATE_FLAGS = FLAG_DISABLE_ACCESSIBILITY
| FLAG_SHOW_SCRIM | FLAG_ALL_APPS_SCRIM;
@@ -75,8 +76,7 @@ public class AllAppsState extends LauncherState {
@Override
public float[] getWorkspaceScaleAndTranslation(Launcher launcher) {
return new float[] { 1f, 0,
- -launcher.getAllAppsController().getShiftRange()
- * AllAppsTransitionController.PARALLAX_COEFFICIENT};
+ -launcher.getAllAppsController().getShiftRange() * PARALLAX_COEFFICIENT};
}
@Override