Loading quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +13 −2 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.Utilities.mapBoundToRange; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.anim.Interpolators.ACCEL_1_5; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5; Loading Loading @@ -184,6 +183,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener public static final int SPLIT_DIVIDER_ANIM_DURATION = 100; public static final int CONTENT_ALPHA_DURATION = 217; public static final int TASKBAR_TO_APP_DURATION = 600; // TODO(b/236145847): Tune TASKBAR_TO_HOME_DURATION to 383 after conflict with unlock animation // is solved. public static final int TASKBAR_TO_HOME_DURATION = 300; protected static final int CONTENT_SCALE_DURATION = 350; protected static final int CONTENT_SCRIM_DURATION = 350; Loading Loading @@ -527,7 +530,15 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener workspace.forEachVisiblePage( view -> viewsToAnimate.add(((CellLayout) view).getShortcutsAndWidgets())); // Do not scale hotseat as a whole when taskbar is present, and scale QSB only if it's // not inline. if (mDeviceProfile.isTaskbarPresent) { if (!mDeviceProfile.isQsbInline) { viewsToAnimate.add(mLauncher.getHotseat().getQsb()); } } else { viewsToAnimate.add(mLauncher.getHotseat()); } viewsToAnimate.forEach(view -> { view.setLayerType(View.LAYER_TYPE_HARDWARE, null); Loading quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +3 −1 Original line number Diff line number Diff line Loading @@ -171,7 +171,9 @@ public class LauncherTaskbarUIController extends TaskbarUIController { isResumed, fromInit, /* startAnimation= */ true, QuickstepTransitionManager.CONTENT_ALPHA_DURATION); !isResumed ? QuickstepTransitionManager.TASKBAR_TO_APP_DURATION : QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION); } @Nullable Loading quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +45 −13 Original line number Diff line number Diff line Loading @@ -19,11 +19,13 @@ import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP; import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE; import static com.android.launcher3.taskbar.TaskbarStashController.TASKBAR_STASH_DURATION; import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME; import static com.android.systemui.animation.Interpolators.EMPHASIZED; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; Loading @@ -31,6 +33,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.LauncherState; import com.android.launcher3.QuickstepTransitionManager; import com.android.launcher3.Utilities; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.util.MultiValueAlpha; Loading @@ -44,7 +47,6 @@ import com.android.systemui.shared.recents.model.ThumbnailData; import java.io.PrintWriter; import java.util.HashMap; import java.util.StringJoiner; import java.util.function.Consumer; import java.util.function.Supplier; /** Loading @@ -53,6 +55,9 @@ import java.util.function.Supplier; */ public class TaskbarLauncherStateController { private static final String TAG = TaskbarLauncherStateController.class.getSimpleName(); private static final boolean DEBUG = false; public static final int FLAG_RESUMED = 1 << 0; public static final int FLAG_RECENTS_ANIMATION_RUNNING = 1 << 1; public static final int FLAG_TRANSITION_STATE_RUNNING = 1 << 2; Loading Loading @@ -99,9 +104,13 @@ import java.util.function.Supplier; } updateStateForFlag(FLAG_TRANSITION_STATE_RUNNING, true); if (!mShouldDelayLauncherStateAnim) { if (toState == LauncherState.NORMAL) { applyState(QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION); } else { applyState(); } } } @Override public void onStateTransitionComplete(LauncherState finalState) { Loading @@ -122,7 +131,12 @@ import java.util.function.Supplier; MultiValueAlpha taskbarIconAlpha = mControllers.taskbarViewController.getTaskbarIconAlpha(); mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME); mIconAlphaForHome.setConsumer( (Consumer<Float>) alpha -> mLauncher.getHotseat().setIconsAlpha(alpha > 0 ? 0 : 1)); alpha -> { mLauncher.getHotseat().setIconsAlpha(alpha > 0 ? 0 : 1); if (mLauncher.getDeviceProfile().isQsbInline) { mLauncher.getHotseat().setQsbAlpha(alpha > 0 ? 0 : 1); } }); mIconAlignmentForResumedState.finishAnimation(); onIconAlignmentRatioChangedForAppAndHomeTransition(); Loading Loading @@ -269,6 +283,11 @@ import java.util.function.Supplier; ObjectAnimator resumeAlignAnim = mIconAlignmentForResumedState .animateToValue(toAlignmentForResumedState) .setDuration(duration); if (DEBUG) { Log.d(TAG, "mIconAlignmentForResumedState - " + mIconAlignmentForResumedState.value + " -> " + toAlignmentForResumedState + ": " + duration); } resumeAlignAnim.addListener(new AnimatorListenerAdapter() { @Override Loading Loading @@ -305,6 +324,11 @@ import java.util.function.Supplier; if (isRecentsAnimationRunning) { gestureAlignAnim.setDuration(duration); } if (DEBUG) { Log.d(TAG, "mIconAlignmentForGestureState - " + mIconAlignmentForGestureState.value + " -> " + toAlignmentForGestureState + ": " + duration); } gestureAlignAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { Loading @@ -330,6 +354,7 @@ import java.util.function.Supplier; .setDuration(duration)); } animatorSet.setInterpolator(EMPHASIZED); if (start) { animatorSet.start(); } Loading Loading @@ -374,6 +399,12 @@ import java.util.function.Supplier; mIconAlignmentForLauncherState.finishAnimation(); animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment) .setDuration(duration)); if (DEBUG) { Log.d(TAG, "mIconAlignmentForLauncherState - " + mIconAlignmentForLauncherState.value + " -> " + toAlignment + ": " + duration); } animatorSet.setInterpolator(EMPHASIZED); } } Loading @@ -396,17 +427,17 @@ import java.util.function.Supplier; onIconAlignmentRatioChanged(this::getCurrentIconAlignmentRatioBetweenAppAndHome); } private void onIconAlignmentRatioChanged(Supplier<Float> alignmentSupplier) { private void onIconAlignmentRatioChanged(Supplier<AnimatedFloat> alignmentSupplier) { if (mControllers == null) { return; } float alignment = alignmentSupplier.get(); AnimatedFloat animatedFloat = alignmentSupplier.get(); float currentValue = mIconAlphaForHome.getValue(); boolean taskbarWillBeVisible = alignment < 1; boolean taskbarWillBeVisible = animatedFloat.value < 1; boolean firstFrameVisChanged = (taskbarWillBeVisible && Float.compare(currentValue, 1) != 0) || (!taskbarWillBeVisible && Float.compare(currentValue, 0) != 0); updateIconAlignment(alignment); updateIconAlignment(animatedFloat.value, animatedFloat.getEndValue()); // Sync the first frame where we swap taskbar and hotseat. if (firstFrameVisChanged && mCanSyncViews && !Utilities.IS_RUNNING_IN_TEST_HARNESS) { Loading @@ -416,21 +447,22 @@ import java.util.function.Supplier; } } private void updateIconAlignment(float alignment) { private void updateIconAlignment(float alignment, Float endAlignment) { mControllers.taskbarViewController.setLauncherIconAlignment( alignment, mLauncher.getDeviceProfile()); alignment, endAlignment, mLauncher.getDeviceProfile()); // Switch taskbar and hotseat in last frame setTaskbarViewVisible(alignment < 1); mControllers.navbarButtonsViewController.updateTaskbarAlignment(alignment); } private float getCurrentIconAlignmentRatioBetweenAppAndHome() { return Math.max(mIconAlignmentForResumedState.value, mIconAlignmentForGestureState.value); private AnimatedFloat getCurrentIconAlignmentRatioBetweenAppAndHome() { return mIconAlignmentForResumedState.value > mIconAlignmentForGestureState.value ? mIconAlignmentForResumedState : mIconAlignmentForGestureState; } private float getCurrentIconAlignmentRatioForLauncherState() { return mIconAlignmentForLauncherState.value; private AnimatedFloat getCurrentIconAlignmentRatioForLauncherState() { return mIconAlignmentForLauncherState; } private void setTaskbarViewVisible(boolean isVisible) { Loading quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +45 −5 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Rect; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; Loading @@ -31,6 +32,7 @@ import androidx.annotation.Nullable; import androidx.core.graphics.ColorUtils; import com.android.launcher3.BubbleTextView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; import com.android.launcher3.R; import com.android.launcher3.Utilities; Loading Loading @@ -78,6 +80,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar // Only non-null when device supports having an All Apps button. private @Nullable AllAppsButton mAllAppsButton; private View mQsb; public TaskbarView(@NonNull Context context) { this(context, null); } Loading Loading @@ -117,6 +121,9 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar new ViewGroup.LayoutParams(mIconTouchSize, mIconTouchSize)); mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding); } // TODO: Disable touch events on QSB otherwise it can crash. mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false); } private int getColorWithGivenLuminance(int color, float luminance) { Loading Loading @@ -166,6 +173,7 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar if (mAllAppsButton != null) { removeView(mAllAppsButton); } removeView(mQsb); for (int i = 0; i < hotseatItemInfos.length; i++) { ItemInfo hotseatItemInfo = hotseatItemInfos[i]; Loading Loading @@ -242,6 +250,11 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar int index = Utilities.isRtl(getResources()) ? 0 : getChildCount(); addView(mAllAppsButton, index); } if (mActivityContext.getDeviceProfile().isQsbInline) { addView(mQsb, Utilities.isRtl(getResources()) ? getChildCount() : 0); // Always set QSB to invisible after re-adding. mQsb.setVisibility(View.INVISIBLE); } mThemeIconsBackground = calculateThemeIconsBackground(); setThemedIconsBackgroundColor(mThemeIconsBackground); Loading Loading @@ -273,7 +286,12 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { int count = getChildCount(); int spaceNeeded = count * (mItemMarginLeftRight * 2 + mIconTouchSize); int countExcludingQsb = count; DeviceProfile deviceProfile = mActivityContext.getDeviceProfile(); if (deviceProfile.isQsbInline) { countExcludingQsb--; } int spaceNeeded = countExcludingQsb * (mItemMarginLeftRight * 2 + mIconTouchSize); int navSpaceNeeded = ApiWrapper.getHotseatEndOffset(getContext()); boolean layoutRtl = isLayoutRtl(); int iconEnd = right - (right - left - spaceNeeded) / 2; Loading @@ -292,11 +310,26 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar mIconLayoutBounds.bottom = mIconLayoutBounds.top + mIconTouchSize; for (int i = count; i > 0; i--) { View child = getChildAt(i - 1); if (child == mQsb) { int qsbStart; int qsbEnd; if (layoutRtl) { qsbStart = iconEnd + mItemMarginLeftRight; qsbEnd = qsbStart + deviceProfile.qsbWidth; } else { qsbEnd = iconEnd - mItemMarginLeftRight; qsbStart = qsbEnd - deviceProfile.qsbWidth; } int qsbTop = (bottom - top - deviceProfile.hotseatQsbHeight) / 2; int qsbBottom = qsbTop + deviceProfile.hotseatQsbHeight; child.layout(qsbStart, qsbTop, qsbEnd, qsbBottom); } else { iconEnd -= mItemMarginLeftRight; int iconStart = iconEnd - mIconTouchSize; child.layout(iconStart, mIconLayoutBounds.top, iconEnd, mIconLayoutBounds.bottom); iconEnd = iconStart - mItemMarginLeftRight; } } mIconLayoutBounds.left = iconEnd; } Loading Loading @@ -367,6 +400,13 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar return mAllAppsButton; } /** * Returns the QSB in the taskbar. */ public View getQsb() { return mQsb; } // FolderIconParent implemented methods. @Override Loading quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +48 −9 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.launcher3.taskbar; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA; import static com.android.launcher3.Utilities.squaredHypot; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP; Loading @@ -35,12 +36,15 @@ 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.AlphaUpdateListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.icons.ThemedIconDrawable; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.util.HorizontalInsettableView; import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.LauncherBindableItemsContainer; import com.android.launcher3.util.MultiValueAlpha; Loading Loading @@ -211,9 +215,10 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar * 0 => not aligned * 1 => fully aligned */ public void setLauncherIconAlignment(float alignmentRatio, DeviceProfile launcherDp) { public void setLauncherIconAlignment(float alignmentRatio, Float endAlignment, DeviceProfile launcherDp) { if (mIconAlignControllerLazy == null) { mIconAlignControllerLazy = createIconAlignmentController(launcherDp); mIconAlignControllerLazy = createIconAlignmentController(launcherDp, endAlignment); } mIconAlignControllerLazy.setPlayFraction(alignmentRatio); if (alignmentRatio <= 0 || alignmentRatio >= 1) { Loading @@ -225,11 +230,13 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar /** * Creates an animation for aligning the taskbar icons with the provided Launcher device profile */ private AnimatorPlaybackController createIconAlignmentController(DeviceProfile launcherDp) { private AnimatorPlaybackController createIconAlignmentController(DeviceProfile launcherDp, Float endAlignment) { mOnControllerPreCreateCallback.run(); PendingAnimation setter = new PendingAnimation(100); DeviceProfile taskbarDp = mActivity.getDeviceProfile(); Rect hotseatPadding = launcherDp.getHotseatLayoutPadding(mActivity); float scaleUp = ((float) launcherDp.iconSizePx) / mActivity.getDeviceProfile().iconSizePx; float scaleUp = ((float) launcherDp.iconSizePx) / taskbarDp.iconSizePx; int borderSpacing = launcherDp.hotseatBorderSpace; int hotseatCellSize = DeviceProfile.calculateCellWidth( launcherDp.availableWidthPx - hotseatPadding.left - hotseatPadding.right, Loading @@ -246,14 +253,13 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar } int collapsedHeight = mActivity.getDefaultTaskbarWindowHeight(); int expandedHeight = Math.max(collapsedHeight, mActivity.getDeviceProfile().taskbarSize + offsetY); int expandedHeight = Math.max(collapsedHeight, taskbarDp.taskbarSize + offsetY); setter.addOnFrameListener(anim -> mActivity.setTaskbarWindowHeight( anim.getAnimatedFraction() > 0 ? expandedHeight : collapsedHeight)); boolean isToHome = endAlignment != null && endAlignment == 1; for (int i = 0; i < mTaskbarView.getChildCount(); i++) { View child = mTaskbarView.getChildAt(i); int positionInHotseat; if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get() && child == mTaskbarView.getAllAppsButtonView()) { Loading @@ -261,13 +267,46 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar // as its convenient for animation purposes. positionInHotseat = Utilities.isRtl(child.getResources()) ? -1 : mActivity.getDeviceProfile().numShownHotseatIcons; : taskbarDp.numShownHotseatIcons; if (!FeatureFlags.ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.get()) { setter.setViewAlpha(child, 0, LINEAR); setter.setViewAlpha(child, 0, isToHome ? Interpolators.clampToProgress(LINEAR, 0f, 0.17f) : Interpolators.clampToProgress(LINEAR, 0.72f, 0.84f)); } } else if (child.getTag() instanceof ItemInfo) { positionInHotseat = ((ItemInfo) child.getTag()).screenId; } else if (child == mTaskbarView.getQsb()) { boolean isRtl = Utilities.isRtl(child.getResources()); float hotseatIconCenter = isRtl ? launcherDp.widthPx - hotseatPadding.right + borderSpacing + launcherDp.qsbWidth / 2f : hotseatPadding.left - borderSpacing - launcherDp.qsbWidth / 2f; float childCenter = (child.getLeft() + child.getRight()) / 2f; float halfQsbIconWidthDiff = (launcherDp.qsbWidth - taskbarDp.iconSizePx) / 2f; setter.addFloat(child, ICON_TRANSLATE_X, isRtl ? -halfQsbIconWidthDiff : halfQsbIconWidthDiff, hotseatIconCenter - childCenter, LINEAR); int qsbContentHeight = child.getHeight() - child.getPaddingTop() - child.getPaddingBottom(); float scale = ((float) taskbarDp.iconSizePx) / qsbContentHeight; setter.addFloat(child, SCALE_PROPERTY, scale, 1f, LINEAR); setter.addFloat(child, VIEW_ALPHA, 0f, 1f, isToHome ? Interpolators.clampToProgress(LINEAR, 0f, 0.35f) : Interpolators.clampToProgress(LINEAR, 0.84f, 1f)); setter.addOnFrameListener(animator -> AlphaUpdateListener.updateVisibility(child)); float qsbInsetFraction = halfQsbIconWidthDiff / launcherDp.qsbWidth; if (child instanceof HorizontalInsettableView) { setter.addFloat((HorizontalInsettableView) child, HorizontalInsettableView.HORIZONTAL_INSETS, qsbInsetFraction, 0, LINEAR); } continue; } else { Log.w(TAG, "Unsupported view found in createIconAlignmentController, v=" + child); continue; Loading Loading
quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +13 −2 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.Utilities.mapBoundToRange; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.anim.Interpolators.ACCEL_1_5; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5; Loading Loading @@ -184,6 +183,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener public static final int SPLIT_DIVIDER_ANIM_DURATION = 100; public static final int CONTENT_ALPHA_DURATION = 217; public static final int TASKBAR_TO_APP_DURATION = 600; // TODO(b/236145847): Tune TASKBAR_TO_HOME_DURATION to 383 after conflict with unlock animation // is solved. public static final int TASKBAR_TO_HOME_DURATION = 300; protected static final int CONTENT_SCALE_DURATION = 350; protected static final int CONTENT_SCRIM_DURATION = 350; Loading Loading @@ -527,7 +530,15 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener workspace.forEachVisiblePage( view -> viewsToAnimate.add(((CellLayout) view).getShortcutsAndWidgets())); // Do not scale hotseat as a whole when taskbar is present, and scale QSB only if it's // not inline. if (mDeviceProfile.isTaskbarPresent) { if (!mDeviceProfile.isQsbInline) { viewsToAnimate.add(mLauncher.getHotseat().getQsb()); } } else { viewsToAnimate.add(mLauncher.getHotseat()); } viewsToAnimate.forEach(view -> { view.setLayerType(View.LAYER_TYPE_HARDWARE, null); Loading
quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +3 −1 Original line number Diff line number Diff line Loading @@ -171,7 +171,9 @@ public class LauncherTaskbarUIController extends TaskbarUIController { isResumed, fromInit, /* startAnimation= */ true, QuickstepTransitionManager.CONTENT_ALPHA_DURATION); !isResumed ? QuickstepTransitionManager.TASKBAR_TO_APP_DURATION : QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION); } @Nullable Loading
quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +45 −13 Original line number Diff line number Diff line Loading @@ -19,11 +19,13 @@ import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP; import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE; import static com.android.launcher3.taskbar.TaskbarStashController.TASKBAR_STASH_DURATION; import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME; import static com.android.systemui.animation.Interpolators.EMPHASIZED; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; Loading @@ -31,6 +33,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.LauncherState; import com.android.launcher3.QuickstepTransitionManager; import com.android.launcher3.Utilities; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.util.MultiValueAlpha; Loading @@ -44,7 +47,6 @@ import com.android.systemui.shared.recents.model.ThumbnailData; import java.io.PrintWriter; import java.util.HashMap; import java.util.StringJoiner; import java.util.function.Consumer; import java.util.function.Supplier; /** Loading @@ -53,6 +55,9 @@ import java.util.function.Supplier; */ public class TaskbarLauncherStateController { private static final String TAG = TaskbarLauncherStateController.class.getSimpleName(); private static final boolean DEBUG = false; public static final int FLAG_RESUMED = 1 << 0; public static final int FLAG_RECENTS_ANIMATION_RUNNING = 1 << 1; public static final int FLAG_TRANSITION_STATE_RUNNING = 1 << 2; Loading Loading @@ -99,9 +104,13 @@ import java.util.function.Supplier; } updateStateForFlag(FLAG_TRANSITION_STATE_RUNNING, true); if (!mShouldDelayLauncherStateAnim) { if (toState == LauncherState.NORMAL) { applyState(QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION); } else { applyState(); } } } @Override public void onStateTransitionComplete(LauncherState finalState) { Loading @@ -122,7 +131,12 @@ import java.util.function.Supplier; MultiValueAlpha taskbarIconAlpha = mControllers.taskbarViewController.getTaskbarIconAlpha(); mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME); mIconAlphaForHome.setConsumer( (Consumer<Float>) alpha -> mLauncher.getHotseat().setIconsAlpha(alpha > 0 ? 0 : 1)); alpha -> { mLauncher.getHotseat().setIconsAlpha(alpha > 0 ? 0 : 1); if (mLauncher.getDeviceProfile().isQsbInline) { mLauncher.getHotseat().setQsbAlpha(alpha > 0 ? 0 : 1); } }); mIconAlignmentForResumedState.finishAnimation(); onIconAlignmentRatioChangedForAppAndHomeTransition(); Loading Loading @@ -269,6 +283,11 @@ import java.util.function.Supplier; ObjectAnimator resumeAlignAnim = mIconAlignmentForResumedState .animateToValue(toAlignmentForResumedState) .setDuration(duration); if (DEBUG) { Log.d(TAG, "mIconAlignmentForResumedState - " + mIconAlignmentForResumedState.value + " -> " + toAlignmentForResumedState + ": " + duration); } resumeAlignAnim.addListener(new AnimatorListenerAdapter() { @Override Loading Loading @@ -305,6 +324,11 @@ import java.util.function.Supplier; if (isRecentsAnimationRunning) { gestureAlignAnim.setDuration(duration); } if (DEBUG) { Log.d(TAG, "mIconAlignmentForGestureState - " + mIconAlignmentForGestureState.value + " -> " + toAlignmentForGestureState + ": " + duration); } gestureAlignAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { Loading @@ -330,6 +354,7 @@ import java.util.function.Supplier; .setDuration(duration)); } animatorSet.setInterpolator(EMPHASIZED); if (start) { animatorSet.start(); } Loading Loading @@ -374,6 +399,12 @@ import java.util.function.Supplier; mIconAlignmentForLauncherState.finishAnimation(); animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment) .setDuration(duration)); if (DEBUG) { Log.d(TAG, "mIconAlignmentForLauncherState - " + mIconAlignmentForLauncherState.value + " -> " + toAlignment + ": " + duration); } animatorSet.setInterpolator(EMPHASIZED); } } Loading @@ -396,17 +427,17 @@ import java.util.function.Supplier; onIconAlignmentRatioChanged(this::getCurrentIconAlignmentRatioBetweenAppAndHome); } private void onIconAlignmentRatioChanged(Supplier<Float> alignmentSupplier) { private void onIconAlignmentRatioChanged(Supplier<AnimatedFloat> alignmentSupplier) { if (mControllers == null) { return; } float alignment = alignmentSupplier.get(); AnimatedFloat animatedFloat = alignmentSupplier.get(); float currentValue = mIconAlphaForHome.getValue(); boolean taskbarWillBeVisible = alignment < 1; boolean taskbarWillBeVisible = animatedFloat.value < 1; boolean firstFrameVisChanged = (taskbarWillBeVisible && Float.compare(currentValue, 1) != 0) || (!taskbarWillBeVisible && Float.compare(currentValue, 0) != 0); updateIconAlignment(alignment); updateIconAlignment(animatedFloat.value, animatedFloat.getEndValue()); // Sync the first frame where we swap taskbar and hotseat. if (firstFrameVisChanged && mCanSyncViews && !Utilities.IS_RUNNING_IN_TEST_HARNESS) { Loading @@ -416,21 +447,22 @@ import java.util.function.Supplier; } } private void updateIconAlignment(float alignment) { private void updateIconAlignment(float alignment, Float endAlignment) { mControllers.taskbarViewController.setLauncherIconAlignment( alignment, mLauncher.getDeviceProfile()); alignment, endAlignment, mLauncher.getDeviceProfile()); // Switch taskbar and hotseat in last frame setTaskbarViewVisible(alignment < 1); mControllers.navbarButtonsViewController.updateTaskbarAlignment(alignment); } private float getCurrentIconAlignmentRatioBetweenAppAndHome() { return Math.max(mIconAlignmentForResumedState.value, mIconAlignmentForGestureState.value); private AnimatedFloat getCurrentIconAlignmentRatioBetweenAppAndHome() { return mIconAlignmentForResumedState.value > mIconAlignmentForGestureState.value ? mIconAlignmentForResumedState : mIconAlignmentForGestureState; } private float getCurrentIconAlignmentRatioForLauncherState() { return mIconAlignmentForLauncherState.value; private AnimatedFloat getCurrentIconAlignmentRatioForLauncherState() { return mIconAlignmentForLauncherState; } private void setTaskbarViewVisible(boolean isVisible) { Loading
quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +45 −5 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Rect; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; Loading @@ -31,6 +32,7 @@ import androidx.annotation.Nullable; import androidx.core.graphics.ColorUtils; import com.android.launcher3.BubbleTextView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; import com.android.launcher3.R; import com.android.launcher3.Utilities; Loading Loading @@ -78,6 +80,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar // Only non-null when device supports having an All Apps button. private @Nullable AllAppsButton mAllAppsButton; private View mQsb; public TaskbarView(@NonNull Context context) { this(context, null); } Loading Loading @@ -117,6 +121,9 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar new ViewGroup.LayoutParams(mIconTouchSize, mIconTouchSize)); mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding); } // TODO: Disable touch events on QSB otherwise it can crash. mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false); } private int getColorWithGivenLuminance(int color, float luminance) { Loading Loading @@ -166,6 +173,7 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar if (mAllAppsButton != null) { removeView(mAllAppsButton); } removeView(mQsb); for (int i = 0; i < hotseatItemInfos.length; i++) { ItemInfo hotseatItemInfo = hotseatItemInfos[i]; Loading Loading @@ -242,6 +250,11 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar int index = Utilities.isRtl(getResources()) ? 0 : getChildCount(); addView(mAllAppsButton, index); } if (mActivityContext.getDeviceProfile().isQsbInline) { addView(mQsb, Utilities.isRtl(getResources()) ? getChildCount() : 0); // Always set QSB to invisible after re-adding. mQsb.setVisibility(View.INVISIBLE); } mThemeIconsBackground = calculateThemeIconsBackground(); setThemedIconsBackgroundColor(mThemeIconsBackground); Loading Loading @@ -273,7 +286,12 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { int count = getChildCount(); int spaceNeeded = count * (mItemMarginLeftRight * 2 + mIconTouchSize); int countExcludingQsb = count; DeviceProfile deviceProfile = mActivityContext.getDeviceProfile(); if (deviceProfile.isQsbInline) { countExcludingQsb--; } int spaceNeeded = countExcludingQsb * (mItemMarginLeftRight * 2 + mIconTouchSize); int navSpaceNeeded = ApiWrapper.getHotseatEndOffset(getContext()); boolean layoutRtl = isLayoutRtl(); int iconEnd = right - (right - left - spaceNeeded) / 2; Loading @@ -292,11 +310,26 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar mIconLayoutBounds.bottom = mIconLayoutBounds.top + mIconTouchSize; for (int i = count; i > 0; i--) { View child = getChildAt(i - 1); if (child == mQsb) { int qsbStart; int qsbEnd; if (layoutRtl) { qsbStart = iconEnd + mItemMarginLeftRight; qsbEnd = qsbStart + deviceProfile.qsbWidth; } else { qsbEnd = iconEnd - mItemMarginLeftRight; qsbStart = qsbEnd - deviceProfile.qsbWidth; } int qsbTop = (bottom - top - deviceProfile.hotseatQsbHeight) / 2; int qsbBottom = qsbTop + deviceProfile.hotseatQsbHeight; child.layout(qsbStart, qsbTop, qsbEnd, qsbBottom); } else { iconEnd -= mItemMarginLeftRight; int iconStart = iconEnd - mIconTouchSize; child.layout(iconStart, mIconLayoutBounds.top, iconEnd, mIconLayoutBounds.bottom); iconEnd = iconStart - mItemMarginLeftRight; } } mIconLayoutBounds.left = iconEnd; } Loading Loading @@ -367,6 +400,13 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar return mAllAppsButton; } /** * Returns the QSB in the taskbar. */ public View getQsb() { return mQsb; } // FolderIconParent implemented methods. @Override Loading
quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +48 −9 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.launcher3.taskbar; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA; import static com.android.launcher3.Utilities.squaredHypot; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP; Loading @@ -35,12 +36,15 @@ 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.AlphaUpdateListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.icons.ThemedIconDrawable; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.util.HorizontalInsettableView; import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.LauncherBindableItemsContainer; import com.android.launcher3.util.MultiValueAlpha; Loading Loading @@ -211,9 +215,10 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar * 0 => not aligned * 1 => fully aligned */ public void setLauncherIconAlignment(float alignmentRatio, DeviceProfile launcherDp) { public void setLauncherIconAlignment(float alignmentRatio, Float endAlignment, DeviceProfile launcherDp) { if (mIconAlignControllerLazy == null) { mIconAlignControllerLazy = createIconAlignmentController(launcherDp); mIconAlignControllerLazy = createIconAlignmentController(launcherDp, endAlignment); } mIconAlignControllerLazy.setPlayFraction(alignmentRatio); if (alignmentRatio <= 0 || alignmentRatio >= 1) { Loading @@ -225,11 +230,13 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar /** * Creates an animation for aligning the taskbar icons with the provided Launcher device profile */ private AnimatorPlaybackController createIconAlignmentController(DeviceProfile launcherDp) { private AnimatorPlaybackController createIconAlignmentController(DeviceProfile launcherDp, Float endAlignment) { mOnControllerPreCreateCallback.run(); PendingAnimation setter = new PendingAnimation(100); DeviceProfile taskbarDp = mActivity.getDeviceProfile(); Rect hotseatPadding = launcherDp.getHotseatLayoutPadding(mActivity); float scaleUp = ((float) launcherDp.iconSizePx) / mActivity.getDeviceProfile().iconSizePx; float scaleUp = ((float) launcherDp.iconSizePx) / taskbarDp.iconSizePx; int borderSpacing = launcherDp.hotseatBorderSpace; int hotseatCellSize = DeviceProfile.calculateCellWidth( launcherDp.availableWidthPx - hotseatPadding.left - hotseatPadding.right, Loading @@ -246,14 +253,13 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar } int collapsedHeight = mActivity.getDefaultTaskbarWindowHeight(); int expandedHeight = Math.max(collapsedHeight, mActivity.getDeviceProfile().taskbarSize + offsetY); int expandedHeight = Math.max(collapsedHeight, taskbarDp.taskbarSize + offsetY); setter.addOnFrameListener(anim -> mActivity.setTaskbarWindowHeight( anim.getAnimatedFraction() > 0 ? expandedHeight : collapsedHeight)); boolean isToHome = endAlignment != null && endAlignment == 1; for (int i = 0; i < mTaskbarView.getChildCount(); i++) { View child = mTaskbarView.getChildAt(i); int positionInHotseat; if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get() && child == mTaskbarView.getAllAppsButtonView()) { Loading @@ -261,13 +267,46 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar // as its convenient for animation purposes. positionInHotseat = Utilities.isRtl(child.getResources()) ? -1 : mActivity.getDeviceProfile().numShownHotseatIcons; : taskbarDp.numShownHotseatIcons; if (!FeatureFlags.ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.get()) { setter.setViewAlpha(child, 0, LINEAR); setter.setViewAlpha(child, 0, isToHome ? Interpolators.clampToProgress(LINEAR, 0f, 0.17f) : Interpolators.clampToProgress(LINEAR, 0.72f, 0.84f)); } } else if (child.getTag() instanceof ItemInfo) { positionInHotseat = ((ItemInfo) child.getTag()).screenId; } else if (child == mTaskbarView.getQsb()) { boolean isRtl = Utilities.isRtl(child.getResources()); float hotseatIconCenter = isRtl ? launcherDp.widthPx - hotseatPadding.right + borderSpacing + launcherDp.qsbWidth / 2f : hotseatPadding.left - borderSpacing - launcherDp.qsbWidth / 2f; float childCenter = (child.getLeft() + child.getRight()) / 2f; float halfQsbIconWidthDiff = (launcherDp.qsbWidth - taskbarDp.iconSizePx) / 2f; setter.addFloat(child, ICON_TRANSLATE_X, isRtl ? -halfQsbIconWidthDiff : halfQsbIconWidthDiff, hotseatIconCenter - childCenter, LINEAR); int qsbContentHeight = child.getHeight() - child.getPaddingTop() - child.getPaddingBottom(); float scale = ((float) taskbarDp.iconSizePx) / qsbContentHeight; setter.addFloat(child, SCALE_PROPERTY, scale, 1f, LINEAR); setter.addFloat(child, VIEW_ALPHA, 0f, 1f, isToHome ? Interpolators.clampToProgress(LINEAR, 0f, 0.35f) : Interpolators.clampToProgress(LINEAR, 0.84f, 1f)); setter.addOnFrameListener(animator -> AlphaUpdateListener.updateVisibility(child)); float qsbInsetFraction = halfQsbIconWidthDiff / launcherDp.qsbWidth; if (child instanceof HorizontalInsettableView) { setter.addFloat((HorizontalInsettableView) child, HorizontalInsettableView.HORIZONTAL_INSETS, qsbInsetFraction, 0, LINEAR); } continue; } else { Log.w(TAG, "Unsupported view found in createIconAlignmentController, v=" + child); continue; Loading