Merge "Updating taskbar icon alignment state" into sc-v2-dev

This commit is contained in:
Sunny Goyal 2021-06-16 22:08:07 +00:00 committed by Android (Google) Code Review
commit e900ec68d0
9 changed files with 177 additions and 143 deletions

View File

@ -15,27 +15,29 @@
*/ */
package com.android.launcher3.taskbar; package com.android.launcher3.taskbar;
import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME; import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME;
import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_LAUNCHER_STATE;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.graphics.Rect; import android.graphics.Rect;
import android.view.MotionEvent; import android.view.MotionEvent;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherState;
import com.android.launcher3.QuickstepTransitionManager; import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.util.MultiValueAlpha; import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.quickstep.AnimatedFloat; import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.RecentsAnimationCallbacks;
import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
import com.android.quickstep.RecentsAnimationController;
import com.android.systemui.shared.recents.model.ThumbnailData;
/** /**
@ -51,12 +53,19 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
final TaskbarDragLayer mTaskbarDragLayer; final TaskbarDragLayer mTaskbarDragLayer;
final TaskbarView mTaskbarView; final TaskbarView mTaskbarView;
private final AnimatedFloat mIconAlignmentForResumedState =
new AnimatedFloat(this::onIconAlignmentRatioChanged);
private final AnimatedFloat mIconAlignmentForGestureState =
new AnimatedFloat(this::onIconAlignmentRatioChanged);
private AnimatedFloat mTaskbarBackgroundAlpha; private AnimatedFloat mTaskbarBackgroundAlpha;
private AlphaProperty mIconAlphaForHome; private AlphaProperty mIconAlphaForHome;
private @Nullable Animator mAnimator;
private boolean mIsAnimatingToLauncher; private boolean mIsAnimatingToLauncher;
private TaskbarKeyguardController mKeyguardController; private TaskbarKeyguardController mKeyguardController;
private LauncherState mTargetStateOverride = null;
private TaskbarControllers mControllers;
public LauncherTaskbarUIController( public LauncherTaskbarUIController(
BaseQuickstepLauncher launcher, TaskbarActivityContext context) { BaseQuickstepLauncher launcher, TaskbarActivityContext context) {
mContext = context; mContext = context;
@ -67,7 +76,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
mTaskbarStateHandler = mLauncher.getTaskbarStateHandler(); mTaskbarStateHandler = mLauncher.getTaskbarStateHandler();
mHotseatController = new TaskbarHotseatController( mHotseatController = new TaskbarHotseatController(
mLauncher, mTaskbarView::updateHotseatItems); mLauncher, mTaskbarView::updateHotseatItems);
} }
@Override @Override
@ -77,21 +85,17 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
MultiValueAlpha taskbarIconAlpha = taskbarControllers.taskbarViewController MultiValueAlpha taskbarIconAlpha = taskbarControllers.taskbarViewController
.getTaskbarIconAlpha(); .getTaskbarIconAlpha();
mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME); mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME);
mTaskbarStateHandler.setAnimationController(taskbarIconAlpha.getProperty( mControllers = taskbarControllers;
ALPHA_INDEX_LAUNCHER_STATE));
mHotseatController.init(); mHotseatController.init();
setTaskbarViewVisible(!mLauncher.hasBeenResumed());
mLauncher.setTaskbarUIController(this); mLauncher.setTaskbarUIController(this);
mKeyguardController = taskbarControllers.taskbarKeyguardController; mKeyguardController = taskbarControllers.taskbarKeyguardController;
onLauncherResumedOrPaused(mLauncher.hasBeenResumed());
mIconAlignmentForResumedState.finishAnimation();
} }
@Override @Override
protected void onDestroy() { protected void onDestroy() {
if (mAnimator != null) {
// End this first, in case it relies on properties that are about to be cleaned up.
mAnimator.end();
}
mTaskbarStateHandler.setAnimationController(null);
mHotseatController.cleanup(); mHotseatController.cleanup();
setTaskbarViewVisible(true); setTaskbarViewVisible(true);
mLauncher.getHotseat().setIconsAlpha(1f); mLauncher.getHotseat().setIconsAlpha(1f);
@ -100,7 +104,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
@Override @Override
protected boolean isTaskbarTouchable() { protected boolean isTaskbarTouchable() {
return !mIsAnimatingToLauncher; return !mIsAnimatingToLauncher && mTargetStateOverride == null;
} }
@Override @Override
@ -128,63 +132,82 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
} }
} }
long duration = QuickstepTransitionManager.CONTENT_ALPHA_DURATION; ObjectAnimator anim = mIconAlignmentForResumedState.animateToValue(
if (mAnimator != null) { getCurrentIconAlignmentRatio(), isResumed ? 1 : 0)
mAnimator.cancel(); .setDuration(QuickstepTransitionManager.CONTENT_ALPHA_DURATION);
}
if (isResumed) { anim.addListener(AnimatorListeners.forEndCallback(() -> mIsAnimatingToLauncher = false));
mAnimator = createAnimToLauncher(mLauncher.getStateManager().getState(), duration); anim.start();
} else { mIsAnimatingToLauncher = isResumed;
mAnimator = createAnimToApp(duration);
}
mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mAnimator = null;
}
});
mAnimator.start();
} }
/** /**
* Create Taskbar animation when going from an app to Launcher. * Create Taskbar animation when going from an app to Launcher as part of recents transition.
* @param toState If known, the state we will end up in when reaching Launcher. * @param toState If known, the state we will end up in when reaching Launcher.
* TODO: Move this and createAnimToApp to TaskbarStateHandler using the BACKGROUND state * @param callbacks callbacks to track the recents animation lifecycle. The state change is
* automatically reset once the recents animation finishes
*/ */
public Animator createAnimToLauncher(@NonNull LauncherState toState, long duration) { public Animator createAnimToLauncher(@NonNull LauncherState toState,
PendingAnimation anim = new PendingAnimation(duration); @NonNull RecentsAnimationCallbacks callbacks,
mTaskbarStateHandler.setState(toState, anim); long duration) {
ObjectAnimator animator = mIconAlignmentForGestureState
anim.setFloat(mTaskbarBackgroundAlpha, AnimatedFloat.VALUE, 0, LINEAR); .animateToValue(mIconAlignmentForGestureState.value, 1)
mTaskbarView.alignIconsWithLauncher(mLauncher.getDeviceProfile(), anim); .setDuration(duration);
animator.addListener(new AnimatorListenerAdapter() {
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mIsAnimatingToLauncher = true;
}
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
mIsAnimatingToLauncher = false; mTargetStateOverride = null;
setTaskbarViewVisible(false);
} }
});
return anim.buildAnim();
}
private Animator createAnimToApp(long duration) {
PendingAnimation anim = new PendingAnimation(duration);
anim.setFloat(mTaskbarBackgroundAlpha, AnimatedFloat.VALUE, 1, LINEAR);
anim.addListener(AnimatorListeners.forEndCallback(mTaskbarView.resetIconPosition(anim)));
anim.addListener(new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationStart(Animator animation) { public void onAnimationStart(Animator animation) {
setTaskbarViewVisible(true); mTargetStateOverride = toState;
} }
}); });
return anim.buildAnim(); callbacks.addListener(new RecentsAnimationListener() {
@Override
public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
endGestureStateOverride();
}
@Override
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
endGestureStateOverride();
}
private void endGestureStateOverride() {
callbacks.removeListener(this);
mIconAlignmentForGestureState
.animateToValue(mIconAlignmentForGestureState.value, 0)
.start();
}
});
return animator;
}
private float getCurrentIconAlignmentRatio() {
return Math.max(mIconAlignmentForResumedState.value, mIconAlignmentForGestureState.value);
}
private void onIconAlignmentRatioChanged() {
if (mControllers == null) {
return;
}
float alignment = getCurrentIconAlignmentRatio();
mControllers.taskbarViewController.setLauncherIconAlignment(
alignment, mLauncher.getDeviceProfile());
mTaskbarBackgroundAlpha.updateValue(1 - alignment);
LauncherState state = mTargetStateOverride != null ? mTargetStateOverride
: mLauncher.getStateManager().getState();
if ((state.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
// If the hotseat icons are visible, then switch taskbar in last frame
setTaskbarViewVisible(alignment < 1);
} else {
mLauncher.getHotseat().setIconsAlpha(1);
mIconAlphaForHome.setValue(1 - alignment);
}
} }
/** /**

View File

@ -17,7 +17,6 @@ package com.android.launcher3.taskbar;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_BOTTOM_TAPPABLE_ELEMENT; import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
@ -93,6 +92,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
private final ViewCache mViewCache = new ViewCache(); private final ViewCache mViewCache = new ViewCache();
private final boolean mIsSafeModeEnabled; private final boolean mIsSafeModeEnabled;
private boolean mIsDestroyed = false;
public TaskbarActivityContext(Context windowContext, DeviceProfile dp, public TaskbarActivityContext(Context windowContext, DeviceProfile dp,
TaskbarNavButtonController buttonController) { TaskbarNavButtonController buttonController) {
@ -208,6 +208,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
* Called when this instance of taskbar is no longer needed * Called when this instance of taskbar is no longer needed
*/ */
public void onDestroy() { public void onDestroy() {
mIsDestroyed = true;
setUIController(TaskbarUIController.DEFAULT); setUIController(TaskbarUIController.DEFAULT);
mControllers.onDestroy(); mControllers.onDestroy();
mWindowManager.removeViewImmediate(mDragLayer); mWindowManager.removeViewImmediate(mDragLayer);
@ -252,7 +253,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
* Updates the TaskbarContainer height (pass deviceProfile.taskbarSize to reset). * Updates the TaskbarContainer height (pass deviceProfile.taskbarSize to reset).
*/ */
public void setTaskbarWindowHeight(int height) { public void setTaskbarWindowHeight(int height) {
if (mWindowLayoutParams.height == height) { if (mWindowLayoutParams.height == height || mIsDestroyed) {
return; return;
} }
if (height != MATCH_PARENT) { if (height != MATCH_PARENT) {

View File

@ -18,45 +18,33 @@ package com.android.launcher3.taskbar;
import static com.android.launcher3.LauncherState.TASKBAR; import static com.android.launcher3.LauncherState.TASKBAR;
import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.LINEAR;
import androidx.annotation.Nullable;
import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter; import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.quickstep.AnimatedFloat; import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.SystemUiProxy; import com.android.quickstep.SystemUiProxy;
/** /**
* StateHandler to animate Taskbar according to Launcher's state machine. Does nothing if Taskbar * StateHandler to animate Taskbar according to Launcher's state machine.
* isn't present (i.e. {@link #setAnimationController} is never called).
*/ */
public class TaskbarStateHandler implements StateManager.StateHandler<LauncherState> { public class TaskbarStateHandler implements StateManager.StateHandler<LauncherState> {
private final BaseQuickstepLauncher mLauncher; private final BaseQuickstepLauncher mLauncher;
// Contains Taskbar-related properties we should aniamte. If null, don't do anything.
private @Nullable MultiValueAlpha.AlphaProperty mTaskbarAlpha = null;
private AnimatedFloat mNavbarButtonAlpha = new AnimatedFloat(this::updateNavbarButtonAlpha); private AnimatedFloat mNavbarButtonAlpha = new AnimatedFloat(this::updateNavbarButtonAlpha);
public TaskbarStateHandler(BaseQuickstepLauncher launcher) { public TaskbarStateHandler(BaseQuickstepLauncher launcher) {
mLauncher = launcher; mLauncher = launcher;
} }
public void setAnimationController(MultiValueAlpha.AlphaProperty taskbarAlpha) {
mTaskbarAlpha = taskbarAlpha;
// Reapply state.
setState(mLauncher.getStateManager().getState());
updateNavbarButtonAlpha();
}
@Override @Override
public void setState(LauncherState state) { public void setState(LauncherState state) {
setState(state, PropertySetter.NO_ANIM_PROPERTY_SETTER); setState(state, PropertySetter.NO_ANIM_PROPERTY_SETTER);
// Force update the alpha in case it was not initialized properly
updateNavbarButtonAlpha();
} }
@Override @Override
@ -69,12 +57,7 @@ public class TaskbarStateHandler implements StateManager.StateHandler<LauncherSt
* Sets the provided state * Sets the provided state
*/ */
public void setState(LauncherState toState, PropertySetter setter) { public void setState(LauncherState toState, PropertySetter setter) {
if (mTaskbarAlpha == null) {
return;
}
boolean isTaskbarVisible = (toState.getVisibleElements(mLauncher) & TASKBAR) != 0; boolean isTaskbarVisible = (toState.getVisibleElements(mLauncher) & TASKBAR) != 0;
setter.setFloat(mTaskbarAlpha, MultiValueAlpha.VALUE, isTaskbarVisible ? 1f : 0f, LINEAR);
// Make the nav bar visible in states that taskbar isn't visible. // Make the nav bar visible in states that taskbar isn't visible.
// TODO: We should draw our own handle instead of showing the nav bar. // TODO: We should draw our own handle instead of showing the nav bar.
float navbarButtonAlpha = isTaskbarVisible ? 0f : 1f; float navbarButtonAlpha = isTaskbarVisible ? 0f : 1f;

View File

@ -15,11 +15,6 @@
*/ */
package com.android.launcher3.taskbar; 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.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Canvas; import android.graphics.Canvas;
@ -34,10 +29,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.android.launcher3.BubbleTextView; import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable; import com.android.launcher3.Insettable;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfo;
@ -105,51 +98,6 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
mIconLongClickListener = mControllerCallbacks.getOnLongClickListener(); mIconLongClickListener = mControllerCallbacks.getOnLongClickListener();
} }
/**
* Aligns the icons in the taskbar to that of Launcher.
*/
public void alignIconsWithLauncher(DeviceProfile launcherDp, PropertySetter setter) {
Rect hotseatPadding = launcherDp.getHotseatLayoutPadding(getContext());
float scaleUp = ((float) launcherDp.iconSizePx)
/ mActivityContext.getDeviceProfile().iconSizePx;
int hotseatCellSize =
(launcherDp.availableWidthPx - hotseatPadding.left - hotseatPadding.right)
/ launcherDp.numShownHotseatIcons;
int offsetY = launcherDp.getTaskbarOffsetY();
setter.setFloat(this, VIEW_TRANSLATE_Y, -offsetY, LINEAR);
mActivityContext.setTaskbarWindowHeight(
mActivityContext.getDeviceProfile().taskbarSize + offsetY);
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
ItemInfo info = (ItemInfo) child.getTag();
setter.setFloat(child, SCALE_PROPERTY, scaleUp, LINEAR);
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);
}
}
/**
* Aligns the icons in the taskbar to that of Launcher.
* @return a callback to be executed at the end of the setter
*/
public Runnable resetIconPosition(PropertySetter setter) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
setter.setFloat(child, SCALE_PROPERTY, 1, LINEAR);
setter.setFloat(child, VIEW_TRANSLATE_X, 0, LINEAR);
}
setter.setFloat(this, VIEW_TRANSLATE_Y, 0, LINEAR);
return () -> mActivityContext.setTaskbarWindowHeight(
mActivityContext.getDeviceProfile().taskbarSize);
}
private void removeAndRecycle(View view) { private void removeAndRecycle(View view) {
removeView(view); removeView(view);
view.setOnClickListener(null); view.setOnClickListener(null);
@ -195,6 +143,7 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
// so if the info changes we need to reinflate. This should only happen if a new // so if the info changes we need to reinflate. This should only happen if a new
// folder is dragged to the position that another folder previously existed. // folder is dragged to the position that another folder previously existed.
removeAndRecycle(hotseatView); removeAndRecycle(hotseatView);
hotseatView = null;
} else { } else {
// View found // View found
break; break;

View File

@ -15,19 +15,29 @@
*/ */
package com.android.launcher3.taskbar; 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.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import android.graphics.Rect;
import android.view.View; import android.view.View;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.MultiValueAlpha; import com.android.launcher3.util.MultiValueAlpha;
/** /**
* Handles properties/data collection, then passes the results to TaskbarView to render. * Handles properties/data collection, then passes the results to TaskbarView to render.
*/ */
public class TaskbarViewController { public class TaskbarViewController {
private static final Runnable NO_OP = () -> { };
public static final int ALPHA_INDEX_HOME = 0; public static final int ALPHA_INDEX_HOME = 0;
public static final int ALPHA_INDEX_LAUNCHER_STATE = 1; public static final int ALPHA_INDEX_IME = 1;
public static final int ALPHA_INDEX_IME = 2; public static final int ALPHA_INDEX_KEYGUARD = 2;
public static final int ALPHA_INDEX_KEYGUARD = 3;
private final TaskbarActivityContext mActivity; private final TaskbarActivityContext mActivity;
private final TaskbarView mTaskbarView; private final TaskbarView mTaskbarView;
@ -36,10 +46,15 @@ public class TaskbarViewController {
// Initialized in init. // Initialized in init.
private TaskbarControllers mControllers; private TaskbarControllers mControllers;
// Animation to align icons with Launcher, created lazily. This allows the controller to be
// active only during the animation and does not need to worry about layout changes.
private AnimatorPlaybackController mIconAlignControllerLazy = null;
private Runnable mOnControllerPreCreateCallback = NO_OP;
public TaskbarViewController(TaskbarActivityContext activity, TaskbarView taskbarView) { public TaskbarViewController(TaskbarActivityContext activity, TaskbarView taskbarView) {
mActivity = activity; mActivity = activity;
mTaskbarView = taskbarView; mTaskbarView = taskbarView;
mTaskbarIconAlpha = new MultiValueAlpha(mTaskbarView, 4); mTaskbarIconAlpha = new MultiValueAlpha(mTaskbarView, 3);
mTaskbarIconAlpha.setUpdateVisibility(true); mTaskbarIconAlpha.setUpdateVisibility(true);
} }
@ -71,6 +86,60 @@ public class TaskbarViewController {
mTaskbarView.setClickAndLongClickListenersForIcon(icon); mTaskbarView.setClickAndLongClickListenersForIcon(icon);
} }
/**
* Sets the taskbar icon alignment relative to Launcher hotseat icons
* @param alignmentRatio [0, 1]
* 0 => not aligned
* 1 => fully aligned
*/
public void setLauncherIconAlignment(float alignmentRatio, DeviceProfile launcherDp) {
if (mIconAlignControllerLazy == null) {
mIconAlignControllerLazy = createIconAlignmentController(launcherDp);
}
mIconAlignControllerLazy.setPlayFraction(alignmentRatio);
if (alignmentRatio <= 0 || alignmentRatio >= 1) {
// Cleanup lazy controller so that it is created again in next animation
mIconAlignControllerLazy = null;
}
}
/**
* Creates an animation for aligning the taskbar icons with the provided Launcher device profile
*/
private AnimatorPlaybackController createIconAlignmentController(DeviceProfile launcherDp) {
mOnControllerPreCreateCallback.run();
PendingAnimation setter = new PendingAnimation(100);
Rect hotseatPadding = launcherDp.getHotseatLayoutPadding(mActivity);
float scaleUp = ((float) launcherDp.iconSizePx) / mActivity.getDeviceProfile().iconSizePx;
int hotseatCellSize =
(launcherDp.availableWidthPx - hotseatPadding.left - hotseatPadding.right)
/ launcherDp.numShownHotseatIcons;
int offsetY = launcherDp.getTaskbarOffsetY();
setter.setFloat(mTaskbarView, VIEW_TRANSLATE_Y, -offsetY, LINEAR);
int collapsedHeight = mActivity.getDeviceProfile().taskbarSize;
int expandedHeight = collapsedHeight + offsetY;
setter.addOnFrameListener(anim -> mActivity.setTaskbarWindowHeight(
anim.getAnimatedFraction() > 0 ? expandedHeight : collapsedHeight));
int count = mTaskbarView.getChildCount();
for (int i = 0; i < count; i++) {
View child = mTaskbarView.getChildAt(i);
ItemInfo info = (ItemInfo) child.getTag();
setter.setFloat(child, SCALE_PROPERTY, scaleUp, LINEAR);
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);
}
AnimatorPlaybackController controller = setter.createPlaybackController();
mOnControllerPreCreateCallback = () -> controller.setPlayFraction(0);
return controller;
}
/** /**
* Callbacks for {@link TaskbarView} to interact with its controller. * Callbacks for {@link TaskbarView} to interact with its controller.
*/ */

View File

@ -1107,7 +1107,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
mActivityRestartListener); mActivityRestartListener);
mParallelRunningAnim = mActivityInterface.getParallelAnimationToLauncher( mParallelRunningAnim = mActivityInterface.getParallelAnimationToLauncher(
mGestureState.getEndTarget(), duration); mGestureState.getEndTarget(), duration,
mTaskAnimationManager.getCurrentCallbacks());
if (mParallelRunningAnim != null) { if (mParallelRunningAnim != null) {
mParallelRunningAnim.start(); mParallelRunningAnim.start();
} }

View File

@ -346,7 +346,8 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
* an optional additional animation with the same duration. * an optional additional animation with the same duration.
*/ */
public @Nullable Animator getParallelAnimationToLauncher( public @Nullable Animator getParallelAnimationToLauncher(
GestureState.GestureEndTarget endTarget, long duration) { GestureState.GestureEndTarget endTarget, long duration,
RecentsAnimationCallbacks callbacks) {
if (endTarget == RECENTS) { if (endTarget == RECENTS) {
ACTIVITY_TYPE activity = getCreatedActivity(); ACTIVITY_TYPE activity = getCreatedActivity();
if (activity == null) { if (activity == null) {

View File

@ -284,14 +284,15 @@ public final class LauncherActivityInterface extends
@Override @Override
public @Nullable Animator getParallelAnimationToLauncher(GestureEndTarget endTarget, public @Nullable Animator getParallelAnimationToLauncher(GestureEndTarget endTarget,
long duration) { long duration, RecentsAnimationCallbacks callbacks) {
LauncherTaskbarUIController uiController = getTaskbarController(); LauncherTaskbarUIController uiController = getTaskbarController();
Animator superAnimator = super.getParallelAnimationToLauncher(endTarget, duration); Animator superAnimator = super.getParallelAnimationToLauncher(
if (uiController == null) { endTarget, duration, callbacks);
if (uiController == null || callbacks == null) {
return superAnimator; return superAnimator;
} }
LauncherState toState = stateFromGestureEndTarget(endTarget); LauncherState toState = stateFromGestureEndTarget(endTarget);
Animator taskbarAnimator = uiController.createAnimToLauncher(toState, duration); Animator taskbarAnimator = uiController.createAnimToLauncher(toState, callbacks, duration);
if (superAnimator == null) { if (superAnimator == null) {
return taskbarAnimator; return taskbarAnimator;
} else { } else {

View File

@ -28,6 +28,7 @@ import android.os.Bundle;
import android.os.SystemProperties; import android.os.SystemProperties;
import android.util.Log; import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread; import androidx.annotation.UiThread;
import com.android.launcher3.Utilities; import com.android.launcher3.Utilities;
@ -261,6 +262,11 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
mLastAppearedTaskTarget = null; mLastAppearedTaskTarget = null;
} }
@Nullable
public RecentsAnimationCallbacks getCurrentCallbacks() {
return mCallbacks;
}
public void dump() { public void dump() {
// TODO // TODO
} }