Merge "Animate inline QSB between home and apps" into tm-qpr-dev
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user