Merge "Add taskbar icons unfold animation" into sc-v2-dev
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 033cf8e..2534699 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -35,6 +35,8 @@
import android.content.Intent;
import android.content.IntentSender;
import android.content.ServiceConnection;
+import android.hardware.SensorManager;
+import android.hardware.devicestate.DeviceStateManager;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;
@@ -73,6 +75,8 @@
import com.android.quickstep.TaskUtils;
import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.TouchInteractionService.TISBinder;
+import com.android.quickstep.util.LauncherUnfoldAnimationController;
+import com.android.quickstep.util.ProxyScreenStatusProvider;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
import com.android.quickstep.util.SplitSelectStateController;
@@ -82,6 +86,9 @@
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import com.android.systemui.unfold.UnfoldTransitionFactory;
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
+import com.android.systemui.unfold.config.UnfoldTransitionConfig;
import java.util.List;
import java.util.stream.Stream;
@@ -117,6 +124,7 @@
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mTaskbarManager = ((TISBinder) iBinder).getTaskbarManager();
mTaskbarManager.setLauncher(BaseQuickstepLauncher.this);
+
Log.d(TAG, "TIS service connected");
resetServiceBindRetryState();
@@ -142,16 +150,41 @@
private @Nullable DragOptions mNextWorkspaceDragOptions = null;
private SplitPlaceholderView mSplitPlaceholderView;
+ private @Nullable UnfoldTransitionProgressProvider mUnfoldTransitionProgressProvider;
+ private @Nullable LauncherUnfoldAnimationController mLauncherUnfoldAnimationController;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SysUINavigationMode.INSTANCE.get(this).addModeChangeListener(this);
addMultiWindowModeChangedListener(mDepthController);
+ initUnfoldTransitionProgressProvider();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ if (mLauncherUnfoldAnimationController != null) {
+ mLauncherUnfoldAnimationController.onResume();
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ if (mLauncherUnfoldAnimationController != null) {
+ mLauncherUnfoldAnimationController.onPause();
+ }
+
+ super.onPause();
}
@Override
public void onDestroy() {
mAppTransitionManager.onActivityDestroyed();
+ if (mUnfoldTransitionProgressProvider != null) {
+ mUnfoldTransitionProgressProvider.destroy();
+ }
SysUINavigationMode.INSTANCE.get(this).removeModeChangeListener(this);
@@ -160,6 +193,11 @@
mTaskbarManager.clearLauncher(this);
}
resetServiceBindRetryState();
+
+ if (mLauncherUnfoldAnimationController != null) {
+ mLauncherUnfoldAnimationController.onDestroy();
+ }
+
super.onDestroy();
}
@@ -334,6 +372,28 @@
mConnectionAttempts = 0;
}
+ private void initUnfoldTransitionProgressProvider() {
+ final UnfoldTransitionConfig config = UnfoldTransitionFactory.createConfig(this);
+ if (config.isEnabled()) {
+ mUnfoldTransitionProgressProvider =
+ UnfoldTransitionFactory.createUnfoldTransitionProgressProvider(
+ this,
+ config,
+ ProxyScreenStatusProvider.INSTANCE,
+ getSystemService(DeviceStateManager.class),
+ getSystemService(SensorManager.class),
+ getMainThreadHandler(),
+ getMainExecutor()
+ );
+
+ mLauncherUnfoldAnimationController = new LauncherUnfoldAnimationController(
+ this,
+ getWindowManager(),
+ mUnfoldTransitionProgressProvider
+ );
+ }
+ }
+
public void setTaskbarUIController(LauncherTaskbarUIController taskbarUIController) {
mTaskbarUIController = taskbarUIController;
}
@@ -373,6 +433,11 @@
return mTaskbarStateHandler;
}
+ @Nullable
+ public UnfoldTransitionProgressProvider getUnfoldTransitionProgressProvider() {
+ return mUnfoldTransitionProgressProvider;
+ }
+
@Override
public boolean supportsAdaptiveIconAnimation(View clickedView) {
return mAppTransitionManager.hasControlRemoteAppTransitionPermission()
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 8c12567..51d031b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -62,6 +62,7 @@
import com.android.launcher3.views.ActivityContext;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SysUINavigationMode.Mode;
+import com.android.quickstep.util.ScopedUnfoldTransitionProgressProvider;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -98,7 +99,8 @@
private boolean mIsDestroyed = false;
public TaskbarActivityContext(Context windowContext, DeviceProfile dp,
- TaskbarNavButtonController buttonController) {
+ TaskbarNavButtonController buttonController, ScopedUnfoldTransitionProgressProvider
+ unfoldTransitionProgressProvider) {
super(windowContext, Themes.getActivityThemeRes(windowContext));
mDeviceProfile = dp;
@@ -120,6 +122,14 @@
FrameLayout navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view);
StashedHandleView stashedHandleView = mDragLayer.findViewById(R.id.stashed_handle);
+ Display display = windowContext.getDisplay();
+ Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY
+ ? windowContext.getApplicationContext()
+ : windowContext.getApplicationContext().createDisplayContext(display);
+ mWindowManager = c.getSystemService(WindowManager.class);
+ mLeftCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
+ mRightCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
+
// Construct controllers.
mControllers = new TaskbarControllers(this,
new TaskbarDragController(this),
@@ -129,18 +139,12 @@
R.color.popup_color_primary_light),
new TaskbarDragLayerController(this, mDragLayer),
new TaskbarViewController(this, taskbarView),
+ new TaskbarUnfoldAnimationController(unfoldTransitionProgressProvider,
+ mWindowManager),
new TaskbarKeyguardController(this),
new StashedHandleViewController(this, stashedHandleView),
new TaskbarStashController(this),
new TaskbarEduController(this));
-
- Display display = windowContext.getDisplay();
- Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY
- ? windowContext.getApplicationContext()
- : windowContext.getApplicationContext().createDisplayContext(display);
- mWindowManager = c.getSystemService(WindowManager.class);
- mLeftCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
- mRightCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
}
public void init() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 1197543..6144881 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -31,6 +31,7 @@
public final RotationButtonController rotationButtonController;
public final TaskbarDragLayerController taskbarDragLayerController;
public final TaskbarViewController taskbarViewController;
+ public final TaskbarUnfoldAnimationController taskbarUnfoldAnimationController;
public final TaskbarKeyguardController taskbarKeyguardController;
public final StashedHandleViewController stashedHandleViewController;
public final TaskbarStashController taskbarStashController;
@@ -46,6 +47,7 @@
RotationButtonController rotationButtonController,
TaskbarDragLayerController taskbarDragLayerController,
TaskbarViewController taskbarViewController,
+ TaskbarUnfoldAnimationController taskbarUnfoldAnimationController,
TaskbarKeyguardController taskbarKeyguardController,
StashedHandleViewController stashedHandleViewController,
TaskbarStashController taskbarStashController,
@@ -57,6 +59,7 @@
this.rotationButtonController = rotationButtonController;
this.taskbarDragLayerController = taskbarDragLayerController;
this.taskbarViewController = taskbarViewController;
+ this.taskbarUnfoldAnimationController = taskbarUnfoldAnimationController;
this.taskbarKeyguardController = taskbarKeyguardController;
this.stashedHandleViewController = stashedHandleViewController;
this.taskbarStashController = taskbarStashController;
@@ -75,6 +78,7 @@
}
taskbarDragLayerController.init(this);
taskbarViewController.init(this);
+ taskbarUnfoldAnimationController.init(this);
taskbarKeyguardController.init(navbarButtonsViewController);
stashedHandleViewController.init(this);
taskbarStashController.init(this);
@@ -89,6 +93,7 @@
rotationButtonController.onDestroy();
taskbarDragLayerController.onDestroy();
taskbarKeyguardController.onDestroy();
+ taskbarUnfoldAnimationController.onDestroy();
taskbarViewController.onDestroy();
stashedHandleViewController.onDestroy();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 4ed83f2..ec98bbf 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -42,6 +42,7 @@
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TouchInteractionService;
+import com.android.quickstep.util.ScopedUnfoldTransitionProgressProvider;
/**
* Class to manage taskbar lifecycle
@@ -58,6 +59,10 @@
private final TaskbarNavButtonController mNavButtonController;
private final SettingsCache.OnChangeListener mUserSetupCompleteListener;
+ // The source for this provider is set when Launcher is available
+ private final ScopedUnfoldTransitionProgressProvider mUnfoldProgressProvider =
+ new ScopedUnfoldTransitionProgressProvider();
+
private TaskbarActivityContext mTaskbarActivityContext;
private BaseQuickstepLauncher mLauncher;
/**
@@ -120,6 +125,9 @@
*/
public void setLauncher(@NonNull BaseQuickstepLauncher launcher) {
mLauncher = launcher;
+ mUnfoldProgressProvider.setSourceProvider(launcher
+ .getUnfoldTransitionProgressProvider());
+
if (mTaskbarActivityContext != null) {
mTaskbarActivityContext.setUIController(
new LauncherTaskbarUIController(launcher, mTaskbarActivityContext));
@@ -135,6 +143,7 @@
if (mTaskbarActivityContext != null) {
mTaskbarActivityContext.setUIController(TaskbarUIController.DEFAULT);
}
+ mUnfoldProgressProvider.setSourceProvider(null);
}
}
@@ -153,8 +162,8 @@
return;
}
- mTaskbarActivityContext = new TaskbarActivityContext(
- mContext, dp.copy(mContext), mNavButtonController);
+ mTaskbarActivityContext = new TaskbarActivityContext(mContext, dp.copy(mContext),
+ mNavButtonController, mUnfoldProgressProvider);
mTaskbarActivityContext.init();
if (mLauncher != null) {
mTaskbarActivityContext.setUIController(
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java
new file mode 100644
index 0000000..43f015c
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2021 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.launcher3.taskbar;
+
+import android.view.View;
+import android.view.WindowManager;
+
+import com.android.quickstep.util.LauncherViewsMoveFromCenterTranslationApplier;
+import com.android.quickstep.util.ScopedUnfoldTransitionProgressProvider;
+import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator;
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
+
+/**
+ * Controls animation of taskbar icons when unfolding foldable devices
+ */
+public class TaskbarUnfoldAnimationController {
+
+ private final ScopedUnfoldTransitionProgressProvider mUnfoldTransitionProgressProvider;
+ private final UnfoldMoveFromCenterAnimator mMoveFromCenterAnimator;
+ private final TransitionListener mTransitionListener = new TransitionListener();
+ private TaskbarViewController mTaskbarViewController;
+
+ public TaskbarUnfoldAnimationController(ScopedUnfoldTransitionProgressProvider
+ unfoldTransitionProgressProvider, WindowManager windowManager) {
+ mUnfoldTransitionProgressProvider = unfoldTransitionProgressProvider;
+ mMoveFromCenterAnimator = new UnfoldMoveFromCenterAnimator(windowManager,
+ new LauncherViewsMoveFromCenterTranslationApplier());
+ }
+
+ /**
+ * Initializes the controller
+ * @param taskbarControllers references to all other taskbar controllers
+ */
+ public void init(TaskbarControllers taskbarControllers) {
+ mTaskbarViewController = taskbarControllers.taskbarViewController;
+ mTaskbarViewController.addOneTimePreDrawListener(() ->
+ mUnfoldTransitionProgressProvider.setReadyToHandleTransition(true));
+ mUnfoldTransitionProgressProvider.addCallback(mTransitionListener);
+ }
+
+ /**
+ * Destroys the controller
+ */
+ public void onDestroy() {
+ mUnfoldTransitionProgressProvider.setReadyToHandleTransition(false);
+ mUnfoldTransitionProgressProvider.removeCallback(mTransitionListener);
+ }
+
+ private class TransitionListener implements TransitionProgressListener {
+
+ @Override
+ public void onTransitionStarted() {
+ mMoveFromCenterAnimator.updateDisplayProperties();
+ View[] icons = mTaskbarViewController.getIconViews();
+ for (View icon : icons) {
+ // TODO(b/193794563) we should re-register views if they are re-bound/re-inflated
+ // during the animation
+ mMoveFromCenterAnimator.registerViewForAnimation(icon);
+ }
+
+ mMoveFromCenterAnimator.onTransitionStarted();
+ }
+
+ @Override
+ public void onTransitionFinished() {
+ mMoveFromCenterAnimator.onTransitionFinished();
+ }
+
+ @Override
+ public void onTransitionProgress(float progress) {
+ mMoveFromCenterAnimator.onTransitionProgress(progress);
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index f1748af..f359a3d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -16,20 +16,24 @@
package com.android.launcher3.taskbar;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
-import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.AnimatedFloat.VALUE;
import android.graphics.Rect;
+import android.util.FloatProperty;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnPreDrawListener;
+import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.quickstep.AnimatedFloat;
@@ -117,6 +121,25 @@
mTaskbarView.setClickAndLongClickListenersForIcon(icon);
}
+ /**
+ * Adds one time pre draw listener to the taskbar view, it is called before
+ * drawing a frame and invoked only once
+ * @param listener callback that will be invoked before drawing the next frame
+ */
+ public void addOneTimePreDrawListener(Runnable listener) {
+ mTaskbarView.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ final ViewTreeObserver viewTreeObserver = mTaskbarView.getViewTreeObserver();
+ if (viewTreeObserver.isAlive()) {
+ listener.run();
+ viewTreeObserver.removeOnPreDrawListener(this);
+ }
+ return true;
+ }
+ });
+ }
+
public Rect getIconLayoutBounds() {
return mTaskbarView.getIconLayoutBounds();
}
@@ -194,7 +217,7 @@
float childCenter = (child.getLeft() + child.getRight()) / 2;
float hotseatIconCenter = hotseatPadding.left + hotseatCellSize * info.screenId
+ hotseatCellSize / 2;
- setter.setFloat(child, VIEW_TRANSLATE_X, hotseatIconCenter - childCenter, LINEAR);
+ setter.setFloat(child, ICON_TRANSLATE_X, hotseatIconCenter - childCenter, LINEAR);
}
AnimatorPlaybackController controller = setter.createPlaybackController();
@@ -257,4 +280,30 @@
return false;
}
}
+
+ public static final FloatProperty<View> ICON_TRANSLATE_X =
+ new FloatProperty<View>("taskbarAligmentTranslateX") {
+
+ @Override
+ public void setValue(View view, float v) {
+ if (view instanceof BubbleTextView) {
+ ((BubbleTextView) view).setTranslationXForTaskbarAlignmentAnimation(v);
+ } else if (view instanceof FolderIcon) {
+ ((FolderIcon) view).setTranslationForTaskbarAlignmentAnimation(v);
+ } else {
+ view.setTranslationX(v);
+ }
+ }
+
+ @Override
+ public Float get(View view) {
+ if (view instanceof BubbleTextView) {
+ return ((BubbleTextView) view)
+ .getTranslationXForTaskbarAlignmentAnimation();
+ } else if (view instanceof FolderIcon) {
+ return ((FolderIcon) view).getTranslationXForTaskbarAlignmentAnimation();
+ }
+ return view.getTranslationX();
+ }
+ };
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 14bc380..2009cd7 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -36,13 +36,9 @@
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
-import android.hardware.SensorManager;
-import android.hardware.devicestate.DeviceStateManager;
import android.view.HapticFeedbackConstants;
import android.view.View;
-import androidx.annotation.Nullable;
-
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
@@ -79,14 +75,9 @@
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskUtils;
-import com.android.quickstep.util.LauncherUnfoldAnimationController;
-import com.android.quickstep.util.ProxyScreenStatusProvider;
import com.android.quickstep.util.QuickstepOnboardingPrefs;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
-import com.android.systemui.unfold.UnfoldTransitionFactory;
-import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
-import com.android.systemui.unfold.config.UnfoldTransitionConfig;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -106,51 +97,10 @@
private FixedContainerItems mAllAppsPredictions;
private HotseatPredictionController mHotseatPredictionController;
- @Nullable
- private LauncherUnfoldAnimationController mLauncherUnfoldAnimationController;
-
@Override
protected void setupViews() {
super.setupViews();
mHotseatPredictionController = new HotseatPredictionController(this);
-
- final UnfoldTransitionConfig config = UnfoldTransitionFactory.createConfig(this);
- if (config.isEnabled()) {
- final UnfoldTransitionProgressProvider unfoldTransitionProgressProvider =
- UnfoldTransitionFactory.createUnfoldTransitionProgressProvider(
- this,
- config,
- ProxyScreenStatusProvider.INSTANCE,
- getSystemService(DeviceStateManager.class),
- getSystemService(SensorManager.class),
- getMainThreadHandler(),
- getMainExecutor()
- );
-
- mLauncherUnfoldAnimationController = new LauncherUnfoldAnimationController(
- this,
- getWindowManager(),
- unfoldTransitionProgressProvider
- );
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- if (mLauncherUnfoldAnimationController != null) {
- mLauncherUnfoldAnimationController.onResume();
- }
- }
-
- @Override
- protected void onPause() {
- if (mLauncherUnfoldAnimationController != null) {
- mLauncherUnfoldAnimationController.onPause();
- }
-
- super.onPause();
}
@Override
@@ -281,10 +231,6 @@
public void onDestroy() {
super.onDestroy();
mHotseatPredictionController.destroy();
-
- if (mLauncherUnfoldAnimationController != null) {
- mLauncherUnfoldAnimationController.onDestroy();
- }
}
@Override
diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
index c5ab84d..47d3580 100644
--- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
+++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
@@ -37,26 +37,23 @@
private static final float MAX_WIDTH_INSET_FRACTION = 0.15f;
private final Launcher mLauncher;
- private final UnfoldTransitionProgressProvider mUnfoldTransitionProgressProvider;
- private final UnfoldMoveFromCenterWorkspaceAnimator mMoveFromCenterWorkspaceAnimation;
@Nullable
private HorizontalInsettableView mQsbInsettable;
- private final AnimationListener mAnimationListener = new AnimationListener();
-
- private boolean mIsTransitionRunning = false;
- private boolean mIsReadyToPlayAnimation = false;
+ private final ScopedUnfoldTransitionProgressProvider mProgressProvider;
public LauncherUnfoldAnimationController(
Launcher launcher,
WindowManager windowManager,
UnfoldTransitionProgressProvider unfoldTransitionProgressProvider) {
mLauncher = launcher;
- mUnfoldTransitionProgressProvider = unfoldTransitionProgressProvider;
- mMoveFromCenterWorkspaceAnimation = new UnfoldMoveFromCenterWorkspaceAnimator(launcher,
- windowManager);
- mUnfoldTransitionProgressProvider.addCallback(mAnimationListener);
+ mProgressProvider = new ScopedUnfoldTransitionProgressProvider(
+ unfoldTransitionProgressProvider);
+
+ mProgressProvider.addCallback(new UnfoldMoveFromCenterWorkspaceAnimator(launcher,
+ windowManager));
+ mProgressProvider.addCallback(new QsbAnimationListener());
}
/**
@@ -73,7 +70,7 @@
@Override
public boolean onPreDraw() {
if (obs.isAlive()) {
- onPreDrawAfterResume();
+ mProgressProvider.setReadyToHandleTransition(true);
obs.removeOnPreDrawListener(this);
}
return true;
@@ -85,12 +82,7 @@
* Called when launcher activity is paused
*/
public void onPause() {
- if (mIsTransitionRunning) {
- mIsTransitionRunning = false;
- mAnimationListener.onTransitionFinished();
- }
-
- mIsReadyToPlayAnimation = false;
+ mProgressProvider.setReadyToHandleTransition(false);
mQsbInsettable = null;
}
@@ -98,48 +90,24 @@
* Called when launcher activity is destroyed
*/
public void onDestroy() {
- mUnfoldTransitionProgressProvider.removeCallback(mAnimationListener);
+ mProgressProvider.destroy();
}
- /**
- * Called after performing layouting of the views after configuration change
- */
- private void onPreDrawAfterResume() {
- mIsReadyToPlayAnimation = true;
-
- if (mIsTransitionRunning) {
- mMoveFromCenterWorkspaceAnimation.onTransitionStarted();
- }
- }
-
- private class AnimationListener implements TransitionProgressListener {
+ private class QsbAnimationListener implements TransitionProgressListener {
@Override
public void onTransitionStarted() {
- mIsTransitionRunning = true;
-
- if (mIsReadyToPlayAnimation) {
- mMoveFromCenterWorkspaceAnimation.onTransitionStarted();
- }
}
@Override
public void onTransitionFinished() {
- if (mIsReadyToPlayAnimation) {
- mMoveFromCenterWorkspaceAnimation.onTransitionFinished();
-
- if (mQsbInsettable != null) {
- mQsbInsettable.setHorizontalInsets(0);
- }
+ if (mQsbInsettable != null) {
+ mQsbInsettable.setHorizontalInsets(0);
}
-
- mIsTransitionRunning = false;
}
@Override
public void onTransitionProgress(float progress) {
- mMoveFromCenterWorkspaceAnimation.onTransitionProgress(progress);
-
if (mQsbInsettable != null) {
float insetPercentage = comp(progress) * MAX_WIDTH_INSET_FRACTION;
mQsbInsettable.setHorizontalInsets(insetPercentage);
diff --git a/quickstep/src/com/android/quickstep/util/LauncherViewsMoveFromCenterTranslationApplier.java b/quickstep/src/com/android/quickstep/util/LauncherViewsMoveFromCenterTranslationApplier.java
new file mode 100644
index 0000000..effdfdd
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/LauncherViewsMoveFromCenterTranslationApplier.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 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.annotation.NonNull;
+import android.view.View;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.widget.NavigableAppWidgetHostView;
+import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator.TranslationApplier;
+
+/**
+ * Class that allows to set translations for move from center animation independently
+ * from other translations for certain launcher views
+ */
+public class LauncherViewsMoveFromCenterTranslationApplier implements TranslationApplier {
+
+ @Override
+ public void apply(@NonNull View view, float x, float y) {
+ if (view instanceof NavigableAppWidgetHostView) {
+ ((NavigableAppWidgetHostView) view).setTranslationForMoveFromCenterAnimation(x, y);
+ } else if (view instanceof BubbleTextView) {
+ ((BubbleTextView) view).setTranslationForMoveFromCenterAnimation(x, y);
+ } else if (view instanceof FolderIcon) {
+ ((FolderIcon) view).setTranslationForMoveFromCenterAnimation(x, y);
+ } else {
+ view.setTranslationX(x);
+ view.setTranslationY(y);
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/ScopedUnfoldTransitionProgressProvider.java b/quickstep/src/com/android/quickstep/util/ScopedUnfoldTransitionProgressProvider.java
new file mode 100644
index 0000000..2ef311f
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/ScopedUnfoldTransitionProgressProvider.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2021 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.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Manages progress listeners that can have smaller lifespan than the unfold animation.
+ * Allows to limit getting transition updates to only when
+ * {@link ScopedUnfoldTransitionProgressProvider#setReadyToHandleTransition} is called
+ * with readyToHandleTransition = true
+ *
+ * If the transition has already started by the moment when the clients are ready to play
+ * the transition then it will report transition started callback and current animation progress.
+ */
+public final class ScopedUnfoldTransitionProgressProvider implements
+ UnfoldTransitionProgressProvider, TransitionProgressListener {
+
+ private static final float PROGRESS_UNSET = -1f;
+
+ @Nullable
+ private UnfoldTransitionProgressProvider mSource;
+
+ private final List<TransitionProgressListener> mListeners = new ArrayList<>();
+
+ private boolean mIsReadyToHandleTransition;
+ private boolean mIsTransitionRunning;
+ private float mLastTransitionProgress = PROGRESS_UNSET;
+
+ public ScopedUnfoldTransitionProgressProvider() {
+ this(null);
+ }
+
+ public ScopedUnfoldTransitionProgressProvider(@Nullable UnfoldTransitionProgressProvider
+ source) {
+ setSourceProvider(source);
+ }
+
+ /**
+ * Sets the source for the unfold transition progress updates,
+ * it replaces current provider if it is already set
+ * @param provider transition provider that emits transition progress updates
+ */
+ public void setSourceProvider(@Nullable UnfoldTransitionProgressProvider provider) {
+ if (mSource != null) {
+ mSource.removeCallback(this);
+ }
+
+ if (provider != null) {
+ mSource = provider;
+ mSource.addCallback(this);
+ }
+ }
+
+ /**
+ * Allows to notify this provide whether the listeners can play the transition or not.
+ * Call this method with readyToHandleTransition = true when all listeners
+ * are ready to consume the transition progress events.
+ * Call it with readyToHandleTransition = false when listeners can't process the events.
+ */
+ public void setReadyToHandleTransition(boolean isReadyToHandleTransition) {
+ if (mIsTransitionRunning) {
+ if (mIsReadyToHandleTransition) {
+ mListeners.forEach(TransitionProgressListener::onTransitionStarted);
+
+ if (mLastTransitionProgress != PROGRESS_UNSET) {
+ mListeners.forEach(listener ->
+ listener.onTransitionProgress(mLastTransitionProgress));
+ }
+ } else {
+ mIsTransitionRunning = false;
+ mListeners.forEach(TransitionProgressListener::onTransitionFinished);
+ }
+ }
+
+ mIsReadyToHandleTransition = isReadyToHandleTransition;
+ }
+
+ @Override
+ public void addCallback(@NonNull TransitionProgressListener listener) {
+ mListeners.add(listener);
+ }
+
+ @Override
+ public void removeCallback(@NonNull TransitionProgressListener listener) {
+ mListeners.remove(listener);
+ }
+
+ @Override
+ public void destroy() {
+ mSource.removeCallback(this);
+ }
+
+ @Override
+ public void onTransitionStarted() {
+ this.mIsTransitionRunning = true;
+ if (mIsReadyToHandleTransition) {
+ mListeners.forEach(TransitionProgressListener::onTransitionStarted);
+ }
+ }
+
+ @Override
+ public void onTransitionProgress(float progress) {
+ if (mIsReadyToHandleTransition) {
+ mListeners.forEach(listener -> listener.onTransitionProgress(progress));
+ }
+
+ mLastTransitionProgress = progress;
+ }
+
+ @Override
+ public void onTransitionFinished() {
+ if (mIsReadyToHandleTransition) {
+ mListeners.forEach(TransitionProgressListener::onTransitionFinished);
+ }
+
+ mIsTransitionRunning = false;
+ mLastTransitionProgress = PROGRESS_UNSET;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
index 482092d..95403b2 100644
--- a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
@@ -15,20 +15,16 @@
*/
package com.android.quickstep.util;
-import android.annotation.NonNull;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
-import com.android.launcher3.BubbleTextView;
import com.android.launcher3.CellLayout;
import com.android.launcher3.Hotseat;
import com.android.launcher3.Launcher;
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Workspace;
-import com.android.launcher3.widget.NavigableAppWidgetHostView;
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator;
-import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator.TranslationApplier;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import java.util.HashMap;
@@ -49,7 +45,7 @@
public UnfoldMoveFromCenterWorkspaceAnimator(Launcher launcher, WindowManager windowManager) {
mLauncher = launcher;
mMoveFromCenterAnimation = new UnfoldMoveFromCenterAnimator(windowManager,
- new WorkspaceViewsTranslationApplier());
+ new LauncherViewsMoveFromCenterTranslationApplier());
}
@Override
@@ -122,19 +118,4 @@
view.setClipChildren(originalClipChildren);
}
}
-
- private static class WorkspaceViewsTranslationApplier implements TranslationApplier {
-
- @Override
- public void apply(@NonNull View view, float x, float y) {
- if (view instanceof NavigableAppWidgetHostView) {
- ((NavigableAppWidgetHostView) view).setTranslationForMoveFromCenterAnimation(x, y);
- } else if (view instanceof BubbleTextView) {
- ((BubbleTextView) view).setTranslationForMoveFromCenterAnimation(x, y);
- } else {
- view.setTranslationX(x);
- view.setTranslationY(y);
- }
- }
- }
}
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index e52d1be..54920e1 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -90,6 +90,8 @@
private final PointF mTranslationForReorderBounce = new PointF(0, 0);
private final PointF mTranslationForReorderPreview = new PointF(0, 0);
+ private float mTranslationXForTaskbarAlignmentAnimation = 0f;
+
private final PointF mTranslationForMoveFromCenterAnimation = new PointF(0, 0);
private float mScaleForReorderBounce = 1f;
@@ -825,7 +827,8 @@
private void updateTranslation() {
super.setTranslationX(mTranslationForReorderBounce.x + mTranslationForReorderPreview.x
- + mTranslationForMoveFromCenterAnimation.x);
+ + mTranslationForMoveFromCenterAnimation.x
+ + mTranslationXForTaskbarAlignmentAnimation);
super.setTranslationY(mTranslationForReorderBounce.y + mTranslationForReorderPreview.y
+ mTranslationForMoveFromCenterAnimation.y);
}
@@ -860,11 +863,29 @@
return mScaleForReorderBounce;
}
+ /**
+ * Sets translation values for move from center animation
+ */
public void setTranslationForMoveFromCenterAnimation(float x, float y) {
mTranslationForMoveFromCenterAnimation.set(x, y);
updateTranslation();
}
+ /**
+ * Sets translationX for taskbar to launcher alignment animation
+ */
+ public void setTranslationXForTaskbarAlignmentAnimation(float translationX) {
+ mTranslationXForTaskbarAlignmentAnimation = translationX;
+ updateTranslation();
+ }
+
+ /**
+ * Returns translationX value for taskbar to launcher alignment animation
+ */
+ public float getTranslationXForTaskbarAlignmentAnimation() {
+ return mTranslationXForTaskbarAlignmentAnimation;
+ }
+
public View getView() {
return this;
}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 60d8cdb..439df80 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -132,6 +132,9 @@
private Rect mTouchArea = new Rect();
+ private final PointF mTranslationForMoveFromCenterAnimation = new PointF(0, 0);
+ private float mTranslationXForTaskbarAlignmentAnimation = 0f;
+
private final PointF mTranslationForReorderBounce = new PointF(0, 0);
private final PointF mTranslationForReorderPreview = new PointF(0, 0);
private float mScaleForReorderBounce = 1f;
@@ -765,8 +768,11 @@
}
private void updateTranslation() {
- super.setTranslationX(mTranslationForReorderBounce.x + mTranslationForReorderPreview.x);
- super.setTranslationY(mTranslationForReorderBounce.y + mTranslationForReorderPreview.y);
+ super.setTranslationX(mTranslationForReorderBounce.x + mTranslationForReorderPreview.x
+ + mTranslationForMoveFromCenterAnimation.x
+ + mTranslationXForTaskbarAlignmentAnimation);
+ super.setTranslationY(mTranslationForReorderBounce.y + mTranslationForReorderPreview.y
+ + mTranslationForMoveFromCenterAnimation.y);
}
public void setReorderBounceOffset(float x, float y) {
@@ -778,6 +784,29 @@
offset.set(mTranslationForReorderBounce);
}
+ /**
+ * Sets translationX value for taskbar to launcher alignment animation
+ */
+ public void setTranslationForTaskbarAlignmentAnimation(float translationX) {
+ mTranslationXForTaskbarAlignmentAnimation = translationX;
+ updateTranslation();
+ }
+
+ /**
+ * Returns translation values for taskbar to launcher alignment animation
+ */
+ public float getTranslationXForTaskbarAlignmentAnimation() {
+ return mTranslationXForTaskbarAlignmentAnimation;
+ }
+
+ /**
+ * Sets translation values for move from center animation
+ */
+ public void setTranslationForMoveFromCenterAnimation(float x, float y) {
+ mTranslationForMoveFromCenterAnimation.set(x, y);
+ updateTranslation();
+ }
+
@Override
public void setReorderPreviewOffset(float x, float y) {
mTranslationForReorderPreview.set(x, y);