Merge "Add taskbar icons unfold animation" into sc-v2-dev

This commit is contained in:
Nick Chameyev
2021-09-03 11:19:22 +00:00
committed by Android (Google) Code Review
13 changed files with 484 additions and 135 deletions
@@ -35,6 +35,8 @@ import android.content.Context;
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.SystemUiProxy;
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.quickstep.views.SplitPlaceholderView;
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 abstract class BaseQuickstepLauncher extends Launcher
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 @@ public abstract class BaseQuickstepLauncher extends Launcher
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 @@ public abstract class BaseQuickstepLauncher extends Launcher
mTaskbarManager.clearLauncher(this);
}
resetServiceBindRetryState();
if (mLauncherUnfoldAnimationController != null) {
mLauncherUnfoldAnimationController.onDestroy();
}
super.onDestroy();
}
@@ -334,6 +372,28 @@ public abstract class BaseQuickstepLauncher extends Launcher
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 @@ public abstract class BaseQuickstepLauncher extends Launcher
return mTaskbarStateHandler;
}
@Nullable
public UnfoldTransitionProgressProvider getUnfoldTransitionProgressProvider() {
return mUnfoldTransitionProgressProvider;
}
@Override
public boolean supportsAdaptiveIconAnimation(View clickedView) {
return mAppTransitionManager.hasControlRemoteAppTransitionPermission()
@@ -62,6 +62,7 @@ import com.android.launcher3.util.ViewCache;
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 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
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 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
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 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
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() {
@@ -31,6 +31,7 @@ public class TaskbarControllers {
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 @@ public class TaskbarControllers {
RotationButtonController rotationButtonController,
TaskbarDragLayerController taskbarDragLayerController,
TaskbarViewController taskbarViewController,
TaskbarUnfoldAnimationController taskbarUnfoldAnimationController,
TaskbarKeyguardController taskbarKeyguardController,
StashedHandleViewController stashedHandleViewController,
TaskbarStashController taskbarStashController,
@@ -57,6 +59,7 @@ public class TaskbarControllers {
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 @@ public class TaskbarControllers {
}
taskbarDragLayerController.init(this);
taskbarViewController.init(this);
taskbarUnfoldAnimationController.init(this);
taskbarKeyguardController.init(navbarButtonsViewController);
stashedHandleViewController.init(this);
taskbarStashController.init(this);
@@ -89,6 +93,7 @@ public class TaskbarControllers {
rotationButtonController.onDestroy();
taskbarDragLayerController.onDestroy();
taskbarKeyguardController.onDestroy();
taskbarUnfoldAnimationController.onDestroy();
taskbarViewController.onDestroy();
stashedHandleViewController.onDestroy();
}
@@ -42,6 +42,7 @@ import com.android.quickstep.SysUINavigationMode;
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 @@ public class TaskbarManager implements DisplayController.DisplayInfoChangeListen
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 class TaskbarManager implements DisplayController.DisplayInfoChangeListen
*/
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 @@ public class TaskbarManager implements DisplayController.DisplayInfoChangeListen
if (mTaskbarActivityContext != null) {
mTaskbarActivityContext.setUIController(TaskbarUIController.DEFAULT);
}
mUnfoldProgressProvider.setSourceProvider(null);
}
}
@@ -153,8 +162,8 @@ public class TaskbarManager implements DisplayController.DisplayInfoChangeListen
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(
@@ -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);
}
}
}
@@ -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 @@ public class TaskbarViewController {
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 @@ public class TaskbarViewController {
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 @@ public class TaskbarViewController {
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();
}
};
}
@@ -36,13 +36,9 @@ import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SY
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;
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 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
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 class QuickstepLauncher extends BaseQuickstepLauncher {
public void onDestroy() {
super.onDestroy();
mHotseatPredictionController.destroy();
if (mLauncherUnfoldAnimationController != null) {
mLauncherUnfoldAnimationController.onDestroy();
}
}
@Override
@@ -37,26 +37,23 @@ public class LauncherUnfoldAnimationController {
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 @@ public class LauncherUnfoldAnimationController {
@Override
public boolean onPreDraw() {
if (obs.isAlive()) {
onPreDrawAfterResume();
mProgressProvider.setReadyToHandleTransition(true);
obs.removeOnPreDrawListener(this);
}
return true;
@@ -85,12 +82,7 @@ public class LauncherUnfoldAnimationController {
* 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 @@ public class LauncherUnfoldAnimationController {
* 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);
@@ -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);
}
}
}
@@ -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;
}
}
@@ -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 class UnfoldMoveFromCenterWorkspaceAnimator
public UnfoldMoveFromCenterWorkspaceAnimator(Launcher launcher, WindowManager windowManager) {
mLauncher = launcher;
mMoveFromCenterAnimation = new UnfoldMoveFromCenterAnimator(windowManager,
new WorkspaceViewsTranslationApplier());
new LauncherViewsMoveFromCenterTranslationApplier());
}
@Override
@@ -122,19 +118,4 @@ public class UnfoldMoveFromCenterWorkspaceAnimator
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);
}
}
}
}
+22 -1
View File
@@ -90,6 +90,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
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 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
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 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
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;
}
@@ -132,6 +132,9 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
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 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
}
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 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
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);