Compute window offset when quick scrub starts

Instead of setting the window center to match the task center on every
update, compute the final offset when quick scrub starts and interpolate
alongside other factors such as window scale.

Bug: 78027888
Change-Id: I33b115764d46ecd6907ecb82b1ba12aeefc583c5
This commit is contained in:
Tony Wickham
2018-04-16 14:08:57 -07:00
parent 229fc93949
commit 78595cd7de
5 changed files with 78 additions and 32 deletions

View File

@@ -43,6 +43,7 @@ import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.views.LauncherLayoutListener;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.RecentsViewContainer;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -65,6 +66,8 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
*/
boolean onQuickInteractionStart(T activity, boolean activityVisible);
float getTranslationYForQuickScrub(T activity);
void executeOnWindowAvailable(T activity, Runnable action);
void onTransitionCancelled(T activity, boolean activityVisible);
@@ -117,6 +120,13 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
return !fromState.overviewUi;
}
@Override
public float getTranslationYForQuickScrub(Launcher activity) {
LauncherRecentsView recentsView = activity.getOverviewPanel();
float transYFactor = FAST_OVERVIEW.getOverviewScaleAndTranslationYFactor(activity)[1];
return recentsView.computeTranslationYForFactor(transYFactor);
}
@Override
public void executeOnWindowAvailable(Launcher activity, Runnable action) {
if (activity.getWorkspace().runOnOverlayHidden(action)) {
@@ -275,6 +285,11 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
return false;
}
@Override
public float getTranslationYForQuickScrub(RecentsActivity activity) {
return 0;
}
@Override
public void executeOnWindowAvailable(RecentsActivity activity, Runnable action) {
action.run();

View File

@@ -458,17 +458,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
}
mLauncherTransitionController.setPlayFraction(shift);
// Make sure the window follows the first task if it moves, e.g. during quick scrub.
View firstTask = mRecentsView.getPageAt(0);
// The first task may be null if we are swiping up from a task that does not
// appear in the list (ie. the assistant)
if (firstTask != null) {
int scrollForFirstTask = mRecentsView.getScrollForPage(0);
int offsetFromFirstTask = (scrollForFirstTask - mRecentsView.getScrollX());
mClipAnimationHelper.offsetTarget(firstTask.getScaleX(),
offsetFromFirstTask + firstTask.getTranslationX(),
mRecentsView.getTranslationY());
}
if (mRecentsAnimationWrapper.controller != null) {
// TODO: This logic is spartanic!
boolean passedThreshold = shift > 0.12f;
@@ -714,11 +703,31 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
}
private void onQuickScrubStart() {
mActivityControlHelper.onQuickInteractionStart(mActivity, mWasLauncherAlreadyVisible);
if (mLauncherTransitionController != null) {
mLauncherTransitionController.getAnimationPlayer().end();
mLauncherTransitionController = null;
}
mActivityControlHelper.onQuickInteractionStart(mActivity, false);
mQuickScrubController.onQuickScrubStart(false);
// Inform the last progress in case we skipped before.
mQuickScrubController.onQuickScrubProgress(mCurrentQuickScrubProgress);
// Make sure the window follows the first task if it moves, e.g. during quick scrub.
TaskView firstTask = mRecentsView.getPageAt(0);
// The first task may be null if we are swiping up from a task that does not
// appear in the list (i.e. the assistant)
if (firstTask != null) {
int scrollForFirstTask = mRecentsView.getScrollForPage(0);
int scrollForSecondTask = mRecentsView.getChildCount() > 1
? mRecentsView.getScrollForPage(1) : scrollForFirstTask;
int offsetFromFirstTask = scrollForFirstTask - scrollForSecondTask;
float interpolation = offsetFromFirstTask / (mRecentsView.getWidth() / 2);
mClipAnimationHelper.offsetTarget(
firstTask.getCurveScaleForInterpolation(interpolation), offsetFromFirstTask,
mActivityControlHelper.getTranslationYForQuickScrub(mActivity));
}
}
private void onFinishedTransitionToQuickScrub() {

View File

@@ -15,9 +15,13 @@
*/
package com.android.quickstep.util;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.SCROLL;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Matrix.ScaleToFit;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -46,8 +50,10 @@ public class ClipAnimationHelper {
private final RectF mSourceRect = new RectF();
// The bounds of the task view in launcher window coordinates
private final RectF mTargetRect = new RectF();
// Doesn't change after initialized, used as an anchor when changing mTargetRect
private final RectF mInitialTargetRect = new RectF();
// Doesn't change after initialized, used as an anchor when changing mTargetOffset
private final PointF mInitialTargetOffset = new PointF();
// Set when the final window destination is changed, such as offsetting for quick scrub
private final PointF mTargetOffset = new PointF();
// The insets to be used for clipping the app window, which can be larger than mSourceInsets
// if the aspect ratio of the target is smaller than the aspect ratio of the source rect. In
// app window coordinates.
@@ -60,6 +66,9 @@ public class ClipAnimationHelper {
private final Rect mClipRect = new Rect();
private final RectFEvaluator mRectFEvaluator = new RectFEvaluator();
private final Matrix mTmpMatrix = new Matrix();
private final RectF mTmpRectF = new RectF();
private float mTargetScale = 1f;
public void updateSource(Rect homeStackBounds, RemoteAnimationTargetCompat target) {
mHomeStackBounds.set(homeStackBounds);
@@ -75,10 +84,9 @@ public class ClipAnimationHelper {
mSourceStackBounds.width() - mSourceInsets.right,
mSourceStackBounds.height() - mSourceInsets.bottom);
mTargetRect.set(targetRect);
mTargetRect.offset(mHomeStackBounds.left - mSourceStackBounds.left,
mInitialTargetOffset.set(mHomeStackBounds.left - mSourceStackBounds.left,
mHomeStackBounds.top - mSourceStackBounds.top);
mInitialTargetRect.set(mTargetRect);
mTargetOffset.set(mInitialTargetOffset);
// Calculate the clip based on the target rect (since the content insets and the
// launcher insets may differ, so the aspect ratio of the target rect can differ
@@ -98,10 +106,13 @@ public class ClipAnimationHelper {
public void applyTransform(RemoteAnimationTargetSet targetSet, float progress) {
RectF currentRect;
synchronized (mTargetRect) {
currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTargetRect);
mTmpRectF.set(mTargetRect);
Utilities.scaleRectFAboutCenter(mTmpRectF, mTargetScale);
currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTmpRectF);
synchronized (mTargetOffset) {
// Stay lined up with the center of the target, since it moves for quick scrub.
currentRect.offset(mTargetRect.centerX() - currentRect.centerX(), 0);
currentRect.offset(mTargetOffset.x * SCROLL.getInterpolation(progress),
mTargetOffset.y * LINEAR.getInterpolation(progress));
}
mClipRect.left = (int) (mSourceWindowClipInsets.left * progress);
@@ -131,10 +142,10 @@ public class ClipAnimationHelper {
}
public void offsetTarget(float scale, float offsetX, float offsetY) {
synchronized (mTargetRect) {
mTargetRect.set(mInitialTargetRect);
Utilities.scaleRectFAboutCenter(mTargetRect, scale);
mTargetRect.offset(offsetX, offsetY);
synchronized (mTargetOffset) {
mTargetScale = scale;
mTargetOffset.set(mInitialTargetOffset);
mTargetOffset.offset(offsetX, offsetY);
}
}
@@ -187,13 +198,11 @@ public class ClipAnimationHelper {
}
public void drawForProgress(TaskThumbnailView ttv, Canvas canvas, float progress) {
RectF currentRect;
synchronized (mTargetRect) {
currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTargetRect);
}
RectF currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTargetRect);
canvas.translate(mSourceStackBounds.left - mHomeStackBounds.left,
mSourceStackBounds.top - mHomeStackBounds.top);
synchronized (mTargetOffset) {
canvas.translate(-mTargetOffset.x, -mTargetOffset.y);
}
mTmpMatrix.setRectToRect(mTargetRect, currentRect, ScaleToFit.FILL);
canvas.concat(mTmpMatrix);
canvas.translate(mTargetRect.left, mTargetRect.top);

View File

@@ -86,7 +86,11 @@ public class LauncherRecentsView extends RecentsView<Launcher> {
public void setTranslationYFactor(float translationFactor) {
mTranslationYFactor = translationFactor;
setTranslationY(mTranslationYFactor * (getPaddingBottom() - getPaddingTop()));
setTranslationY(computeTranslationYForFactor(mTranslationYFactor));
}
public float computeTranslationYForFactor(float translationYFactor) {
return translationYFactor * (getPaddingBottom() - getPaddingTop());
}
@Override

View File

@@ -219,11 +219,20 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
mSnapshotView.setDimAlpha(mCurveDimAlpha);
}
mCurveScale = 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR;
mCurveScale = getCurveScaleForCurveInterpolation(curveInterpolation);
setScaleX(mCurveScale);
setScaleY(mCurveScale);
}
public float getCurveScaleForInterpolation(float linearInterpolation) {
float curveInterpolation = CURVE_INTERPOLATOR.getInterpolation(linearInterpolation);
return getCurveScaleForCurveInterpolation(curveInterpolation);
}
private float getCurveScaleForCurveInterpolation(float curveInterpolation) {
return 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR;
}
public float getCurveScale() {
return mCurveScale;
}