Merge "Redraw live tile in updatePageOffsets()" into sc-dev
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 827eb7d..62ab95a 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -172,6 +172,8 @@
private final float mClosingWindowTransY;
private final float mMaxShadowRadius;
+ private final StartingWindowListener mStartingWindowListener = new StartingWindowListener();
+
private DeviceProfile mDeviceProfile;
private RemoteAnimationProvider mRemoteAnimationProvider;
@@ -221,13 +223,9 @@
}
};
+ mStartingWindowListener.setTransitionManager(this);
SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(
- new IStartingWindowListener.Stub() {
- @Override
- public void onTaskLaunching(int taskId, int supportedType) {
- mTypeForTaskId.put(taskId, supportedType);
- }
- });
+ mStartingWindowListener);
}
}
@@ -566,7 +564,6 @@
// Set the crop here so we can calculate the corner radius below.
crop.set(left, top, right, bottom);
- RectF targetBounds = new RectF(windowTargetBounds);
RectF floatingIconBounds = new RectF();
RectF tmpRectF = new RectF();
Point tmpPos = new Point();
@@ -655,12 +652,8 @@
tmpRectF.offset(dragLayerBounds[0], dragLayerBounds[1]);
tmpRectF.offset(mDx.value, mDy.value);
Utilities.scaleRectFAboutCenter(tmpRectF, mIconScaleToFitScreen.value);
- float windowTransX0 = tmpRectF.left - offsetX;
- float windowTransY0 = tmpRectF.top - offsetY;
- if (hasSplashScreen) {
- windowTransX0 -= crop.left * scale;
- windowTransY0 -= crop.top * scale;
- }
+ float windowTransX0 = tmpRectF.left - offsetX - crop.left * scale;
+ float windowTransY0 = tmpRectF.top - offsetY - crop.top * scale;
// Calculate the icon position.
floatingIconBounds.set(launcherIconBounds);
@@ -819,6 +812,7 @@
public void onActivityDestroyed() {
unregisterRemoteAnimations();
unregisterRemoteTransitions();
+ mStartingWindowListener.setTransitionManager(null);
SystemUiProxy.INSTANCE.getNoCreate().setStartingWindowListener(null);
}
@@ -1213,25 +1207,16 @@
alphaDuration = useUpwardAnimation ? APP_LAUNCH_ALPHA_DURATION
: APP_LAUNCH_ALPHA_DOWN_DURATION;
- if (hasSplashScreen) {
- iconAlphaStart = 0;
+ iconAlphaStart = hasSplashScreen ? 0 : 1f;
- // TOOD: Share value from shell when available.
- final float windowIconSize = Utilities.pxFromSp(108, r.getDisplayMetrics());
+ // TOOD: Share value from shell when available.
+ final float windowIconSize = Utilities.pxFromSp(108, r.getDisplayMetrics());
- cropCenterXStart = windowTargetBounds.centerX();
- cropCenterYStart = windowTargetBounds.centerY();
+ cropCenterXStart = windowTargetBounds.centerX();
+ cropCenterYStart = windowTargetBounds.centerY();
- cropWidthStart = (int) windowIconSize;
- cropHeightStart = (int) windowIconSize;
- } else {
- iconAlphaStart = 1;
-
- cropWidthStart = cropHeightStart =
- Math.min(windowTargetBounds.width(), windowTargetBounds.height());
- cropCenterXStart = cropCenterYStart =
- Math.min(windowTargetBounds.centerX(), windowTargetBounds.centerY());
- }
+ cropWidthStart = (int) windowIconSize;
+ cropHeightStart = (int) windowIconSize;
cropWidthEnd = windowTargetBounds.width();
cropHeightEnd = windowTargetBounds.height();
@@ -1240,4 +1225,17 @@
cropCenterYEnd = windowTargetBounds.centerY();
}
}
+
+ private static class StartingWindowListener extends IStartingWindowListener.Stub {
+ private QuickstepTransitionManager mTransitionManager;
+
+ public void setTransitionManager(QuickstepTransitionManager transitionManager) {
+ mTransitionManager = transitionManager;
+ }
+
+ @Override
+ public void onTaskLaunching(int taskId, int supportedType) {
+ mTransitionManager.mTypeForTaskId.put(taskId, supportedType);
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java b/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java
index 351adf4..c527be3 100644
--- a/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java
+++ b/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java
@@ -46,7 +46,8 @@
}
public boolean get() {
- return mBasePredicate.get() && mSupported && mObserver.isHomeAndOverviewSame();
+ return mBasePredicate.get() && mSupported && mObserver != null
+ && mObserver.isHomeAndOverviewSame();
}
public void initialize(Context context) {
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 5761dfb..d59d120 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -142,7 +142,6 @@
import com.android.quickstep.TaskViewUtils;
import com.android.quickstep.ViewUtils;
import com.android.quickstep.util.LayoutUtils;
-import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.SplitScreenBounds;
import com.android.quickstep.util.SplitSelectStateController;
@@ -328,6 +327,8 @@
private float mFullscreenScale;
private static final int DISMISS_TASK_DURATION = 300;
+ private static final int DISMISS_TASK_TRANSLATION_DURATION = 200;
+ private static final int ADDITIONAL_DISMISS_TASK_TRANSLATION_DURATION = 75;
private static final int ADDITION_TASK_DURATION = 200;
// The threshold at which we update the SystemUI flags when animating from the task into the app
public static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.85f;
@@ -365,15 +366,13 @@
protected float mTaskViewsPrimaryTranslation = 0;
// Progress from 0 to 1 where 0 is a carousel and 1 is a 2 row grid.
private float mGridProgress = 0;
+ private final IntSet mTopRowIdSet = new IntSet();
// The GestureEndTarget that is still in progress.
protected GestureState.GestureEndTarget mCurrentGestureEndTarget;
- IntSet mTopIdSet = new IntSet();
-
private int mOverScrollShift = 0;
-
/**
* TODO: Call reloadIdNeeded in onTaskStackChanged.
*/
@@ -825,18 +824,16 @@
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
appAnimator.setDuration(RECENTS_LAUNCH_DURATION);
appAnimator.setInterpolator(ACCEL_DEACCEL);
- appAnimator.addUpdateListener(new MultiValueUpdateListener() {
- @Override
- public void onUpdate(float percent) {
- SurfaceParams.Builder builder = new SurfaceParams.Builder(
- apps[apps.length - 1].leash);
- Matrix matrix = new Matrix();
- matrix.postScale(percent, percent);
- matrix.postTranslate(mActivity.getDeviceProfile().widthPx * (1 - percent) / 2,
- mActivity.getDeviceProfile().heightPx * (1 - percent) / 2);
- builder.withAlpha(percent).withMatrix(matrix);
- surfaceApplier.scheduleApply(builder.build());
- }
+ appAnimator.addUpdateListener(valueAnimator -> {
+ float percent = valueAnimator.getAnimatedFraction();
+ SurfaceParams.Builder builder = new SurfaceParams.Builder(
+ apps[apps.length - 1].leash);
+ Matrix matrix = new Matrix();
+ matrix.postScale(percent, percent);
+ matrix.postTranslate(mActivity.getDeviceProfile().widthPx * (1 - percent) / 2,
+ mActivity.getDeviceProfile().heightPx * (1 - percent) / 2);
+ builder.withAlpha(percent).withMatrix(matrix);
+ surfaceApplier.scheduleApply(builder.build());
});
anim.play(appAnimator);
anim.addListener(new AnimatorListenerAdapter() {
@@ -1299,7 +1296,7 @@
}
mClearAllButton.setFullscreenTranslationPrimary(accumulatedTranslationX);
- updateGridProperties(/*isTaskDismissal=*/false);
+ updateGridProperties();
}
public void getTaskSize(Rect outRect) {
@@ -1659,7 +1656,7 @@
// When switching to tasks in quick switch, ensures the snapped page's scroll maintain
// invariant between quick switch and overview grid, to ensure a smooth animation
// transition.
- updateGridProperties(/*isTaskDismissal=*/false);
+ updateGridProperties();
}
}
@@ -1832,13 +1829,26 @@
}
}
+ /** Updates TaskView and ClearAllButtion scaling and translation required to turn into grid
+ * layout.
+ * This method is used when no task dismissal has occurred.
+ */
+ private void updateGridProperties() {
+ updateGridProperties(null, -1);
+ }
+
/**
* Updates TaskView and ClearAllButton scaling and translation required to turn into grid
* layout.
* This method only calculates the potential position and depends on {@link #setGridProgress} to
- * apply the actual scaling and translation.
+ * apply the actual scaling and translation. This adds task translation animations in the case
+ * of task dismissals: e.g. when dismissedTask is not null.
+ *
+ * @param dismissedTask the TaskView dismissed, possibly null
+ * @param dismissedIndex the index at which the dismissedTask was prior to dismissal, if no
+ * dismissal occurred, this is unused
*/
- private void updateGridProperties(boolean isTaskDismissal) {
+ private void updateGridProperties(TaskView dismissedTask, int dismissedIndex) {
int taskCount = getTaskViewCount();
if (taskCount == 0) {
return;
@@ -1865,8 +1875,12 @@
int snappedPage = getNextPage();
TaskView snappedTaskView = getTaskViewAtByAbsoluteIndex(snappedPage);
+ boolean isTaskDismissal = dismissedTask != null;
+ float dismissedTaskWidth =
+ isTaskDismissal ? dismissedTask.getLayoutParams().width + mPageSpacing : 0;
+
if (!isTaskDismissal) {
- mTopIdSet.clear();
+ mTopRowIdSet.clear();
}
for (int i = 0; i < taskCount; i++) {
TaskView taskView = getTaskViewAt(i);
@@ -1901,13 +1915,14 @@
// calculate the distance focused task need to shift.
focusedTaskShift += mIsRtl ? taskWidthAndSpacing : -taskWidthAndSpacing;
}
- boolean isTopRow = isTaskDismissal ? mTopIdSet.contains(taskView.getTask().key.id)
+ int taskId = taskView.getTask().key.id;
+ boolean isTopRow = isTaskDismissal ? mTopRowIdSet.contains(taskId)
: topRowWidth <= bottomRowWidth;
if (isTopRow) {
gridTranslations[i] += topAccumulatedTranslationX;
topRowWidth += taskWidthAndSpacing;
topSet.add(i);
- mTopIdSet.add(taskView.getTask().key.id);
+ mTopRowIdSet.add(taskId);
taskView.setGridTranslationY(taskGridVerticalDiff);
@@ -1961,17 +1976,55 @@
snappedTaskGridTranslationX = gridTranslations[snappedPage - mTaskViewStartIndex];
}
-
+ // Animate task dismissTranslationX for tasks with index >= dismissed index and in the
+ // same row as the dismissed index, or if the dismissed task was the focused task. Offset
+ // successive task dismissal durations for a staggered effect.
+ ArrayList<Animator> gridTranslationAnimators = new ArrayList<>();
+ boolean isFocusedTaskDismissed =
+ isTaskDismissal && dismissedTask.getTask().key.id == mFocusedTaskId;
for (int i = 0; i < taskCount; i++) {
TaskView taskView = getTaskViewAt(i);
+ if (isFocusedTaskDismissed || (i >= dismissedIndex && isSameGridRow(dismissedTask,
+ taskView))) {
+ Animator taskDismissAnimator = ObjectAnimator.ofFloat(taskView,
+ taskView.getPrimaryDismissTranslationProperty(),
+ mIsRtl ? -dismissedTaskWidth : dismissedTaskWidth, 0f);
+ int additionalTranslationDuration =
+ i >= dismissedIndex ? (ADDITIONAL_DISMISS_TASK_TRANSLATION_DURATION * (
+ (i - dismissedIndex) / 2)) : 0;
+ taskDismissAnimator.setDuration(
+ DISMISS_TASK_TRANSLATION_DURATION + additionalTranslationDuration);
+ gridTranslationAnimators.add(taskDismissAnimator);
+ }
taskView.setGridTranslationX(gridTranslations[i] - snappedTaskGridTranslationX);
taskView.setNonFullscreenTranslationX(snappedTaskFullscreenScrollAdjustment);
}
+ AnimatorSet gridTranslationAnimatorSet = new AnimatorSet();
+ gridTranslationAnimatorSet.playTogether(gridTranslationAnimators);
+ gridTranslationAnimatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ // Allow the actions view to display again once in focus mode
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ if (getFocusedTaskView() == null) {
+ mActionsView.getScrollAlpha().setValue(1);
+ }
+ }
- // Use the accumulated translation of the longer row.
- float clearAllAccumulatedTranslation = mIsRtl ? Math.max(topAccumulatedTranslationX,
- bottomAccumulatedTranslationX) : Math.min(topAccumulatedTranslationX,
- bottomAccumulatedTranslationX);
+ @Override
+ // Hide the actions view if not in focus mode
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ if (getFocusedTaskView() == null) {
+ mActionsView.getScrollAlpha().setValue(0);
+ }
+ }
+ });
+ gridTranslationAnimatorSet.start();
+
+ // Use the accumulated translation of the row containing the last task.
+ float clearAllAccumulatedTranslation = topSet.contains(taskCount - 1)
+ ? topAccumulatedTranslationX : bottomAccumulatedTranslationX;
// If the last task is on the shorter row, ClearAllButton will embed into the shorter row
// which is not what we want. Compensate the width difference of the 2 rows in that case.
@@ -1989,13 +2042,14 @@
mIsRtl ? -shorterRowCompensation : shorterRowCompensation;
// If the total width is shorter than one grid's width, move ClearAllButton further away
- // accordingly.
+ // accordingly. Update longRowWidth if ClearAllButton has been moved.
float clearAllShortTotalCompensation = 0;
int longRowWidth = Math.max(topRowWidth, bottomRowWidth);
if (longRowWidth < mLastComputedGridSize.width()) {
float shortTotalCompensation = mLastComputedGridSize.width() - longRowWidth;
clearAllShortTotalCompensation =
mIsRtl ? -shortTotalCompensation : shortTotalCompensation;
+ longRowWidth = mLastComputedGridSize.width();
}
float clearAllTotalTranslationX =
@@ -2028,6 +2082,19 @@
setGridProgress(mGridProgress);
}
+ private boolean isSameGridRow(TaskView taskView1, TaskView taskView2) {
+ if (taskView1 == null || taskView2 == null) {
+ return false;
+ }
+ int taskId1 = taskView1.getTask().key.id;
+ int taskId2 = taskView2.getTask().key.id;
+ if (taskId1 == mFocusedTaskId || taskId2 == mFocusedTaskId) {
+ return false;
+ }
+ return (mTopRowIdSet.contains(taskId1) && mTopRowIdSet.contains(taskId2)) || (
+ !mTopRowIdSet.contains(taskId1) && !mTopRowIdSet.contains(taskId2));
+ }
+
/**
* Moves TaskView and ClearAllButton between carousel and 2 row grid.
*
@@ -2238,8 +2305,12 @@
}
int pageToSnapTo = mCurrentPage;
- if (draggedIndex < pageToSnapTo ||
- pageToSnapTo == (getTaskViewCount() - 1)) {
+ // Snap to start if focused task was dismissed, as after quick switch it could
+ // be at any page but the focused task always displays at the start.
+ if (taskView.getTask().key.id == mFocusedTaskId) {
+ pageToSnapTo = mTaskViewStartIndex;
+ } else if (draggedIndex < pageToSnapTo || pageToSnapTo == (getTaskViewCount()
+ - 1)) {
pageToSnapTo -= 1;
}
removeViewInLayout(taskView);
@@ -2250,7 +2321,7 @@
} else {
snapToPageImmediately(pageToSnapTo);
// Grid got messed up, reapply.
- updateGridProperties(/*isTaskDismissal=*/true);
+ updateGridProperties(taskView, draggedIndex - mTaskViewStartIndex);
if (showAsGrid() && getFocusedTaskView() == null) {
animateActionsViewOut();
}
@@ -2259,7 +2330,9 @@
// immediately available.
onLayout(false /* changed */, getLeft(), getTop(), getRight(), getBottom());
}
- resetTaskVisuals();
+ if (!showAsGrid()) {
+ resetTaskVisuals();
+ }
onDismissAnimationEnds();
mPendingAnimation = null;
}