Improve animation when swiping down on task

- Scale icon down/up atomically at a threshold
- Fix scale of tasks to properly take curve/zoom scale into account

Bug: 78779525
Change-Id: I5909c63b18a993433de7a38b9641f4f38a219807
This commit is contained in:
Tony
2018-05-08 13:23:00 -07:00
parent 729020d186
commit b271ad8972
3 changed files with 91 additions and 25 deletions

View File

@@ -15,7 +15,9 @@
*/
package com.android.quickstep.util;
import android.animation.TimeInterpolator;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
@@ -30,7 +32,7 @@ import com.android.quickstep.views.TaskView;
public class TaskViewDrawable extends Drawable {
public static FloatProperty<TaskViewDrawable> PROGRESS =
public static final FloatProperty<TaskViewDrawable> PROGRESS =
new FloatProperty<TaskViewDrawable>("progress") {
@Override
public void setValue(TaskViewDrawable taskViewDrawable, float v) {
@@ -43,8 +45,10 @@ public class TaskViewDrawable extends Drawable {
}
};
private static final TimeInterpolator ICON_SIZE_INTERPOLATOR =
(t) -> (Math.max(t, 0.3f) - 0.3f) / 0.7f;
/**
* The progress at which we play the atomic icon scale animation.
*/
private static final float ICON_SCALE_THRESHOLD = 0.95f;
private final RecentsView mParent;
private final View mIconView;
@@ -55,11 +59,15 @@ public class TaskViewDrawable extends Drawable {
private final ClipAnimationHelper mClipAnimationHelper;
private float mProgress = 1;
private boolean mPassedIconScaleThreshold;
private ValueAnimator mIconScaleAnimator;
private float mIconScale;
public TaskViewDrawable(TaskView tv, RecentsView parent) {
mParent = parent;
mIconView = tv.getIconView();
mIconPos = new int[2];
mIconScale = mIconView.getScaleX();
Utilities.getDescendantCoordRelativeToAncestor(mIconView, parent, mIconPos, true);
mThumbnailView = tv.getThumbnail();
@@ -70,6 +78,37 @@ public class TaskViewDrawable extends Drawable {
public void setProgress(float progress) {
mProgress = progress;
mParent.invalidate();
boolean passedIconScaleThreshold = progress <= ICON_SCALE_THRESHOLD;
if (mPassedIconScaleThreshold != passedIconScaleThreshold) {
mPassedIconScaleThreshold = passedIconScaleThreshold;
animateIconScale(mPassedIconScaleThreshold ? 0 : 1);
}
}
private void animateIconScale(float toScale) {
if (mIconScaleAnimator != null) {
mIconScaleAnimator.cancel();
}
mIconScaleAnimator = ValueAnimator.ofFloat(mIconScale, toScale);
mIconScaleAnimator.addUpdateListener(valueAnimator -> {
mIconScale = (float) valueAnimator.getAnimatedValue();
if (mProgress > ICON_SCALE_THRESHOLD) {
// Speed up the icon scale to ensure it is 1 when progress is 1.
float iconProgress = (mProgress - ICON_SCALE_THRESHOLD) / (1 - ICON_SCALE_THRESHOLD);
if (iconProgress > mIconScale) {
mIconScale = iconProgress;
}
}
invalidateSelf();
});
mIconScaleAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mIconScaleAnimator = null;
}
});
mIconScaleAnimator.setDuration(TaskView.SCALE_ICON_DURATION);
mIconScaleAnimator.start();
}
@Override
@@ -81,8 +120,7 @@ public class TaskViewDrawable extends Drawable {
canvas.save();
canvas.translate(mIconPos[0], mIconPos[1]);
float scale = ICON_SIZE_INTERPOLATOR.getInterpolation(mProgress);
canvas.scale(scale, scale, mIconView.getWidth() / 2, mIconView.getHeight() / 2);
canvas.scale(mIconScale, mIconScale, mIconView.getWidth() / 2, mIconView.getHeight() / 2);
mIconView.draw(canvas);
canvas.restore();
}

View File

@@ -22,6 +22,7 @@ import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
@@ -960,15 +961,13 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
if (currTask == null) {
return;
}
currTask.setScaleX(mAdjacentScale);
currTask.setScaleY(mAdjacentScale);
currTask.setZoomScale(mAdjacentScale);
if (mCurrentPage - 1 >= 0) {
TaskView adjacentTask = getPageAt(mCurrentPage - 1);
float[] scaleAndTranslation = getAdjacentScaleAndTranslation(currTask, adjacentTask,
mAdjacentScale, 0);
adjacentTask.setScaleX(scaleAndTranslation[0]);
adjacentTask.setScaleY(scaleAndTranslation[0]);
adjacentTask.setZoomScale(scaleAndTranslation[0]);
adjacentTask.setTranslationX(-scaleAndTranslation[1]);
adjacentTask.setTranslationY(scaleAndTranslation[2]);
}
@@ -976,8 +975,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
TaskView adjacentTask = getPageAt(mCurrentPage + 1);
float[] scaleAndTranslation = getAdjacentScaleAndTranslation(currTask, adjacentTask,
mAdjacentScale, 0);
adjacentTask.setScaleX(scaleAndTranslation[0]);
adjacentTask.setScaleY(scaleAndTranslation[0]);
adjacentTask.setZoomScale(scaleAndTranslation[0]);
adjacentTask.setTranslationX(scaleAndTranslation[1]);
adjacentTask.setTranslationY(scaleAndTranslation[2]);
}
@@ -986,7 +984,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
private float[] getAdjacentScaleAndTranslation(TaskView currTask, TaskView adjacentTask,
float currTaskToScale, float currTaskToTranslationY) {
float displacement = currTask.getWidth() * (currTaskToScale - currTask.getCurveScale());
sTempFloatArray[0] = currTaskToScale * adjacentTask.getCurveScale();
sTempFloatArray[0] = currTaskToScale;
sTempFloatArray[1] = mIsRtl ? -displacement : displacement;
sTempFloatArray[2] = currTaskToTranslationY;
return sTempFloatArray;
@@ -1127,13 +1125,15 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return anim;
}
private ObjectAnimator createAnimForChild(View child, float[] toScaleAndTranslation) {
return ObjectAnimator.ofPropertyValuesHolder(child,
private Animator createAnimForChild(TaskView child, float[] toScaleAndTranslation) {
AnimatorSet anim = new AnimatorSet();
anim.play(ObjectAnimator.ofFloat(child, TaskView.ZOOM_SCALE, toScaleAndTranslation[0]));
anim.play(ObjectAnimator.ofPropertyValuesHolder(child,
new PropertyListBuilder()
.scale(child.getScaleX() * toScaleAndTranslation[0])
.translationX(toScaleAndTranslation[1])
.translationY(toScaleAndTranslation[2])
.build());
.build()));
return anim;
}
public PendingAnimation createTaskLauncherAnimation(TaskView tv, long duration) {

View File

@@ -30,14 +30,15 @@ import android.graphics.Outline;
import android.os.Bundle;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.Log;
import android.util.Property;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Toast;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
@@ -76,12 +77,26 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
*/
private static final float EDGE_SCALE_DOWN_FACTOR = 0.03f;
private static final long SCALE_ICON_DURATION = 120;
public static final long SCALE_ICON_DURATION = 120;
public static final Property<TaskView, Float> ZOOM_SCALE =
new FloatProperty<TaskView>("zoomScale") {
@Override
public void setValue(TaskView taskView, float v) {
taskView.setZoomScale(v);
}
@Override
public Float get(TaskView taskView) {
return taskView.mZoomScale;
}
};
private Task mTask;
private TaskThumbnailView mSnapshotView;
private IconView mIconView;
private float mCurveScale;
private float mZoomScale;
private float mCurveDimAlpha;
private Animator mDimAlphaAnim;
@@ -207,8 +222,7 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
}
public void resetVisualProperties() {
setScaleX(1f);
setScaleY(1f);
setZoomScale(1);
setTranslationX(0f);
setTranslationY(0f);
setTranslationZ(0);
@@ -226,9 +240,7 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
mSnapshotView.setDimAlpha(mCurveDimAlpha);
}
mCurveScale = getCurveScaleForCurveInterpolation(curveInterpolation);
setScaleX(mCurveScale);
setScaleY(mCurveScale);
setCurveScale(getCurveScaleForCurveInterpolation(curveInterpolation));
}
@Override
@@ -247,10 +259,26 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
return 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR;
}
private void setCurveScale(float curveScale) {
mCurveScale = curveScale;
onScaleChanged();
}
public float getCurveScale() {
return mCurveScale;
}
public void setZoomScale(float adjacentScale) {
mZoomScale = adjacentScale;
onScaleChanged();
}
private void onScaleChanged() {
float scale = mCurveScale * mZoomScale;
setScaleX(scale);
setScaleY(scale);
}
@Override
public boolean hasOverlappingRendering() {
// TODO: Clip-out the icon region from the thumbnail, since they are overlapping.