Merge "Remove TaskViewDrawable, scale RecentsView instead" into ub-launcher3-qt-dev

This commit is contained in:
Tony Wickham
2019-05-17 20:41:55 +00:00
committed by Android (Google) Code Review
8 changed files with 68 additions and 296 deletions
@@ -20,6 +20,7 @@ import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import com.android.launcher3.Launcher;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -61,8 +62,8 @@ public class BackgroundAppState extends OverviewState {
return super.getOverviewScaleAndTranslation(launcher);
}
TaskView dummyTask = recentsView.getTaskViewAt(recentsView.getCurrentPage());
return recentsView.getTempClipAnimationHelper()
.getOverviewFullscreenScaleAndTranslation(dummyTask);
return recentsView.getTempClipAnimationHelper().updateForFullscreenOverview(dummyTask)
.getScaleAndTranslation();
}
@Override
@@ -18,8 +18,8 @@ package com.android.launcher3.uioverrides.touchcontrollers;
import static com.android.launcher3.AbstractFloatingView.TYPE_ACCESSIBLE;
import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -231,7 +231,8 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
} else {
mFlingBlockCheck.onEvent();
}
mCurrentAnimation.setPlayFraction(totalDisplacement * mProgressMultiplier);
mCurrentAnimation.setPlayFraction(Utilities.boundToRange(
totalDisplacement * mProgressMultiplier, 0, 1));
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (mRecentsView.getCurrentPage() != 0 || isGoingUp) {
@@ -285,13 +285,20 @@ public class ClipAnimationHelper {
/**
* Compute scale and translation y such that the specified task view fills the screen.
*/
public LauncherState.ScaleAndTranslation getOverviewFullscreenScaleAndTranslation(TaskView v) {
public ClipAnimationHelper updateForFullscreenOverview(TaskView v) {
TaskThumbnailView thumbnailView = v.getThumbnail();
RecentsView recentsView = v.getRecentsView();
fromTaskThumbnailView(thumbnailView, recentsView);
Rect taskSize = new Rect();
recentsView.getTaskSize(taskSize);
updateTargetRect(taskSize);
return this;
}
/**
* @return The source rect's scale and translation relative to the target rect.
*/
public LauncherState.ScaleAndTranslation getScaleAndTranslation() {
float scale = mSourceRect.width() / mTargetRect.width();
float translationY = mSourceRect.centerY() - mSourceRect.top - mTargetRect.centerY();
return new LauncherState.ScaleAndTranslation(scale, 0, translationY);
@@ -332,35 +339,10 @@ public class ClipAnimationHelper {
mSourceStackBounds.offset(left, insets.top + fullDp.availableHeightPx - taskHeight);
}
public void drawForProgress(TaskThumbnailView ttv, Canvas canvas, float progress) {
RectF currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTargetRect);
canvas.translate(mSourceStackBounds.left - mHomeStackBounds.left,
mSourceStackBounds.top - mHomeStackBounds.top);
mTmpMatrix.setRectToRect(mTargetRect, currentRect, ScaleToFit.FILL);
canvas.concat(mTmpMatrix);
canvas.translate(mTargetRect.left, mTargetRect.top);
float scale = mTargetRect.width() / mSourceRect.width();
float insetProgress = (1 - progress);
float windowCornerRadius = mUseRoundedCornersOnWindows
? mWindowCornerRadius : 0;
ttv.drawOnCanvas(canvas,
-mSourceWindowClipInsets.left * insetProgress,
-mSourceWindowClipInsets.top * insetProgress,
ttv.getMeasuredWidth() + mSourceWindowClipInsets.right * insetProgress,
ttv.getMeasuredHeight() + mSourceWindowClipInsets.bottom * insetProgress,
Utilities.mapRange(progress, windowCornerRadius * scale, ttv.getCornerRadius()));
}
public RectF getTargetRect() {
return mTargetRect;
}
public RectF getSourceRect() {
return mSourceRect;
}
public float getCurrentCornerRadius() {
return mCurrentCornerRadius;
}
@@ -1,151 +0,0 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.quickstep.util;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.util.FloatProperty;
import android.view.View;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.Utilities;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskThumbnailView;
import com.android.quickstep.views.TaskView;
public class TaskViewDrawable extends Drawable {
public static final FloatProperty<TaskViewDrawable> PROGRESS =
new FloatProperty<TaskViewDrawable>("progress") {
@Override
public void setValue(TaskViewDrawable taskViewDrawable, float v) {
taskViewDrawable.setProgress(v);
}
@Override
public Float get(TaskViewDrawable taskViewDrawable) {
return taskViewDrawable.mProgress;
}
};
/**
* 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;
private final float[] mIconPos;
private final TaskView mTaskView;
private final TaskThumbnailView mThumbnailView;
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;
mTaskView = tv;
mIconView = tv.getIconView();
mIconPos = new float[2];
mIconScale = mIconView.getScaleX();
Utilities.getDescendantCoordRelativeToAncestor(mIconView, parent, mIconPos, true);
mThumbnailView = tv.getThumbnail();
mClipAnimationHelper = new ClipAnimationHelper(parent.getContext());
mClipAnimationHelper.fromTaskThumbnailView(mThumbnailView, parent);
mClipAnimationHelper.prepareAnimation(
BaseActivity.fromContext(tv.getContext()).getDeviceProfile(), true /* isOpening */);
}
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
public void draw(Canvas canvas) {
canvas.save();
canvas.translate(mParent.getScrollX(), mParent.getScrollY());
mClipAnimationHelper.drawForProgress(mThumbnailView, canvas, mProgress);
canvas.restore();
canvas.save();
canvas.translate(mIconPos[0], mIconPos[1]);
canvas.scale(mIconScale, mIconScale, mIconView.getWidth() / 2, mIconView.getHeight() / 2);
mIconView.draw(canvas);
canvas.restore();
}
public ClipAnimationHelper getClipAnimationHelper() {
return mClipAnimationHelper;
}
@Override
public void setAlpha(int i) { }
@Override
public void setColorFilter(ColorFilter colorFilter) { }
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
public TaskView getTaskView() {
return mTaskView;
}
}
@@ -30,6 +30,7 @@ import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
@@ -178,6 +179,21 @@ public class LauncherRecentsView extends RecentsView<Launcher> {
return anim;
}
@Override
protected void onTaskLaunchAnimationUpdate(float progress, TaskView tv) {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (mRecentsAnimationWrapper.targetSet != null && tv.isRunningTask()) {
mTransformParams.setProgress(1 - progress)
.setSyncTransactionApplier(mSyncTransactionApplier)
.setForLiveTile(true);
mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
mTransformParams);
} else {
redrawLiveTile(true);
}
}
}
@Override
public PendingAnimation createTaskDismissAnimation(TaskView taskView, boolean animateTaskView,
boolean shouldRemoveTask, long duration) {
@@ -18,6 +18,7 @@ package com.android.quickstep.views;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
@@ -30,7 +31,6 @@ import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CLEAR_ALL_BUTTON;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
import static com.android.quickstep.util.ClipAnimationHelper.TransformParams;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -77,6 +77,7 @@ import com.android.launcher3.Insettable;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils.ViewProgressProperty;
import com.android.launcher3.LauncherState;
import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -99,7 +100,6 @@ import com.android.quickstep.RecentsModel.TaskThumbnailChangeListener;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.TaskViewDrawable;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -1311,15 +1311,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
setVisibility(alpha > 0 ? VISIBLE : GONE);
}
private float[] getAdjacentScaleAndTranslation(TaskView currTask,
float currTaskToScale, float currTaskToTranslationY) {
float displacement = currTask.getWidth() * (currTaskToScale - currTask.getCurveScale());
sTempFloatArray[0] = currTaskToScale;
sTempFloatArray[1] = mIsRtl ? -displacement : displacement;
sTempFloatArray[2] = currTaskToTranslationY;
return sTempFloatArray;
}
@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
@@ -1448,27 +1439,15 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
int centerTaskIndex = getCurrentPage();
boolean launchingCenterTask = taskIndex == centerTaskIndex;
float toScale = clipAnimationHelper.getSourceRect().width()
/ clipAnimationHelper.getTargetRect().width();
float toTranslationY = clipAnimationHelper.getSourceRect().centerY()
- clipAnimationHelper.getTargetRect().centerY();
LauncherState.ScaleAndTranslation toScaleAndTranslation = clipAnimationHelper
.getScaleAndTranslation();
float toScale = toScaleAndTranslation.scale;
float toTranslationY = toScaleAndTranslation.translationY;
if (launchingCenterTask) {
TaskView centerTask = getTaskViewAt(centerTaskIndex);
if (taskIndex - 1 >= 0) {
TaskView adjacentTask = getTaskViewAt(taskIndex - 1);
float[] scaleAndTranslation = getAdjacentScaleAndTranslation(centerTask,
toScale, toTranslationY);
scaleAndTranslation[1] = -scaleAndTranslation[1];
anim.play(createAnimForChild(adjacentTask, scaleAndTranslation));
anim.play(ObjectAnimator.ofFloat(adjacentTask, TaskView.FULLSCREEN_PROGRESS, 1));
}
if (taskIndex + 1 < getTaskViewCount()) {
TaskView adjacentTask = getTaskViewAt(taskIndex + 1);
float[] scaleAndTranslation = getAdjacentScaleAndTranslation(centerTask,
toScale, toTranslationY);
anim.play(createAnimForChild(adjacentTask, scaleAndTranslation));
anim.play(ObjectAnimator.ofFloat(adjacentTask, TaskView.FULLSCREEN_PROGRESS, 1));
}
RecentsView recentsView = tv.getRecentsView();
anim.play(ObjectAnimator.ofFloat(recentsView, SCALE_PROPERTY, toScale));
anim.play(ObjectAnimator.ofFloat(recentsView, TRANSLATION_Y, toTranslationY));
anim.play(ObjectAnimator.ofFloat(recentsView, FULLSCREEN_PROGRESS, 1));
} else {
// We are launching an adjacent task, so parallax the center and other adjacent task.
float displacementX = tv.getWidth() * (toScale - tv.getCurveScale());
@@ -1486,16 +1465,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return anim;
}
private Animator createAnimForChild(TaskView child, float[] toScaleAndTranslation) {
AnimatorSet anim = new AnimatorSet();
anim.play(ObjectAnimator.ofFloat(child, TaskView.ZOOM_SCALE, toScaleAndTranslation[0]));
anim.play(new PropertyListBuilder()
.translationX(toScaleAndTranslation[1])
.translationY(toScaleAndTranslation[2])
.build(child));
return anim;
}
public PendingAnimation createTaskLauncherAnimation(TaskView tv, long duration) {
if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) {
throw new IllegalStateException("Another pending animation is still running");
@@ -1506,60 +1475,38 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return new PendingAnimation(new AnimatorSet());
}
tv.setVisibility(INVISIBLE);
int targetSysUiFlags = tv.getThumbnail().getSysUiStatusNavFlags();
TaskViewDrawable drawable = new TaskViewDrawable(tv, this);
getOverlay().add(drawable);
final boolean[] passedOverviewThreshold = new boolean[] {false};
ObjectAnimator drawableAnim =
ObjectAnimator.ofFloat(drawable, TaskViewDrawable.PROGRESS, 1, 0);
drawableAnim.setInterpolator(LINEAR);
drawableAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
TransformParams mParams = new TransformParams();
ValueAnimator progressAnim = ValueAnimator.ofFloat(0, 1);
progressAnim.setInterpolator(LINEAR);
progressAnim.addUpdateListener(animator -> {
// Once we pass a certain threshold, update the sysui flags to match the target
// tasks' flags
mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW,
animator.getAnimatedFraction() > UPDATE_SYSUI_FLAGS_THRESHOLD
? targetSysUiFlags
: 0);
@Override
public void onAnimationUpdate(ValueAnimator animator) {
// Once we pass a certain threshold, update the sysui flags to match the target
// tasks' flags
mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW,
animator.getAnimatedFraction() > UPDATE_SYSUI_FLAGS_THRESHOLD
? targetSysUiFlags
: 0);
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (mRecentsAnimationWrapper.targetSet != null
&& drawable.getTaskView().isRunningTask()) {
mParams.setProgress(1 - animator.getAnimatedFraction())
.setSyncTransactionApplier(mSyncTransactionApplier)
.setForLiveTile(true);
drawable.getClipAnimationHelper().applyTransform(
mRecentsAnimationWrapper.targetSet, mParams);
} else {
redrawLiveTile(true);
}
}
onTaskLaunchAnimationUpdate(animator.getAnimatedFraction(), tv);
// Passing the threshold from taskview to fullscreen app will vibrate
final boolean passed = animator.getAnimatedFraction() >=
SUCCESS_TRANSITION_PROGRESS;
if (passed != passedOverviewThreshold[0]) {
passedOverviewThreshold[0] = passed;
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
// Passing the threshold from taskview to fullscreen app will vibrate
final boolean passed = animator.getAnimatedFraction() >=
SUCCESS_TRANSITION_PROGRESS;
if (passed != passedOverviewThreshold[0]) {
passedOverviewThreshold[0] = passed;
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
});
AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(tv,
drawable.getClipAnimationHelper());
anim.play(drawableAnim);
ClipAnimationHelper clipAnimationHelper = new ClipAnimationHelper(mActivity);
clipAnimationHelper.fromTaskThumbnailView(tv.getThumbnail(), this);
clipAnimationHelper.prepareAnimation(mActivity.getDeviceProfile(), true /* isOpening */);
AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(tv, clipAnimationHelper);
anim.play(progressAnim);
anim.setDuration(duration);
Consumer<Boolean> onTaskLaunchFinish = (result) -> {
onTaskLaunched(result);
tv.setVisibility(VISIBLE);
getOverlay().remove(drawable);
};
Consumer<Boolean> onTaskLaunchFinish = this::onTaskLaunched;
mPendingAnimation = new PendingAnimation(anim);
mPendingAnimation.addEndListener((onEndListener) -> {
@@ -1585,6 +1532,9 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return mPendingAnimation;
}
protected void onTaskLaunchAnimationUpdate(float progress, TaskView tv) {
}
public abstract boolean shouldUseMultiWindowTaskSizeStrategy();
protected void onTaskLaunched(boolean success) {
@@ -75,8 +75,6 @@ public class TaskThumbnailView extends View {
}
};
private final float mCornerRadius;
private final BaseActivity mActivity;
private final TaskOverlay mOverlay;
private final boolean mIsDarkTextTheme;
@@ -110,7 +108,6 @@ public class TaskThumbnailView extends View {
public TaskThumbnailView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mCornerRadius = TaskCornerRadius.get(context);
mOverlay = TaskOverlayFactory.INSTANCE.get(context).createOverlay(this);
mPaint.setFilterBitmap(true);
mBackgroundPaint.setColor(Color.WHITE);
@@ -118,7 +115,7 @@ public class TaskThumbnailView extends View {
mDimmingPaintAfterClearing.setColor(Color.BLACK);
mActivity = BaseActivity.fromContext(context);
mIsDarkTextTheme = Themes.getAttrBoolean(mActivity, R.attr.isWorkspaceDarkText);
mFullscreenParams = new TaskView.FullscreenDrawParams(mCornerRadius);
mFullscreenParams = new TaskView.FullscreenDrawParams(TaskCornerRadius.get(context));
}
public void bind(Task task) {
@@ -225,10 +222,6 @@ public class TaskThumbnailView extends View {
invalidate();
}
public float getCornerRadius() {
return mCornerRadius;
}
public void drawOnCanvas(Canvas canvas, float x, float y, float width, float height,
float cornerRadius) {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
@@ -103,19 +103,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
Collections.singletonList(new Rect());
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;
}
};
public static final FloatProperty<TaskView> FULLSCREEN_PROGRESS =
new FloatProperty<TaskView>("fullscreenProgress") {
@Override
@@ -165,7 +152,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
private IconView mIconView;
private DigitalWellBeingToast mDigitalWellBeingToast;
private float mCurveScale;
private float mZoomScale;
private float mFullscreenProgress;
private final FullscreenDrawParams mCurrentFullscreenParams;
private final float mCornerRadius;
@@ -459,7 +445,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
private void resetViewTransforms() {
setCurveScale(1);
setZoomScale(1);
setTranslationX(0f);
setTranslationY(0f);
setTranslationZ(0);
@@ -527,13 +512,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
return mCurveScale;
}
public void setZoomScale(float adjacentScale) {
mZoomScale = adjacentScale;
onScaleChanged();
}
private void onScaleChanged() {
float scale = mCurveScale * mZoomScale;
float scale = mCurveScale;
setScaleX(scale);
setScaleY(scale);
}