Merge "Animate inline QSB between home and apps" into tm-qpr-dev am: a5ae4c2e57

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/18799573

Change-Id: I189fa4adfad99c21a9edbb88c34682b1f3c52d84
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Alex Chau
2022-06-16 08:20:50 +00:00
committed by Automerger Merge Worker
10 changed files with 229 additions and 53 deletions
@@ -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;
@@ -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;
@@ -527,7 +530,15 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
workspace.forEachVisiblePage(
view -> viewsToAnimate.add(((CellLayout) view).getShortcutsAndWidgets()));
viewsToAnimate.add(mLauncher.getHotseat());
// 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);
@@ -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
@@ -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;
@@ -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;
@@ -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;
/**
@@ -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;
@@ -99,7 +104,11 @@ import java.util.function.Supplier;
}
updateStateForFlag(FLAG_TRANSITION_STATE_RUNNING, true);
if (!mShouldDelayLauncherStateAnim) {
applyState();
if (toState == LauncherState.NORMAL) {
applyState(QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION);
} else {
applyState();
}
}
}
@@ -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();
@@ -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
@@ -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) {
@@ -330,6 +354,7 @@ import java.util.function.Supplier;
.setDuration(duration));
}
animatorSet.setInterpolator(EMPHASIZED);
if (start) {
animatorSet.start();
}
@@ -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);
}
}
@@ -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) {
@@ -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) {
@@ -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;
@@ -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;
@@ -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);
}
@@ -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) {
@@ -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];
@@ -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);
@@ -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;
@@ -292,10 +310,25 @@ 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);
iconEnd -= mItemMarginLeftRight;
int iconStart = iconEnd - mIconTouchSize;
child.layout(iconStart, mIconLayoutBounds.top, iconEnd, mIconLayoutBounds.bottom);
iconEnd = iconStart - mItemMarginLeftRight;
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;
}
@@ -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
@@ -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;
@@ -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;
@@ -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) {
@@ -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,
@@ -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()) {
@@ -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;
@@ -234,7 +234,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
STATE_LAUNCHER_BIND_TO_SERVICE;
public static final long MAX_SWIPE_DURATION = 350;
public static final long HOME_DURATION = StaggeredWorkspaceAnim.DURATION_MS;
public static final float MIN_PROGRESS_FOR_OVERVIEW = 0.7f;
private static final float SWIPE_DURATION_MULTIPLIER =
@@ -1141,7 +1140,9 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
mInputConsumerProxy.enable();
}
if (endTarget == HOME) {
duration = HOME_DURATION;
duration = mActivity.getDeviceProfile().isTaskbarPresent
? StaggeredWorkspaceAnim.DURATION_TASKBAR_MS
: StaggeredWorkspaceAnim.DURATION_MS;
// Early detach the nav bar once the endTarget is determined as HOME
if (mRecentsAnimationController != null) {
mRecentsAnimationController.detachNavigationBarFromApp(true);
@@ -133,4 +133,11 @@ public class AnimatedFloat {
public boolean isAnimatingToValue(float endValue) {
return isAnimating() && mEndValue != null && mEndValue == endValue;
}
/**
* Returns the value we are animating to, or {@code null} if we are not currently animating.
*/
public Float getEndValue() {
return mEndValue;
}
}
@@ -41,6 +41,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Hotseat;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Workspace;
@@ -60,10 +61,10 @@ import com.android.systemui.plugins.ResourceProvider;
public class StaggeredWorkspaceAnim {
private static final int APP_CLOSE_ROW_START_DELAY_MS = 10;
// How long it takes to fade in each staggered row.
private static final int ALPHA_DURATION_MS = 250;
// Should be used for animations running alongside this StaggeredWorkspaceAnim.
public static final int DURATION_MS = 250;
public static final int DURATION_TASKBAR_MS =
QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION;
private static final float MAX_VELOCITY_PX_PER_S = 22f;
@@ -91,16 +92,20 @@ public class StaggeredWorkspaceAnim {
mSpringTransY = transFactor * launcher.getResources()
.getDimensionPixelSize(R.dimen.swipe_up_max_workspace_trans_y);
DeviceProfile grid = launcher.getDeviceProfile();
long duration = grid.isTaskbarPresent ? DURATION_TASKBAR_MS : DURATION_MS;
if (staggerWorkspace) {
DeviceProfile grid = launcher.getDeviceProfile();
Workspace<?> workspace = launcher.getWorkspace();
Hotseat hotseat = launcher.getHotseat();
// Hotseat and QSB takes up two additional rows.
int totalRows = grid.inv.numRows + (grid.isVerticalBarLayout() ? 0 : 2);
boolean staggerHotseat = !grid.isVerticalBarLayout() && !grid.isTaskbarPresent;
boolean staggerQsb =
!grid.isVerticalBarLayout() && !(grid.isTaskbarPresent && grid.isQsbInline);
int totalRows = grid.inv.numRows + (staggerHotseat ? 1 : 0) + (staggerQsb ? 1 : 0);
// Add animation for all the visible workspace pages
workspace.forEachVisiblePage(page -> addAnimationForPage((CellLayout) page, totalRows));
workspace.forEachVisiblePage(
page -> addAnimationForPage((CellLayout) page, totalRows, duration));
boolean workspaceClipChildren = workspace.getClipChildren();
boolean workspaceClipToPadding = workspace.getClipToPadding();
@@ -119,23 +124,34 @@ public class StaggeredWorkspaceAnim {
View child = hotseatIcons.getChildAt(i);
CellLayout.LayoutParams lp =
((CellLayout.LayoutParams) child.getLayoutParams());
addStaggeredAnimationForView(child, lp.cellY + 1, totalRows);
addStaggeredAnimationForView(child, lp.cellY + 1, totalRows, duration);
}
} else {
final int hotseatRow, qsbRow;
if (grid.isTaskbarPresent) {
qsbRow = grid.inv.numRows + 1;
hotseatRow = grid.inv.numRows + 2;
if (grid.isQsbInline) {
qsbRow = grid.inv.numRows + 1;
hotseatRow = grid.inv.numRows + 1;
} else {
qsbRow = grid.inv.numRows + 1;
hotseatRow = grid.inv.numRows + 2;
}
} else {
hotseatRow = grid.inv.numRows + 1;
qsbRow = grid.inv.numRows + 2;
}
for (int i = hotseatIcons.getChildCount() - 1; i >= 0; i--) {
View child = hotseatIcons.getChildAt(i);
addStaggeredAnimationForView(child, hotseatRow, totalRows);
}
addStaggeredAnimationForView(hotseat.getQsb(), qsbRow, totalRows);
// Do not stagger hotseat as a whole when taskbar is present, and stagger QSB only
// if it's not inline.
if (staggerHotseat) {
for (int i = hotseatIcons.getChildCount() - 1; i >= 0; i--) {
View child = hotseatIcons.getChildAt(i);
addStaggeredAnimationForView(child, hotseatRow, totalRows, duration);
}
}
if (staggerQsb) {
addStaggeredAnimationForView(hotseat.getQsb(), qsbRow, totalRows, duration);
}
}
mAnimators.addListener(new AnimatorListenerAdapter() {
@@ -153,19 +169,19 @@ public class StaggeredWorkspaceAnim {
mAnimators.addListener(forEndCallback(launcher::resumeExpensiveViewUpdates));
if (animateOverviewScrim) {
PendingAnimation pendingAnimation = new PendingAnimation(DURATION_MS);
PendingAnimation pendingAnimation = new PendingAnimation(duration);
launcher.getWorkspace().getStateTransitionAnimation()
.setScrim(pendingAnimation, NORMAL, new StateAnimationConfig());
mAnimators.play(pendingAnimation.buildAnim());
}
addDepthAnimationForState(launcher, NORMAL, DURATION_MS);
addDepthAnimationForState(launcher, NORMAL, duration);
mAnimators.play(launcher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(0f, 1f)
.setDuration(DURATION_MS));
.setDuration(duration));
}
private void addAnimationForPage(CellLayout page, int totalRows) {
private void addAnimationForPage(CellLayout page, int totalRows, long duration) {
ShortcutAndWidgetContainer itemsContainer = page.getShortcutsAndWidgets();
boolean pageClipChildren = page.getClipChildren();
@@ -178,7 +194,7 @@ public class StaggeredWorkspaceAnim {
for (int i = itemsContainer.getChildCount() - 1; i >= 0; i--) {
View child = itemsContainer.getChildAt(i);
CellLayout.LayoutParams lp = ((CellLayout.LayoutParams) child.getLayoutParams());
addStaggeredAnimationForView(child, lp.cellY + lp.cellVSpan, totalRows);
addStaggeredAnimationForView(child, lp.cellY + lp.cellVSpan, totalRows, duration);
}
mAnimators.addListener(new AnimatorListenerAdapter() {
@@ -231,8 +247,9 @@ public class StaggeredWorkspaceAnim {
* @param v A view on the workspace.
* @param row The bottom-most row that contains the view.
* @param totalRows Total number of rows.
* @param duration duration of the animation
*/
private void addStaggeredAnimationForView(View v, int row, int totalRows) {
private void addStaggeredAnimationForView(View v, int row, int totalRows, long duration) {
if (mIgnoredView != null && mIgnoredView == v) return;
// Invert the rows, because we stagger starting from the bottom of the screen.
int invertedRow = totalRows - row;
@@ -266,7 +283,7 @@ public class StaggeredWorkspaceAnim {
v.setAlpha(0);
ObjectAnimator alpha = ObjectAnimator.ofFloat(v, View.ALPHA, 0f, 1f);
alpha.setInterpolator(LINEAR);
alpha.setDuration(ALPHA_DURATION_MS);
alpha.setDuration(duration);
alpha.setStartDelay(startDelay);
alpha.addListener(new AnimatorListenerAdapter() {
@Override
+7
View File
@@ -206,6 +206,13 @@ public class Hotseat extends CellLayout implements Insettable {
getShortcutsAndWidgets().setAlpha(alpha);
}
/**
* Sets the alpha value of just our QSB.
*/
public void setQsbAlpha(float alpha) {
mQsb.setAlpha(alpha);
}
public float getIconsAlpha() {
return getShortcutsAndWidgets().getAlpha();
}
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.util;
import android.util.FloatProperty;
/**
* Allows the implementing view to add insets to the left and right.
*/
@@ -32,4 +34,22 @@ public interface HorizontalInsettableView {
*/
void setHorizontalInsets(float insetPercentage);
/**
* Returns the width percentage to inset the content from the left and from the right. See
* {@link #setHorizontalInsets};
*/
float getHorizontalInsets();
FloatProperty<HorizontalInsettableView> HORIZONTAL_INSETS =
new FloatProperty<HorizontalInsettableView>("horizontalInsets") {
@Override
public Float get(HorizontalInsettableView view) {
return view.getHorizontalInsets();
}
@Override
public void setValue(HorizontalInsettableView view, float insetPercentage) {
view.setHorizontalInsets(insetPercentage);
}
};
}