Hide taskbar view for app open/close animation.
Bug: 246635237
Test: open app in hotseat
close app in hotseat
the 'matching' view in taskbar should be hidden
tested icon, predicted icon, folders in taskbar/hotseat
Change-Id: I74382480826afafe6ae58e78faf26fe10812e29b
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 5ddf2a8..ea7eba3 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -634,7 +634,10 @@
boolean appTargetsAreTranslucent = areAllTargetsTranslucent(appTargets);
RectF launcherIconBounds = new RectF();
- FloatingIconView floatingView = FloatingIconView.getFloatingIconView(mLauncher, v,
+ FloatingIconView floatingView = getFloatingIconView(mLauncher, v,
+ mLauncher.getTaskbarUIController() == null
+ ? null
+ : mLauncher.getTaskbarUIController().findMatchingView(v),
!appTargetsAreTranslucent, launcherIconBounds, true /* isOpening */);
Rect crop = new Rect();
Matrix matrix = new Matrix();
@@ -1350,6 +1353,9 @@
isTransluscent, fallbackBackgroundColor);
} else if (launcherView != null) {
floatingIconView = getFloatingIconView(mLauncher, launcherView,
+ mLauncher.getTaskbarUIController() == null
+ ? null
+ : mLauncher.getTaskbarUIController().findMatchingView(launcherView),
true /* hideOriginal */, targetRect, false /* isOpening */);
} else {
targetRect.set(getDefaultWindowTargetRect());
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index b552e9b..13f0405 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -17,6 +17,8 @@
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
import android.content.Intent;
@@ -277,4 +279,30 @@
* No-op if the view is not yet open.
*/
public void launchSplitTasks(@NonNull View taskview, @NonNull GroupTask groupTask) { }
+
+ /**
+ * Returns the matching view (if any) in the taskbar.
+ * @param view The view to match.
+ */
+ public @Nullable View findMatchingView(View view) {
+ if (!(view.getTag() instanceof ItemInfo)) {
+ return null;
+ }
+ ItemInfo info = (ItemInfo) view.getTag();
+ if (info.container != CONTAINER_HOTSEAT && info.container != CONTAINER_HOTSEAT_PREDICTION) {
+ return null;
+ }
+
+ // Taskbar has the same items as the hotseat and we can use screenId to find the match.
+ int screenId = info.screenId;
+ View[] views = mControllers.taskbarViewController.getIconViews();
+ for (int i = views.length - 1; i >= 0; --i) {
+ if (views[i] != null
+ && views[i].getTag() instanceof ItemInfo
+ && ((ItemInfo) views[i].getTag()).screenId == screenId) {
+ return views[i];
+ }
+ }
+ return null;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index bb781c8..3151374 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -105,6 +105,9 @@
private HomeAnimationFactory createIconHomeAnimationFactory(View workspaceView) {
RectF iconLocation = new RectF();
FloatingIconView floatingIconView = getFloatingIconView(mActivity, workspaceView,
+ mActivity.getTaskbarUIController() == null
+ ? null
+ : mActivity.getTaskbarUIController().findMatchingView(workspaceView),
true /* hideOriginal */, iconLocation, false /* isOpening */);
// We want the window alpha to be 0 once this threshold is met, so that the
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 55af622..e233e46 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -95,6 +95,9 @@
private ClipIconView mClipIconView;
private @Nullable Drawable mBadge;
+ // A view whose visibility should update in sync with mOriginalIcon.
+ private @Nullable View mMatchVisibilityView;
+
private View mOriginalIcon;
private RectF mPositionOut;
private Runnable mOnTargetChangeRunnable;
@@ -386,7 +389,7 @@
* Checks if the icon result is loaded. If true, we set the icon immediately. Else, we add a
* callback to set the icon once the icon result is loaded.
*/
- private void checkIconResult(View originalView) {
+ private void checkIconResult() {
CancellationSignal cancellationSignal = new CancellationSignal();
if (mIconLoadResult == null) {
@@ -399,7 +402,7 @@
setIcon(mIconLoadResult.drawable, mIconLoadResult.badge,
mIconLoadResult.btvDrawable, mIconLoadResult.iconOffset);
setVisibility(VISIBLE);
- setIconAndDotVisible(originalView, false);
+ updateViewsVisibility(false /* isVisible */);
} else {
mIconLoadResult.onIconLoaded = () -> {
if (cancellationSignal.isCanceled()) {
@@ -410,7 +413,7 @@
mIconLoadResult.btvDrawable, mIconLoadResult.iconOffset);
setVisibility(VISIBLE);
- setIconAndDotVisible(originalView, false);
+ updateViewsVisibility(false /* isVisible */);
};
mLoadIconSignal = cancellationSignal;
}
@@ -481,9 +484,9 @@
// No need to wait for icon load since we can display the BubbleTextView drawable.
setVisibility(View.VISIBLE);
}
- if (!mIsOpening && mOriginalIcon != null) {
+ if (!mIsOpening) {
// When closing an app, we want the item on the workspace to be invisible immediately
- setIconAndDotVisible(mOriginalIcon, false);
+ updateViewsVisibility(false /* isVisible */);
}
}
@@ -562,13 +565,14 @@
/**
* Creates a floating icon view for {@param originalView}.
* @param originalView The view to copy
+ * @param secondView A view whose visibility should update in sync with originalView.
* @param hideOriginal If true, it will hide {@param originalView} while this view is visible.
* Else, we will not draw anything in this view.
* @param positionOut Rect that will hold the size and position of v.
* @param isOpening True if this view replaces the icon for app open animation.
*/
public static FloatingIconView getFloatingIconView(Launcher launcher, View originalView,
- boolean hideOriginal, RectF positionOut, boolean isOpening) {
+ @Nullable View secondView, boolean hideOriginal, RectF positionOut, boolean isOpening) {
final DragLayer dragLayer = launcher.getDragLayer();
ViewGroup parent = (ViewGroup) dragLayer.getParent();
FloatingIconView view = launcher.getViewCache().getView(R.layout.floating_icon_view,
@@ -578,6 +582,7 @@
// Init properties before getting the drawable.
view.mIsOpening = isOpening;
view.mOriginalIcon = originalView;
+ view.mMatchVisibilityView = secondView;
view.mPositionOut = positionOut;
// Get the drawable on the background thread
@@ -597,7 +602,8 @@
view.matchPositionOf(launcher, originalView, isOpening, positionOut);
// We need to add it to the overlay, but keep it invisible until animation starts..
- setIconAndDotVisible(view, false);
+ view.setVisibility(View.INVISIBLE);
+
parent.addView(view);
dragLayer.addView(view.mListenerView);
view.mListenerView.setListener(view::fastFinish);
@@ -606,7 +612,7 @@
view.mEndRunnable = null;
if (hideOriginal) {
- setIconAndDotVisible(originalView, true);
+ view.updateViewsVisibility(true /* isVisible */);
view.finish(dragLayer);
} else {
view.finish(dragLayer);
@@ -617,12 +623,21 @@
// Must be called after the fastFinish listener and end runnable is created so that
// the icon is not left in a hidden state.
if (shouldLoadIcon) {
- view.checkIconResult(originalView);
+ view.checkIconResult();
}
return view;
}
+ private void updateViewsVisibility(boolean isVisible) {
+ if (mOriginalIcon != null) {
+ setIconAndDotVisible(mOriginalIcon, isVisible);
+ }
+ if (mMatchVisibilityView != null) {
+ setIconAndDotVisible(mMatchVisibilityView, isVisible);
+ }
+ }
+
private void finish(DragLayer dragLayer) {
((ViewGroup) dragLayer.getParent()).removeView(this);
dragLayer.removeView(mListenerView);