Merge "Treat all apps predictions as all app icons when animating icons to their original position" into tm-qpr-dev
diff --git a/OWNERS b/OWNERS
index 7f98ea6..560b562 100644
--- a/OWNERS
+++ b/OWNERS
@@ -7,13 +7,6 @@
alexchau@google.com
andraskloczl@google.com
patmanning@google.com
-petrcermak@google.com
-pbdr@google.com
-kideckel@google.com
-stevenckng@google.com
-ydixit@google.com
-boadway@google.com
-alinazaidi@google.com
adamcohen@google.com
hyunyoungs@google.com
mrcasey@google.com
@@ -24,10 +17,8 @@
zakcohen@google.com
santie@google.com
vadimt@google.com
-mett@google.com
jonmiranda@google.com
pinyaoting@google.com
-sfufa@google.com
gwasserman@google.com
jamesoleary@google.com
joshtrask@google.com
@@ -37,8 +28,6 @@
tracyzhou@google.com
peanutbutter@google.com
xuqiu@google.com
-sreyasr@google.com
-thiruram@google.com
brianji@google.com
per-file FeatureFlags.java, globs = set noparent
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index 7b297af..4013a71 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -86,7 +86,7 @@
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Tap another app to use split-screen"</string>
<string name="toast_split_app_unsupported" msgid="3271526028981899666">"App does not support split-screen."</string>
- <string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organisation"</string>
+ <string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organization"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"You can find this later in the <xliff:g id="NAME">%1$s</xliff:g> app"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Cancel"</string>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index a206a49..75f0933 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -97,7 +97,7 @@
<string name="taskbar_edu_switch_apps" msgid="6942863327845784813">"Префрлувајте се меѓу апликации преку лентата за задачи"</string>
<string name="taskbar_edu_splitscreen" msgid="2663361731630346489">"Повлечете кон страната за да користите две апликации одеднаш"</string>
<string name="taskbar_edu_stashing" msgid="5212374387411764031">"Допрете и задржете за да се сокрие лентата за задачи"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Следна"</string>
+ <string name="taskbar_edu_next" msgid="4007618274426775841">"Следно"</string>
<string name="taskbar_edu_previous" msgid="459202320127201702">"Назад"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Затвори"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index e1a3b72..b20752d 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -31,7 +31,6 @@
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 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 @@
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);
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index ca30e72..6df31e5 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -171,7 +171,9 @@
isResumed,
fromInit,
/* startAnimation= */ true,
- QuickstepTransitionManager.CONTENT_ALPHA_DURATION);
+ !isResumed
+ ? QuickstepTransitionManager.TASKBAR_TO_APP_DURATION
+ : QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION);
}
@Nullable
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 61fad50..d1994e7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -148,7 +148,7 @@
mIsUserSetupComplete = SettingsCache.INSTANCE.get(this).getValue(
Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0);
mIsNavBarForceVisible = SettingsCache.INSTANCE.get(this).getValue(
- Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_FORCE_VISIBLE), 0);
+ Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_KIDS_MODE), 0);
mIsNavBarKidsMode = SettingsCache.INSTANCE.get(this).getValue(
Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_KIDS_MODE), 0);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index dc0ef27..ff11f67 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -19,11 +19,13 @@
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 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 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 @@
*/
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 @@
}
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 @@
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();
@@ -169,10 +183,8 @@
mTaskBarRecentsAnimationListener = new TaskBarRecentsAnimationListener(callbacks);
callbacks.addListener(mTaskBarRecentsAnimationListener);
- RecentsView recentsView = mLauncher.getOverviewPanel();
- recentsView.setTaskLaunchListener(() -> {
- mTaskBarRecentsAnimationListener.endGestureStateOverride(true);
- });
+ ((RecentsView) mLauncher.getOverviewPanel()).setTaskLaunchListener(() ->
+ mTaskBarRecentsAnimationListener.endGestureStateOverride(true));
return animatorSet;
}
@@ -269,6 +281,11 @@
ObjectAnimator resumeAlignAnim = mIconAlignmentForResumedState
.animateToValue(toAlignmentForResumedState)
.setDuration(duration);
+ if (DEBUG) {
+ Log.d(TAG, "mIconAlignmentForResumedState - "
+ + mIconAlignmentForResumedState.value
+ + " -> " + toAlignmentForResumedState + ": " + duration);
+ }
resumeAlignAnim.addListener(new AnimatorListenerAdapter() {
@Override
@@ -305,6 +322,11 @@
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 +352,7 @@
.setDuration(duration));
}
+ animatorSet.setInterpolator(EMPHASIZED);
if (start) {
animatorSet.start();
}
@@ -374,6 +397,12 @@
mIconAlignmentForLauncherState.finishAnimation();
animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment)
.setDuration(duration));
+ if (DEBUG) {
+ Log.d(TAG, "mIconAlignmentForLauncherState - "
+ + mIconAlignmentForLauncherState.value
+ + " -> " + toAlignment + ": " + duration);
+ }
+ animatorSet.setInterpolator(EMPHASIZED);
}
}
@@ -396,17 +425,17 @@
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 +445,22 @@
}
}
- 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) {
@@ -459,6 +489,7 @@
private void endGestureStateOverride(boolean finishedToApp) {
mCallbacks.removeListener(this);
mTaskBarRecentsAnimationListener = null;
+ ((RecentsView) mLauncher.getOverviewPanel()).setTaskLaunchListener(null);
// Update the resumed state immediately to ensure a seamless handoff
boolean launcherResumed = !finishedToApp;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 6f88d64..6a43cc5 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -20,6 +20,7 @@
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.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 @@
// 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 @@
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 @@
if (mAllAppsButton != null) {
removeView(mAllAppsButton);
}
+ removeView(mQsb);
for (int i = 0; i < hotseatItemInfos.length; i++) {
ItemInfo hotseatItemInfo = hotseatItemInfos[i];
@@ -242,6 +250,11 @@
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 @@
@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 @@
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 @@
return mAllAppsButton;
}
+ /**
+ * Returns the QSB in the taskbar.
+ */
+ public View getQsb() {
+ return mQsb;
+ }
+
// FolderIconParent implemented methods.
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index fdd9de5..0cbd0d1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -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.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 @@
* 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 @@
/**
* 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 @@
}
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 @@
// 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;
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
index c56ac5b..61b038e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
@@ -187,7 +187,7 @@
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
Optional.ofNullable(mAllAppsContext)
.map(c -> c.getSystemService(WindowManager.class))
- .ifPresent(m -> m.removeView(mAllAppsContext.getDragLayer()));
+ .ifPresent(m -> m.removeViewImmediate(mAllAppsContext.getDragLayer()));
mAllAppsContext = null;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 429f209..6427e09 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -131,9 +131,14 @@
@Override
public void onBackPressed(Launcher launcher) {
- TaskView taskView = launcher.<RecentsView>getOverviewPanel().getRunningTaskView();
+ RecentsView recentsView = launcher.getOverviewPanel();
+ TaskView taskView = recentsView.getRunningTaskView();
if (taskView != null) {
- taskView.launchTasks();
+ if (recentsView.isTaskViewFullyVisible(taskView)) {
+ taskView.launchTasks();
+ } else {
+ recentsView.snapToPage(recentsView.indexOfChild(taskView));
+ }
} else {
super.onBackPressed(launcher);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index 2d7fe69..4d2f965 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -42,17 +42,10 @@
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
-import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD;
-import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD;
-import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_SCRIM_OPAQUE_THRESHOLD;
-import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_SCRIM_VISIBLE_THRESHOLD;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
-import static com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE;
-import static com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE;
import android.animation.ValueAnimator;
@@ -60,8 +53,8 @@
import com.android.launcher3.Hotseat;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Workspace;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.touch.AllAppsSwipeController;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.util.RecentsAtomicAnimationFactory;
@@ -182,23 +175,9 @@
}
config.duration = Math.max(config.duration, mHintToNormalDuration);
} else if (fromState == ALL_APPS && toState == NORMAL) {
- boolean isTablet = mActivity.getDeviceProfile().isTablet;
- config.setInterpolator(ANIM_ALL_APPS_FADE,
- isTablet ? FINAL_FRAME : Interpolators.clampToProgress(LINEAR,
- 1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
- 1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD));
- config.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(LINEAR,
- 1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD,
- 1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD));
- config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_ACCELERATE);
- if (!isTablet) {
- config.setInterpolator(ANIM_WORKSPACE_FADE, INSTANT);
- }
+ AllAppsSwipeController.applyAllAppsToNormalConfig(mActivity, config);
} else if (fromState == NORMAL && toState == ALL_APPS) {
- if (mActivity.getDeviceProfile().isTablet) {
- config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_DECELERATE);
- }
- // TODO(b/231682175): centralize this setup in AllAppsSwipeController
+ AllAppsSwipeController.applyNormalToAllAppsAnimConfig(mActivity, config);
}
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index e56c90c..9efbc34 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -21,21 +21,8 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_DEPTH;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
import android.view.MotionEvent;
-import android.view.animation.Interpolator;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
@@ -44,6 +31,7 @@
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.touch.AbstractStateChangeTouchController;
+import com.android.launcher3.touch.AllAppsSwipeController;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.uioverrides.states.OverviewState;
import com.android.quickstep.SystemUiProxy;
@@ -58,53 +46,6 @@
private static final String TAG = "PortraitStatesTouchCtrl";
- /**
- * The progress at which all apps content will be fully visible.
- */
- public static final float ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD = 0.8f;
-
- /**
- * Minimum clamping progress for fading in all apps content
- */
- public static final float ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD = 0.5f;
-
- /**
- * Minimum clamping progress for fading in all apps scrim
- */
- public static final float ALL_APPS_SCRIM_VISIBLE_THRESHOLD = .1f;
-
- /**
- * Maximum clamping progress for opaque all apps scrim
- */
- public static final float ALL_APPS_SCRIM_OPAQUE_THRESHOLD = .5f;
-
- // Custom timing for NORMAL -> ALL_APPS on phones only.
- private static final float ALL_APPS_STATE_TRANSITION = 0.4f;
- private static final float ALL_APPS_FULL_DEPTH_PROGRESS = 0.5f;
-
- // Custom interpolators for NORMAL -> ALL_APPS on phones only.
- private static final Interpolator LINEAR_EARLY =
- Interpolators.clampToProgress(LINEAR, 0f, ALL_APPS_STATE_TRANSITION);
- private static final Interpolator STEP_TRANSITION =
- Interpolators.clampToProgress(FINAL_FRAME, 0f, ALL_APPS_STATE_TRANSITION);
- // The blur to and from All Apps is set to be complete when the interpolator is at 0.5.
- public static final Interpolator BLUR =
- Interpolators.clampToProgress(
- Interpolators.mapToProgress(LINEAR, 0f, ALL_APPS_FULL_DEPTH_PROGRESS),
- 0f, ALL_APPS_STATE_TRANSITION);
- public static final Interpolator WORKSPACE_FADE = STEP_TRANSITION;
- public static final Interpolator WORKSPACE_SCALE = LINEAR_EARLY;
- public static final Interpolator HOTSEAT_FADE = STEP_TRANSITION;
- public static final Interpolator HOTSEAT_SCALE = LINEAR_EARLY;
- public static final Interpolator HOTSEAT_TRANSLATE = STEP_TRANSITION;
- public static final Interpolator SCRIM_FADE = LINEAR_EARLY;
- public static final Interpolator ALL_APPS_FADE =
- Interpolators.clampToProgress(LINEAR, ALL_APPS_STATE_TRANSITION, 1f);
- public static final Interpolator ALL_APPS_VERTICAL_PROGRESS =
- Interpolators.clampToProgress(
- Interpolators.mapToProgress(LINEAR, ALL_APPS_STATE_TRANSITION, 1f),
- ALL_APPS_STATE_TRANSITION, 1f);
-
private final PortraitOverviewStateTouchHelper mOverviewPortraitStateTouchHelper;
public PortraitStatesTouchController(Launcher l) {
@@ -160,66 +101,15 @@
return fromState;
}
- private StateAnimationConfig getNormalToAllAppsAnimation() {
- StateAnimationConfig builder = new StateAnimationConfig();
- if (mLauncher.getDeviceProfile().isTablet) {
- builder.setInterpolator(ANIM_ALL_APPS_FADE, INSTANT);
- builder.setInterpolator(ANIM_SCRIM_FADE,
- Interpolators.clampToProgress(LINEAR,
- ALL_APPS_SCRIM_VISIBLE_THRESHOLD,
- ALL_APPS_SCRIM_OPAQUE_THRESHOLD));
- } else {
- // TODO(b/231682175): centralize this setup in AllAppsSwipeController.
- builder.setInterpolator(ANIM_DEPTH, BLUR);
- builder.setInterpolator(ANIM_WORKSPACE_FADE, WORKSPACE_FADE);
- builder.setInterpolator(ANIM_WORKSPACE_SCALE, WORKSPACE_SCALE);
- builder.setInterpolator(ANIM_HOTSEAT_FADE, HOTSEAT_FADE);
- builder.setInterpolator(ANIM_HOTSEAT_SCALE, HOTSEAT_SCALE);
- builder.setInterpolator(ANIM_HOTSEAT_TRANSLATE, HOTSEAT_TRANSLATE);
- builder.setInterpolator(ANIM_SCRIM_FADE, SCRIM_FADE);
- builder.setInterpolator(ANIM_ALL_APPS_FADE, ALL_APPS_FADE);
- builder.setInterpolator(ANIM_VERTICAL_PROGRESS, ALL_APPS_VERTICAL_PROGRESS);
- }
- return builder;
- }
-
- private StateAnimationConfig getAllAppsToNormalAnimation() {
- StateAnimationConfig builder = new StateAnimationConfig();
- if (mLauncher.getDeviceProfile().isTablet) {
- builder.setInterpolator(ANIM_ALL_APPS_FADE, FINAL_FRAME);
- builder.setInterpolator(ANIM_SCRIM_FADE,
- Interpolators.clampToProgress(LINEAR,
- 1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD,
- 1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD));
- } else {
- // These interpolators are the reverse of the ones used above, so swiping out of All
- // Apps feels the same as swiping into it.
- // TODO(b/231682175): centralize this setup in AllAppsSwipeController.
- builder.setInterpolator(ANIM_DEPTH, Interpolators.reverse(BLUR));
- builder.setInterpolator(ANIM_WORKSPACE_FADE, Interpolators.reverse(WORKSPACE_FADE));
- builder.setInterpolator(ANIM_WORKSPACE_SCALE, Interpolators.reverse(WORKSPACE_SCALE));
- builder.setInterpolator(ANIM_HOTSEAT_FADE, Interpolators.reverse(HOTSEAT_FADE));
- builder.setInterpolator(ANIM_HOTSEAT_SCALE, Interpolators.reverse(HOTSEAT_SCALE));
- builder.setInterpolator(ANIM_HOTSEAT_TRANSLATE,
- Interpolators.reverse(HOTSEAT_TRANSLATE));
- builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.reverse(SCRIM_FADE));
- builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.reverse(ALL_APPS_FADE));
- builder.setInterpolator(ANIM_VERTICAL_PROGRESS,
- Interpolators.reverse(ALL_APPS_VERTICAL_PROGRESS));
- }
- return builder;
- }
-
@Override
protected StateAnimationConfig getConfigForStates(
LauncherState fromState, LauncherState toState) {
- final StateAnimationConfig config;
+ final StateAnimationConfig config = new StateAnimationConfig();
+ config.userControlled = true;
if (fromState == NORMAL && toState == ALL_APPS) {
- config = getNormalToAllAppsAnimation();
+ AllAppsSwipeController.applyNormalToAllAppsAnimConfig(mLauncher, config);
} else if (fromState == ALL_APPS && toState == NORMAL) {
- config = getAllAppsToNormalAnimation();
- } else {
- config = new StateAnimationConfig();
+ AllAppsSwipeController.applyAllAppsToNormalConfig(mLauncher, config);
}
return config;
}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index f6589de..0972e4e 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -166,11 +166,7 @@
if (mActivity != activity) {
return;
}
- if (mTaskAnimationManager != null) {
- mTaskAnimationManager.finishRunningRecentsAnimation(true);
- }
mRecentsView = null;
- mActivity.unregisterActivityLifecycleCallbacks(mLifecycleCallbacks);
mActivity = null;
}
};
@@ -234,7 +230,6 @@
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 =
@@ -866,6 +861,7 @@
TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
if (mRecentsView != null) {
+ final View rv = mRecentsView;
mRecentsView.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {
boolean mHandled = false;
@@ -881,8 +877,7 @@
InteractionJankMonitorWrapper.begin(mRecentsView,
InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME);
- mRecentsView.post(() ->
- mRecentsView.getViewTreeObserver().removeOnDrawListener(this));
+ rv.post(() -> rv.getViewTreeObserver().removeOnDrawListener(this));
}
});
}
@@ -1141,7 +1136,9 @@
mInputConsumerProxy.enable();
}
if (endTarget == HOME) {
- duration = HOME_DURATION;
+ duration = mActivity != null && 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);
@@ -1599,6 +1596,9 @@
private void reset() {
mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
+ if (mActivity != null) {
+ mActivity.unregisterActivityLifecycleCallbacks(mLifecycleCallbacks);
+ }
}
/**
@@ -1676,7 +1676,7 @@
boolean wasVisible = mWasLauncherAlreadyVisible || mGestureStarted;
mActivityInterface.onTransitionCancelled(wasVisible, mGestureState.getEndTarget());
- if (mRecentsAnimationTargets != null) {
+ if (mRecentsAnimationTargets != null && wasVisible) {
setDividerShown(true /* shown */, true /* immediate */);
}
diff --git a/quickstep/src/com/android/quickstep/AnimatedFloat.java b/quickstep/src/com/android/quickstep/AnimatedFloat.java
index 6c7a885..a166553 100644
--- a/quickstep/src/com/android/quickstep/AnimatedFloat.java
+++ b/quickstep/src/com/android/quickstep/AnimatedFloat.java
@@ -133,4 +133,11 @@
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;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index d11d50b..1634c08 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -165,7 +165,7 @@
}
@Override
- public void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) {
+ public boolean onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) {
mThumbnailCache.updateTaskSnapShot(taskId, snapshot);
for (int i = mThumbnailChangeListeners.size() - 1; i >= 0; i--) {
@@ -174,6 +174,7 @@
task.thumbnail = snapshot;
}
}
+ return true;
}
@Override
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index db402af..a030568 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -468,7 +468,6 @@
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
finishCallback.run();
}
});
@@ -530,7 +529,6 @@
for (SurfaceControl leash: closingTargets) {
t.hide(leash);
}
- super.onAnimationEnd(animation);
finishCallback.run();
}
});
@@ -599,9 +597,14 @@
launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
launcherAnim.setDuration(RECENTS_LAUNCH_DURATION);
- // Make sure recents gets fixed up by resetting task alphas and scales, etc.
windowAnimEndListener = new AnimatorListenerAdapter() {
@Override
+ public void onAnimationStart(Animator animation) {
+ recentsView.onTaskLaunchedInLiveTileMode();
+ }
+
+ // Make sure recents gets fixed up by resetting task alphas and scales, etc.
+ @Override
public void onAnimationEnd(Animator animation) {
recentsView.finishRecentsAnimation(false /* toRecents */, () -> {
recentsView.post(() -> {
@@ -677,7 +680,6 @@
dockFadeAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
if (shown) {
for (SurfaceControl leash : auxiliarySurfaces) {
t.setAlpha(leash, 0);
@@ -689,7 +691,6 @@
@Override
public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
if (!shown) {
for (SurfaceControl leash : auxiliarySurfaces) {
t.hide(leash);
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 417473f..bf1c998 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -151,6 +151,8 @@
*/
public class TISBinder extends IOverviewProxy.Stub {
+ @Nullable private Runnable mOnOverviewTargetChangeListener = null;
+
@BinderThread
public void onInitialize(Bundle bundle) {
ISystemUiProxy proxy = ISystemUiProxy.Stub.asInterface(
@@ -331,6 +333,18 @@
public void setGestureBlockedTaskId(int taskId) {
mDeviceState.setGestureBlockingTaskId(taskId);
}
+
+ /** Sets a listener to be run on Overview Target updates. */
+ public void setOverviewTargetChangeListener(@Nullable Runnable listener) {
+ mOnOverviewTargetChangeListener = listener;
+ }
+
+ protected void onOverviewTargetChange() {
+ if (mOnOverviewTargetChangeListener != null) {
+ mOnOverviewTargetChangeListener.run();
+ mOnOverviewTargetChangeListener = null;
+ }
+ }
}
private static boolean sConnected = false;
@@ -491,6 +505,7 @@
if (newOverviewActivity != null) {
mTaskbarManager.setActivity(newOverviewActivity);
}
+ mTISBinder.onOverviewTargetChange();
}
@UiThread
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 10b4ff9..641385d 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -443,12 +443,18 @@
mMainThreadHandler.removeCallbacks(mCancelRecentsAnimationRunnable);
mMainThreadHandler.postDelayed(mCancelRecentsAnimationRunnable, 100);
}
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- mMotionPauseDetector.clear();
+ cleanupAfterGesture();
TraceHelper.INSTANCE.endSection(traceToken);
}
+ private void cleanupAfterGesture() {
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+ mMotionPauseDetector.clear();
+ }
+
@Override
public void notifyOrientationSetup() {
mRotationTouchHelper.onStartGesture();
@@ -471,6 +477,7 @@
Preconditions.assertUIThread();
removeListener();
mInteractionHandler = null;
+ cleanupAfterGesture();
mOnCompleteCallback.accept(this);
}
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
index 66ed056..aa52789 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -208,6 +208,7 @@
mBinder = binder;
mBinder.getTaskbarManager().setSetupUIVisible(isResumed());
mBinder.setSwipeUpProxy(isResumed() ? this::createSwipeUpProxy : null);
+ mBinder.setOverviewTargetChangeListener(mBinder::preloadOverviewForSUWAllSet);
mBinder.preloadOverviewForSUWAllSet();
}
@@ -224,6 +225,7 @@
if (mBinder != null) {
mBinder.getTaskbarManager().setSetupUIVisible(false);
mBinder.setSwipeUpProxy(null);
+ mBinder.setOverviewTargetChangeListener(null);
}
}
diff --git a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index 32e08ff..de527a7 100644
--- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -41,6 +41,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* @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 @@
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
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index dbb20e0..1acdec1 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -390,10 +390,8 @@
.withWindowCrop(mTmpCropRect)
.withCornerRadius(getCurrentCornerRadius());
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && params.getRecentsSurface() != null) {
- // When relativeLayer = 0, it reverts the surfaces back to the original order.
- builder.withRelativeLayerTo(params.getRecentsSurface(),
- mDrawsBelowRecents ? Integer.MIN_VALUE : 0);
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ builder.withLayer(mDrawsBelowRecents ? Integer.MIN_VALUE : 0);
}
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index 69cad69..1629bb7 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -52,6 +52,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.SystemUiController;
+import com.android.launcher3.util.SystemUiController.SystemUiControllerFlags;
import com.android.quickstep.TaskOverlayFactory.TaskOverlay;
import com.android.quickstep.views.TaskView.FullscreenDrawParams;
import com.android.systemui.shared.recents.model.Task;
@@ -247,6 +248,7 @@
}
+ @SystemUiControllerFlags
public int getSysUiStatusNavFlags() {
if (mThumbnailData != null) {
int flags = 0;
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
index 6ec6269..401b967 100644
--- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
@@ -16,8 +16,6 @@
package com.android.quickstep;
-import android.content.Intent;
-
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
@@ -43,7 +41,7 @@
// b/143488140
mLauncher.goHome();
// Start an activity where the gestures start.
- startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
+ startTestActivity(2);
}
private void runTest(String... eventSequence) {
diff --git a/res/layout/widgets_list_row_header.xml b/res/layout/widgets_list_row_header.xml
index 3cdc2e8..35bea27 100644
--- a/res/layout/widgets_list_row_header.xml
+++ b/res/layout/widgets_list_row_header.xml
@@ -19,7 +19,6 @@
android:id="@+id/widgets_list_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingVertical="@dimen/widget_list_header_view_vertical_padding"
android:orientation="horizontal"
android:importantForAccessibility="yes"
android:focusable="true"
diff --git a/res/values/id.xml b/res/values/id.xml
index af21b27..9fc0ff8 100644
--- a/res/values/id.xml
+++ b/res/values/id.xml
@@ -16,7 +16,6 @@
-->
<resources>
<item type="id" name="apps_list_view_work" />
- <item type="id" name="tag_widget_entry" />
<item type="id" name="view_type_widgets_space" />
<item type="id" name="view_type_widgets_list" />
<item type="id" name="view_type_widgets_header" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 847e4a8..2addf50 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -344,7 +344,7 @@
<string name="action_move">Move item</string>
<!-- Accessibility description to move item to empty cell. -->
- <string name="move_to_empty_cell">Move to row <xliff:g id="number" example="1">%1$s</xliff:g> column <xliff:g id="number" example="1">%2$s</xliff:g></string>
+ <string name="move_to_empty_cell_description">Move to row <xliff:g id="number" example="1">%1$s</xliff:g> column <xliff:g id="number" example="1">%2$s</xliff:g> in <xliff:g id="string" example="Home screen 2 of 4">%3$s</xliff:g></string>
<!-- Accessibility description to move item inside a folder. -->
<string name="move_to_position">Move to position <xliff:g id="number" example="1">%1$s</xliff:g></string>
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 300e7bf..52dfcd4 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -1202,13 +1202,14 @@
int row = cellY + 1;
int col = workspace.mIsRtl ? mCountX - cellX : cellX + 1;
int panelCount = workspace.getPanelCount();
+ int screenId = workspace.getIdForScreen(this);
+ int pageIndex = workspace.getPageIndexForScreenId(screenId);
if (panelCount > 1) {
// Increment the column if the target is on the right side of a two panel home
- int screenId = workspace.getIdForScreen(this);
- int pageIndex = workspace.getPageIndexForScreenId(screenId);
col += (pageIndex % panelCount) * mCountX;
}
- return getContext().getString(R.string.move_to_empty_cell, row, col);
+ return getContext().getString(R.string.move_to_empty_cell_description, row, col,
+ workspace.getPageDescription(pageIndex));
}
}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 87885f6..8c1f505 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -1148,7 +1148,7 @@
private int getHotseatBottomPadding() {
if (isQsbInline) {
- return getQsbOffsetY() - (Math.abs(hotseatQsbHeight - hotseatCellHeightPx) / 2);
+ return getQsbOffsetY() + ((hotseatQsbHeight - hotseatCellHeightPx) / 2);
} else {
return (getQsbOffsetY() - taskbarSize) / 2;
}
diff --git a/src/com/android/launcher3/FastScrollRecyclerView.java b/src/com/android/launcher3/FastScrollRecyclerView.java
index f117069..94903f2 100644
--- a/src/com/android/launcher3/FastScrollRecyclerView.java
+++ b/src/com/android/launcher3/FastScrollRecyclerView.java
@@ -24,6 +24,7 @@
import android.view.accessibility.AccessibilityNodeInfo;
import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.compat.AccessibilityManagerCompat;
@@ -86,15 +87,20 @@
* Returns the available scroll height:
* AvailableScrollHeight = Total height of the all items - last page height
*/
- protected abstract int getAvailableScrollHeight();
+ protected int getAvailableScrollHeight() {
+ // AvailableScrollHeight = Total height of the all items - first page height
+ int firstPageHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
+ int totalHeightOfAllItems = getItemsHeight(/* untilIndex= */ getAdapter().getItemCount());
+ int availableScrollHeight = totalHeightOfAllItems - firstPageHeight;
+ return Math.max(0, availableScrollHeight);
+ }
/**
* Returns the available scroll bar height:
* AvailableScrollBarHeight = Total height of the visible view - thumb height
*/
protected int getAvailableScrollBarHeight() {
- int availableScrollBarHeight = getScrollbarTrackHeight() - mScrollbar.getThumbHeight();
- return availableScrollBarHeight;
+ return getScrollbarTrackHeight() - mScrollbar.getThumbHeight();
}
/**
@@ -152,12 +158,51 @@
}
/**
- * Maps the touch (from 0..1) to the adapter position that should be visible.
- * <p>Override in each subclass of this base class.
- *
* @return the scroll top of this recycler view.
*/
- public abstract int getCurrentScrollY();
+ public int getCurrentScrollY() {
+ Adapter adapter = getAdapter();
+ if (adapter == null) {
+ return -1;
+ }
+ if (adapter.getItemCount() == 0 || getChildCount() == 0) {
+ return -1;
+ }
+
+ int itemPosition = NO_POSITION;
+ View child = null;
+
+ LayoutManager layoutManager = getLayoutManager();
+ if (layoutManager instanceof LinearLayoutManager) {
+ // Use the LayoutManager as the source of truth for visible positions. During
+ // animations, the view group child may not correspond to the visible views that appear
+ // at the top.
+ itemPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
+ child = layoutManager.findViewByPosition(itemPosition);
+ }
+
+ if (child == null) {
+ // If the layout manager returns null for any reason, which can happen before layout
+ // has occurred for the position, then look at the child of this view as a ViewGroup.
+ child = getChildAt(0);
+ itemPosition = getChildAdapterPosition(child);
+ }
+ if (itemPosition == NO_POSITION) {
+ return -1;
+ }
+ return getPaddingTop() + getItemsHeight(itemPosition)
+ - layoutManager.getDecoratedTop(child);
+ }
+
+ /**
+ * Returns the sum of the height, in pixels, of this list adapter's items from index
+ * 0 (inclusive) until {@code untilIndex} (exclusive). If untilIndex is same as the itemCount,
+ * it returns the full height of all the items.
+ *
+ * <p>If the untilIndex is larger than the total number of items in this adapter, returns the
+ * sum of all items' height.
+ */
+ protected abstract int getItemsHeight(int untilIndex);
/**
* Maps the touch (from 0..1) to the adapter position that should be visible.
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 76106fc..8c4c662 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -206,6 +206,13 @@
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();
}
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 73ca4a3..dacbe92 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -61,8 +61,6 @@
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -634,18 +632,6 @@
float screenHeight = config.screenHeightDp * res.getDisplayMetrics().density;
int rotation = WindowManagerProxy.INSTANCE.get(context).getRotation(context);
- if (Utilities.IS_DEBUG_DEVICE) {
- StringWriter stringWriter = new StringWriter();
- PrintWriter printWriter = new PrintWriter(stringWriter);
- DisplayController.INSTANCE.get(context).dump(printWriter);
- printWriter.flush();
- Log.d("b/231312158", "getDeviceProfile -"
- + "\nconfig: " + config
- + "\ndisplayMetrics: " + res.getDisplayMetrics()
- + "\nrotation: " + rotation
- + "\n" + stringWriter,
- new Exception());
- }
return getBestMatch(screenWidth, screenHeight, rotation);
}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 73be5be..cba0b7d 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -1187,7 +1187,9 @@
}
public int getScrollForPage(int index) {
- if (!pageScrollsInitialized() || index >= mPageScrolls.length || index < 0) {
+ // TODO(b/233112195): Use !pageScrollsInitialized() instead of mPageScrolls == null, once we
+ // root cause where we should be using runOnPageScrollsInitialized().
+ if (mPageScrolls == null || index >= mPageScrolls.length || index < 0) {
return 0;
} else {
return mPageScrolls[index];
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 4903d77..c482ed5 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -3418,7 +3418,11 @@
return getPageDescription(page);
}
- private String getPageDescription(int page) {
+ /**
+ * @param page page index.
+ * @return Description of the page at the given page index.
+ */
+ public String getPageDescription(int page) {
int nScreens = getChildCount();
int extraScreenId = mScreenOrder.indexOf(EXTRA_EMPTY_SCREEN_ID);
if (extraScreenId >= 0 && nScreens > 1) {
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index af17cf7..de34416 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -31,7 +31,6 @@
import android.util.Log;
import android.util.SparseIntArray;
import android.view.MotionEvent;
-import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
@@ -342,24 +341,7 @@
}
@Override
- public int getCurrentScrollY() {
- // Return early if there are no items or we haven't been measured
- List<AllAppsGridAdapter.AdapterItem> items = mApps.getAdapterItems();
- if (items.isEmpty() || mNumAppsPerRow == 0 || getChildCount() == 0) {
- return -1;
- }
-
- // Calculate the y and offset for the item
- View child = getChildAt(0);
- int position = getChildAdapterPosition(child);
- if (position == NO_POSITION) {
- return -1;
- }
- return getPaddingTop() +
- getCurrentScrollY(position, getLayoutManager().getDecoratedTop(child));
- }
-
- public int getCurrentScrollY(int position, int offset) {
+ protected int getItemsHeight(int position) {
List<AllAppsGridAdapter.AdapterItem> items = mApps.getAdapterItems();
AllAppsGridAdapter.AdapterItem posItem = position < items.size()
? items.get(position) : null;
@@ -400,17 +382,7 @@
}
mCachedScrollPositions.put(position, y);
}
- return y - offset;
- }
-
- /**
- * Returns the available scroll height:
- * AvailableScrollHeight = Total height of the all items - last page height
- */
- @Override
- protected int getAvailableScrollHeight() {
- return getPaddingTop() + getCurrentScrollY(getAdapter().getItemCount(), 0)
- - getHeight() + getPaddingBottom();
+ return y;
}
public int getScrollBarTop() {
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index a4a2085..e0f1b3d 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -23,7 +23,6 @@
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
-import static com.android.launcher3.util.SystemUiController.UI_STATE_ALLAPPS;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
@@ -37,7 +36,6 @@
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
@@ -293,11 +291,6 @@
public void setupViews(ScrimView scrimView, ActivityAllAppsContainerView<Launcher> appsView) {
mScrimView = scrimView;
mAppsView = appsView;
- if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && Utilities.ATLEAST_R) {
- mLauncher.getSystemUiController().updateUiState(UI_STATE_ALLAPPS,
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
- }
mAppsView.setScrimView(scrimView);
mAppsViewAlpha = new MultiValueAlpha(mAppsView, APPS_VIEW_INDEX_COUNT);
mAppsViewAlpha.setUpdateVisibility(true);
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 6ecbad2..02655b7 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -17,6 +17,7 @@
import android.animation.ValueAnimator;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.ArrayMap;
@@ -84,7 +85,7 @@
// These two values are necessary to ensure that the header protection is drawn correctly.
private final int mHeaderTopAdjustment;
private final int mHeaderBottomAdjustment;
- private final boolean mHeaderProtectionSupported;
+ private boolean mHeaderProtectionSupported;
protected ViewGroup mTabLayout;
private AllAppsRecyclerView mMainRV;
@@ -122,9 +123,14 @@
mHeaderBottomAdjustment = context.getResources()
.getDimensionPixelSize(R.dimen.all_apps_header_bottom_adjustment);
mHeaderProtectionSupported = context.getResources().getBoolean(
- R.bool.config_header_protection_supported)
- // TODO(b/208599118) Support header protection for bottom sheet.
- && !ActivityContext.lookupContext(context).getDeviceProfile().isTablet;
+ R.bool.config_header_protection_supported);
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ mHeaderProtectionSupported = getContext().getResources().getBoolean(
+ R.bool.config_header_protection_supported);
}
@Override
diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java
index b70cb13..5edd431 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -155,13 +155,18 @@
mWorkModeSwitch.getResources().getDimensionPixelSize(R.dimen.qsb_widget_height);
}
if (!mAllApps.mActivityContext.getDeviceProfile().isGestureMode){
- workFabMarginBottom += mAllApps.mActivityContext.getDeviceProfile().getInsets().bottom;
+ if (mDeviceProfile.isTaskbarPresent){
+ workFabMarginBottom += mDeviceProfile.taskbarSize;
+ } else {
+ workFabMarginBottom +=
+ mAllApps.mActivityContext.getDeviceProfile().getInsets().bottom;
+ }
}
lp.bottomMargin = workFabMarginBottom;
- int totalScreenWidth = mDeviceProfile.widthPx;
+ int allAppsContainerWidth = mAllApps.getVisibleContainerView().getWidth();
int personalWorkTabWidth =
mAllApps.mActivityContext.getAppsView().getFloatingHeaderView().getTabWidth();
- lp.rightMargin = lp.leftMargin = (totalScreenWidth - personalWorkTabWidth) / 2;
+ lp.rightMargin = lp.leftMargin = (allAppsContainerWidth - personalWorkTabWidth) / 2;
if (mWorkModeSwitch.getParent() != mAllApps) {
mAllApps.addView(mWorkModeSwitch);
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 9e1cd28..38b5c65 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -96,6 +96,9 @@
public static final BooleanFlag ENABLE_QUICK_SEARCH = new DeviceFlag("ENABLE_QUICK_SEARCH",
true, "Use quick search behavior.");
+ public static final BooleanFlag ENABLE_HIDE_HEADER = new DeviceFlag("ENABLE_HIDE_HEADER",
+ true, "Hide header on keyboard before typing in all apps");
+
public static final BooleanFlag COLLECT_SEARCH_HISTORY = new DeviceFlag(
"COLLECT_SEARCH_HISTORY", false, "Allow launcher to collect search history for log");
diff --git a/src/com/android/launcher3/folder/PreviewItemManager.java b/src/com/android/launcher3/folder/PreviewItemManager.java
index 6355b62..2e5f2e5 100644
--- a/src/com/android/launcher3/folder/PreviewItemManager.java
+++ b/src/com/android/launcher3/folder/PreviewItemManager.java
@@ -79,6 +79,8 @@
private int mPrevTopPadding = -1;
private Drawable mReferenceDrawable = null;
+ private int mNumOfPrevItems = 0;
+
// These hold the first page preview items
private ArrayList<PreviewItemDrawingParams> mFirstPageParams = new ArrayList<>();
// These hold the current page preview items. It is empty if the current page is the first page.
@@ -254,7 +256,6 @@
void buildParamsForPage(int page, ArrayList<PreviewItemDrawingParams> params, boolean animate) {
List<WorkspaceItemInfo> items = mIcon.getPreviewItemsOnPage(page);
- int prevNumItems = params.size();
// We adjust the size of the list to match the number of items in the preview.
while (items.size() < params.size()) {
@@ -278,8 +279,9 @@
mReferenceDrawable = p.drawable;
}
} else {
- FolderPreviewItemAnim anim = new FolderPreviewItemAnim(this, p, i, prevNumItems, i,
- numItemsInFirstPagePreview, DROP_IN_ANIMATION_DURATION, null);
+ FolderPreviewItemAnim anim = new FolderPreviewItemAnim(this, p, i,
+ mNumOfPrevItems, i, numItemsInFirstPagePreview, DROP_IN_ANIMATION_DURATION,
+ null);
if (p.anim != null) {
if (p.anim.hasEqualFinalState(anim)) {
@@ -318,7 +320,9 @@
}
void updatePreviewItems(boolean animate) {
+ int numOfPrevItemsAux = mFirstPageParams.size();
buildParamsForPage(0, mFirstPageParams, animate);
+ mNumOfPrevItems = numOfPrevItemsAux;
}
void updatePreviewItems(Predicate<WorkspaceItemInfo> itemCheck) {
diff --git a/src/com/android/launcher3/model/DeviceGridState.java b/src/com/android/launcher3/model/DeviceGridState.java
index 35fcb78..46f0b0b 100644
--- a/src/com/android/launcher3/model/DeviceGridState.java
+++ b/src/com/android/launcher3/model/DeviceGridState.java
@@ -134,10 +134,13 @@
* DeviceGridState without migration, or false otherwise.
*/
public boolean isCompatible(DeviceGridState other) {
- if (this == other) return true;
- if (other == null) return false;
- return mNumHotseat == other.mNumHotseat
- && Objects.equals(mGridSizeString, other.mGridSizeString);
+ if (this == other) {
+ return true;
+ }
+ if (other == null) {
+ return false;
+ }
+ return Objects.equals(mDbFile, other.mDbFile);
}
public Integer getColumns() {
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 49d97d2..8e7a10c 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -72,6 +72,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.Optional;
import java.util.stream.Collectors;
/**
@@ -244,23 +245,32 @@
mNotificationContainer);
}
+ private void initializeSystemShortcuts(List<SystemShortcut> shortcuts) {
+ if (shortcuts.isEmpty()) {
+ return;
+ }
+ // If there is only 1 shortcut, add it to its own container so it can show text and icon
+ if (shortcuts.size() == 1) {
+ initializeSystemShortcut(R.layout.system_shortcut, this, shortcuts.get(0));
+ return;
+ }
+ mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_icons, this);
+ for (SystemShortcut shortcut : shortcuts) {
+ initializeSystemShortcut(
+ R.layout.system_shortcut_icon_only, mSystemShortcutContainer,
+ shortcut);
+ }
+ }
+
@TargetApi(Build.VERSION_CODES.P)
public void populateAndShow(final BubbleTextView originalIcon, int shortcutCount,
- final List<NotificationKeyData> notificationKeys, List<SystemShortcut> systemShortcuts) {
+ final List<NotificationKeyData> notificationKeys, List<SystemShortcut> shortcuts) {
mNumNotifications = notificationKeys.size();
mOriginalIcon = originalIcon;
boolean hasDeepShortcuts = shortcutCount > 0;
mContainerWidth = getResources().getDimensionPixelSize(R.dimen.bg_popup_item_width);
- // if there are deep shortcuts, we might want to increase the width of shortcuts to fit
- // horizontally laid out system shortcuts.
- if (hasDeepShortcuts) {
- mContainerWidth = Math.max(mContainerWidth,
- systemShortcuts.size() * getResources()
- .getDimensionPixelSize(R.dimen.system_shortcut_header_icon_touch_size)
- );
- }
// Add views
if (mNumNotifications > 0) {
// Add notification entries
@@ -279,6 +289,24 @@
mDeepShortcutContainer = findViewById(R.id.deep_shortcuts_container);
}
if (hasDeepShortcuts) {
+ // Remove the widget shortcut fom the list
+ List<SystemShortcut> systemShortcuts = shortcuts
+ .stream()
+ .filter(shortcut -> !(shortcut instanceof SystemShortcut.Widgets))
+ .collect(Collectors.toList());
+ Optional<SystemShortcut.Widgets> widgetShortcutOpt = shortcuts
+ .stream()
+ .filter(shortcut -> shortcut instanceof SystemShortcut.Widgets)
+ .map(SystemShortcut.Widgets.class::cast)
+ .findFirst();
+
+ // if there are deep shortcuts, we might want to increase the width of shortcuts to fit
+ // horizontally laid out system shortcuts.
+ mContainerWidth = Math.max(mContainerWidth,
+ systemShortcuts.size() * getResources()
+ .getDimensionPixelSize(R.dimen.system_shortcut_header_icon_touch_size)
+ );
+
mDeepShortcutContainer.setVisibility(View.VISIBLE);
for (int i = shortcutCount; i > 0; i--) {
@@ -288,30 +316,19 @@
}
updateHiddenShortcuts();
- if (!systemShortcuts.isEmpty()) {
- for (SystemShortcut shortcut : systemShortcuts) {
- if (shortcut instanceof SystemShortcut.Widgets) {
- if (mWidgetContainer == null) {
- mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container,
- this);
- }
- initializeWidgetShortcut(mWidgetContainer, shortcut);
- }
+ if (widgetShortcutOpt.isPresent()) {
+ if (mWidgetContainer == null) {
+ mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container,
+ this);
}
- mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_icons, this);
-
- for (SystemShortcut shortcut : systemShortcuts) {
- if (!(shortcut instanceof SystemShortcut.Widgets)) {
- initializeSystemShortcut(
- R.layout.system_shortcut_icon_only, mSystemShortcutContainer,
- shortcut);
- }
- }
+ initializeWidgetShortcut(mWidgetContainer, widgetShortcutOpt.get());
}
+
+ initializeSystemShortcuts(systemShortcuts);
} else {
mDeepShortcutContainer.setVisibility(View.GONE);
- if (!systemShortcuts.isEmpty()) {
- for (SystemShortcut shortcut : systemShortcuts) {
+ if (!shortcuts.isEmpty()) {
+ for (SystemShortcut shortcut : shortcuts) {
initializeSystemShortcut(R.layout.system_shortcut, this, shortcut);
}
}
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 3a030a8..b76e9d5 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -139,4 +139,9 @@
public static final String MISSING_PROMISE_ICON = "b/202985412";
public static final String BAD_STATE = "b/223498680";
public static final String TASKBAR_IN_APP_STATE = "b/227657604";
+
+ public static final String REQUEST_EMULATE_DISPLAY = "emulate-display";
+ public static final String REQUEST_STOP_EMULATE_DISPLAY = "stop-emulate-display";
+ public static final String REQUEST_IS_EMULATE_DISPLAY_RUNNING = "is-emulate-display-running";
+ public static final String REQUEST_EMULATE_PRINT_DEVICE = "emulate-print-device";
}
diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java
index db43baa..37b76fb 100644
--- a/src/com/android/launcher3/touch/AllAppsSwipeController.java
+++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java
@@ -47,48 +47,88 @@
*/
public class AllAppsSwipeController extends AbstractStateChangeTouchController {
- private static final float ALLAPPS_STAGGERED_FADE_THRESHOLD = 0.5f;
+ private static final float ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD = 0.8f;
+ private static final float ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD = 0.5f;
+ private static final float ALL_APPS_SCRIM_VISIBLE_THRESHOLD = 0.1f;
+ private static final float ALL_APPS_STAGGERED_FADE_THRESHOLD = 0.5f;
- // Custom timing for NORMAL -> ALL_APPS on phones only.
- private static final float WORKSPACE_MOTION_START = 0.1667f;
- private static final float ALL_APPS_STATE_TRANSITION = 0.305f;
- private static final float ALL_APPS_FADE_END = 0.4717f;
+ public static final Interpolator ALL_APPS_SCRIM_RESPONDER =
+ Interpolators.clampToProgress(
+ LINEAR, ALL_APPS_SCRIM_VISIBLE_THRESHOLD, ALL_APPS_STAGGERED_FADE_THRESHOLD);
+ public static final Interpolator ALL_APPS_CLAMPING_RESPONDER =
+ Interpolators.clampToProgress(
+ LINEAR,
+ 1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
+ 1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD);
+
+ // ---- Custom interpolators for NORMAL -> ALL_APPS on phones only. ----
+
+ private static final float WORKSPACE_MOTION_START_ATOMIC = 0.1667f;
+ private static final float ALL_APPS_STATE_TRANSITION_ATOMIC = 0.305f;
+ private static final float ALL_APPS_STATE_TRANSITION_MANUAL = 0.4f;
+ private static final float ALL_APPS_FADE_END_ATOMIC = 0.4717f;
private static final float ALL_APPS_FULL_DEPTH_PROGRESS = 0.5f;
- public static final Interpolator ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER =
- Interpolators.clampToProgress(LINEAR, 0, ALLAPPS_STAGGERED_FADE_THRESHOLD);
- public static final Interpolator ALLAPPS_STAGGERED_FADE_LATE_RESPONDER =
- Interpolators.clampToProgress(LINEAR, ALLAPPS_STAGGERED_FADE_THRESHOLD, 1f);
+ private static final Interpolator LINEAR_EARLY_MANUAL =
+ Interpolators.clampToProgress(LINEAR, 0f, ALL_APPS_STATE_TRANSITION_MANUAL);
+ private static final Interpolator STEP_TRANSITION_ATOMIC =
+ Interpolators.clampToProgress(FINAL_FRAME, 0f, ALL_APPS_STATE_TRANSITION_ATOMIC);
+ private static final Interpolator STEP_TRANSITION_MANUAL =
+ Interpolators.clampToProgress(FINAL_FRAME, 0f, ALL_APPS_STATE_TRANSITION_MANUAL);
- // Custom interpolators for NORMAL -> ALL_APPS on phones only.
// The blur to All Apps is set to be complete when the interpolator is at 0.5.
- public static final Interpolator BLUR =
+ private static final Interpolator BLUR_ADJUSTED =
+ Interpolators.mapToProgress(LINEAR, 0f, ALL_APPS_FULL_DEPTH_PROGRESS);
+ public static final Interpolator BLUR_ATOMIC =
Interpolators.clampToProgress(
- Interpolators.mapToProgress(
- LINEAR, 0f, ALL_APPS_FULL_DEPTH_PROGRESS),
- WORKSPACE_MOTION_START, ALL_APPS_STATE_TRANSITION);
- public static final Interpolator WORKSPACE_FADE =
- Interpolators.clampToProgress(FINAL_FRAME, 0f, ALL_APPS_STATE_TRANSITION);
- public static final Interpolator WORKSPACE_SCALE =
+ BLUR_ADJUSTED, WORKSPACE_MOTION_START_ATOMIC, ALL_APPS_STATE_TRANSITION_ATOMIC);
+ public static final Interpolator BLUR_MANUAL =
+ Interpolators.clampToProgress(BLUR_ADJUSTED, 0f, ALL_APPS_STATE_TRANSITION_MANUAL);
+
+ public static final Interpolator WORKSPACE_FADE_ATOMIC = STEP_TRANSITION_ATOMIC;
+ public static final Interpolator WORKSPACE_FADE_MANUAL = STEP_TRANSITION_MANUAL;
+
+ public static final Interpolator WORKSPACE_SCALE_ATOMIC =
Interpolators.clampToProgress(
- EMPHASIZED_ACCELERATE, WORKSPACE_MOTION_START, ALL_APPS_STATE_TRANSITION);
- public static final Interpolator HOTSEAT_FADE = WORKSPACE_FADE;
- public static final Interpolator HOTSEAT_SCALE = HOTSEAT_FADE;
- public static final Interpolator HOTSEAT_TRANSLATE =
+ EMPHASIZED_ACCELERATE, WORKSPACE_MOTION_START_ATOMIC,
+ ALL_APPS_STATE_TRANSITION_ATOMIC);
+ public static final Interpolator WORKSPACE_SCALE_MANUAL = LINEAR_EARLY_MANUAL;
+
+ public static final Interpolator HOTSEAT_FADE_ATOMIC = STEP_TRANSITION_ATOMIC;
+ public static final Interpolator HOTSEAT_FADE_MANUAL = STEP_TRANSITION_MANUAL;
+
+ public static final Interpolator HOTSEAT_SCALE_ATOMIC = STEP_TRANSITION_ATOMIC;
+ public static final Interpolator HOTSEAT_SCALE_MANUAL = LINEAR_EARLY_MANUAL;
+
+ public static final Interpolator HOTSEAT_TRANSLATE_ATOMIC =
Interpolators.clampToProgress(
- EMPHASIZED_ACCELERATE, WORKSPACE_MOTION_START, ALL_APPS_STATE_TRANSITION);
- public static final Interpolator SCRIM_FADE =
+ EMPHASIZED_ACCELERATE, WORKSPACE_MOTION_START_ATOMIC,
+ ALL_APPS_STATE_TRANSITION_ATOMIC);
+ public static final Interpolator HOTSEAT_TRANSLATE_MANUAL = STEP_TRANSITION_MANUAL;
+
+ public static final Interpolator SCRIM_FADE_ATOMIC =
Interpolators.clampToProgress(
Interpolators.mapToProgress(LINEAR, 0f, 0.8f),
- WORKSPACE_MOTION_START, ALL_APPS_STATE_TRANSITION);
- public static final Interpolator ALL_APPS_FADE =
+ WORKSPACE_MOTION_START_ATOMIC, ALL_APPS_STATE_TRANSITION_ATOMIC);
+ public static final Interpolator SCRIM_FADE_MANUAL = LINEAR_EARLY_MANUAL;
+
+ public static final Interpolator ALL_APPS_FADE_ATOMIC =
Interpolators.clampToProgress(
- Interpolators.mapToProgress(DECELERATED_EASE, 0.2f, 1.0f),
- ALL_APPS_STATE_TRANSITION, ALL_APPS_FADE_END);
- public static final Interpolator ALL_APPS_VERTICAL_PROGRESS =
+ Interpolators.mapToProgress(DECELERATED_EASE, 0.2f, 1f),
+ ALL_APPS_STATE_TRANSITION_ATOMIC, ALL_APPS_FADE_END_ATOMIC);
+ public static final Interpolator ALL_APPS_FADE_MANUAL =
+ Interpolators.clampToProgress(LINEAR, ALL_APPS_STATE_TRANSITION_MANUAL, 1f);
+
+ public static final Interpolator ALL_APPS_VERTICAL_PROGRESS_ATOMIC =
Interpolators.clampToProgress(
- Interpolators.mapToProgress(EMPHASIZED_DECELERATE, 0.4f, 1.0f),
- ALL_APPS_STATE_TRANSITION, 1.0f);
+ Interpolators.mapToProgress(EMPHASIZED_DECELERATE, 0.4f, 1f),
+ ALL_APPS_STATE_TRANSITION_ATOMIC, 1f);
+ public static final Interpolator ALL_APPS_VERTICAL_PROGRESS_MANUAL =
+ Interpolators.clampToProgress(
+ Interpolators.mapToProgress(LINEAR, ALL_APPS_STATE_TRANSITION_MANUAL, 1f),
+ ALL_APPS_STATE_TRANSITION_MANUAL, 1f);
+
+ // --------
public AllAppsSwipeController(Launcher l) {
super(l, SingleAxisSwipeDetector.VERTICAL);
@@ -141,6 +181,7 @@
protected StateAnimationConfig getConfigForStates(LauncherState fromState,
LauncherState toState) {
StateAnimationConfig config = super.getConfigForStates(fromState, toState);
+ config.userControlled = true;
if (fromState == NORMAL && toState == ALL_APPS) {
applyNormalToAllAppsAnimConfig(mLauncher, config);
} else if (fromState == ALL_APPS && toState == NORMAL) {
@@ -150,36 +191,75 @@
}
/**
- * Applies Animation config values for transition from all apps to home
+ * Applies Animation config values for transition from all apps to home.
*/
public static void applyAllAppsToNormalConfig(Launcher launcher, StateAnimationConfig config) {
- boolean isTablet = launcher.getDeviceProfile().isTablet;
- config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
- config.setInterpolator(ANIM_ALL_APPS_FADE, isTablet
- ? FINAL_FRAME : ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
- if (!isTablet) {
- config.setInterpolator(ANIM_WORKSPACE_FADE, INSTANT);
+ if (launcher.getDeviceProfile().isTablet) {
+ config.setInterpolator(ANIM_SCRIM_FADE,
+ Interpolators.reverse(ALL_APPS_SCRIM_RESPONDER));
+ config.setInterpolator(ANIM_ALL_APPS_FADE, FINAL_FRAME);
+ if (!config.userControlled) {
+ config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_ACCELERATE);
+ }
+ } else {
+ if (config.userControlled) {
+ config.setInterpolator(ANIM_DEPTH, Interpolators.reverse(BLUR_MANUAL));
+ config.setInterpolator(ANIM_WORKSPACE_FADE,
+ Interpolators.reverse(WORKSPACE_FADE_MANUAL));
+ config.setInterpolator(ANIM_WORKSPACE_SCALE,
+ Interpolators.reverse(WORKSPACE_SCALE_MANUAL));
+ config.setInterpolator(ANIM_HOTSEAT_FADE,
+ Interpolators.reverse(HOTSEAT_FADE_MANUAL));
+ config.setInterpolator(ANIM_HOTSEAT_SCALE,
+ Interpolators.reverse(HOTSEAT_SCALE_MANUAL));
+ config.setInterpolator(ANIM_HOTSEAT_TRANSLATE,
+ Interpolators.reverse(HOTSEAT_TRANSLATE_MANUAL));
+ config.setInterpolator(ANIM_SCRIM_FADE, Interpolators.reverse(SCRIM_FADE_MANUAL));
+ config.setInterpolator(ANIM_ALL_APPS_FADE,
+ Interpolators.reverse(ALL_APPS_FADE_MANUAL));
+ config.setInterpolator(ANIM_VERTICAL_PROGRESS,
+ Interpolators.reverse(ALL_APPS_VERTICAL_PROGRESS_MANUAL));
+ } else {
+ config.setInterpolator(ANIM_SCRIM_FADE,
+ Interpolators.reverse(ALL_APPS_SCRIM_RESPONDER));
+ config.setInterpolator(ANIM_ALL_APPS_FADE, ALL_APPS_CLAMPING_RESPONDER);
+ config.setInterpolator(ANIM_WORKSPACE_FADE, INSTANT);
+ config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_ACCELERATE);
+ }
}
}
/**
- * Applies Animation config values for transition from home to all apps
+ * Applies Animation config values for transition from home to all apps.
*/
- public static void applyNormalToAllAppsAnimConfig(Launcher launcher,
- StateAnimationConfig config) {
+ public static void applyNormalToAllAppsAnimConfig(
+ Launcher launcher, StateAnimationConfig config) {
if (launcher.getDeviceProfile().isTablet) {
- config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
config.setInterpolator(ANIM_ALL_APPS_FADE, INSTANT);
+ config.setInterpolator(ANIM_SCRIM_FADE, ALL_APPS_SCRIM_RESPONDER);
+ if (!config.userControlled) {
+ config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_DECELERATE);
+ }
} else {
- config.setInterpolator(ANIM_DEPTH, BLUR);
- config.setInterpolator(ANIM_WORKSPACE_FADE, WORKSPACE_FADE);
- config.setInterpolator(ANIM_WORKSPACE_SCALE, WORKSPACE_SCALE);
- config.setInterpolator(ANIM_HOTSEAT_FADE, HOTSEAT_FADE);
- config.setInterpolator(ANIM_HOTSEAT_SCALE, HOTSEAT_SCALE);
- config.setInterpolator(ANIM_HOTSEAT_TRANSLATE, HOTSEAT_TRANSLATE);
- config.setInterpolator(ANIM_SCRIM_FADE, SCRIM_FADE);
- config.setInterpolator(ANIM_ALL_APPS_FADE, ALL_APPS_FADE);
- config.setInterpolator(ANIM_VERTICAL_PROGRESS, ALL_APPS_VERTICAL_PROGRESS);
+ config.setInterpolator(ANIM_DEPTH, config.userControlled ? BLUR_MANUAL : BLUR_ATOMIC);
+ config.setInterpolator(ANIM_WORKSPACE_FADE,
+ config.userControlled ? WORKSPACE_FADE_MANUAL : WORKSPACE_FADE_ATOMIC);
+ config.setInterpolator(ANIM_WORKSPACE_SCALE,
+ config.userControlled ? WORKSPACE_SCALE_MANUAL : WORKSPACE_SCALE_ATOMIC);
+ config.setInterpolator(ANIM_HOTSEAT_FADE,
+ config.userControlled ? HOTSEAT_FADE_MANUAL : HOTSEAT_FADE_ATOMIC);
+ config.setInterpolator(ANIM_HOTSEAT_SCALE,
+ config.userControlled ? HOTSEAT_SCALE_MANUAL : HOTSEAT_SCALE_ATOMIC);
+ config.setInterpolator(ANIM_HOTSEAT_TRANSLATE,
+ config.userControlled ? HOTSEAT_TRANSLATE_MANUAL : HOTSEAT_TRANSLATE_ATOMIC);
+ config.setInterpolator(ANIM_SCRIM_FADE,
+ config.userControlled ? SCRIM_FADE_MANUAL : SCRIM_FADE_ATOMIC);
+ config.setInterpolator(ANIM_ALL_APPS_FADE,
+ config.userControlled ? ALL_APPS_FADE_MANUAL : ALL_APPS_FADE_ATOMIC);
+ config.setInterpolator(ANIM_VERTICAL_PROGRESS,
+ config.userControlled
+ ? ALL_APPS_VERTICAL_PROGRESS_MANUAL
+ : ALL_APPS_VERTICAL_PROGRESS_ATOMIC);
}
}
}
diff --git a/src/com/android/launcher3/util/HorizontalInsettableView.java b/src/com/android/launcher3/util/HorizontalInsettableView.java
index 7979bc0..486b73d 100644
--- a/src/com/android/launcher3/util/HorizontalInsettableView.java
+++ b/src/com/android/launcher3/util/HorizontalInsettableView.java
@@ -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 @@
*/
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);
+ }
+ };
}
diff --git a/src/com/android/launcher3/util/SystemUiController.java b/src/com/android/launcher3/util/SystemUiController.java
index 630df7e..6945983 100644
--- a/src/com/android/launcher3/util/SystemUiController.java
+++ b/src/com/android/launcher3/util/SystemUiController.java
@@ -19,6 +19,10 @@
import android.view.View;
import android.view.Window;
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
/**
@@ -31,15 +35,26 @@
public static final int UI_STATE_SCRIM_VIEW = 1;
public static final int UI_STATE_WIDGET_BOTTOM_SHEET = 2;
public static final int UI_STATE_FULLSCREEN_TASK = 3;
- public static final int UI_STATE_ALLAPPS = 4;
public static final int FLAG_LIGHT_NAV = 1 << 0;
public static final int FLAG_DARK_NAV = 1 << 1;
public static final int FLAG_LIGHT_STATUS = 1 << 2;
public static final int FLAG_DARK_STATUS = 1 << 3;
+ /**
+ * Security type based on WifiConfiguration.KeyMgmt
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, value = {
+ FLAG_LIGHT_NAV,
+ FLAG_DARK_NAV,
+ FLAG_LIGHT_STATUS,
+ FLAG_DARK_STATUS,
+ })
+ public @interface SystemUiControllerFlags {}
+
private final Window mWindow;
- private final int[] mStates = new int[5];
+ private final int[] mStates = new int[4];
public SystemUiController(Window window) {
mWindow = window;
@@ -50,7 +65,7 @@
? (FLAG_LIGHT_NAV | FLAG_LIGHT_STATUS) : (FLAG_DARK_NAV | FLAG_DARK_STATUS));
}
- public void updateUiState(int uiState, int flags) {
+ public void updateUiState(int uiState, @SystemUiControllerFlags int flags) {
if (mStates[uiState] == flags) {
return;
}
diff --git a/src/com/android/launcher3/util/UiThreadHelper.java b/src/com/android/launcher3/util/UiThreadHelper.java
index 8df3f8a..7e6711f 100644
--- a/src/com/android/launcher3/util/UiThreadHelper.java
+++ b/src/com/android/launcher3/util/UiThreadHelper.java
@@ -69,10 +69,6 @@
activityContext.getStatsLogManager().logger()
.log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED);
return;
- } else {
- // print which stack trace failed.
- Log.e("Launcher", "hideKeyboard ignored.", new Exception());
- // Then attempt to use the old logic.
}
}
// Since the launcher context cannot be accessed directly from callback, adding secondary
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
index 0e5a7d7..e6b9dca 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
@@ -21,7 +21,6 @@
import static com.android.launcher3.recyclerview.ViewHolderBinder.POSITION_LAST;
import android.content.Context;
-import android.graphics.Rect;
import android.os.Process;
import android.util.Log;
import android.util.SparseArray;
@@ -36,7 +35,6 @@
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.Adapter;
-import androidx.recyclerview.widget.RecyclerView.LayoutParams;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import com.android.launcher3.R;
@@ -80,10 +78,10 @@
private static final boolean DEBUG = false;
/** Uniquely identifies widgets list view type within the app. */
- private static final int VIEW_TYPE_WIDGETS_SPACE = R.id.view_type_widgets_space;
- private static final int VIEW_TYPE_WIDGETS_LIST = R.id.view_type_widgets_list;
- private static final int VIEW_TYPE_WIDGETS_HEADER = R.id.view_type_widgets_header;
- private static final int VIEW_TYPE_WIDGETS_SEARCH_HEADER = R.id.view_type_widgets_search_header;
+ public static final int VIEW_TYPE_WIDGETS_SPACE = R.id.view_type_widgets_space;
+ public static final int VIEW_TYPE_WIDGETS_LIST = R.id.view_type_widgets_list;
+ public static final int VIEW_TYPE_WIDGETS_HEADER = R.id.view_type_widgets_header;
+ public static final int VIEW_TYPE_WIDGETS_SEARCH_HEADER = R.id.view_type_widgets_search_header;
private final Context mContext;
private final WidgetsDiffReporter mDiffReporter;
@@ -103,7 +101,6 @@
@Nullable private Predicate<WidgetsListBaseEntry> mFilter = null;
@Nullable private RecyclerView mRecyclerView;
@Nullable private PackageUserKey mPendingClickHeader;
- private final int mSpacingBetweenEntries;
private int mMaxSpanSize = 4;
public WidgetsListAdapter(Context context, LayoutInflater layoutInflater,
@@ -133,28 +130,11 @@
mViewHolderBinders.put(
VIEW_TYPE_WIDGETS_SPACE,
new WidgetsSpaceViewHolderBinder(emptySpaceHeightProvider));
- mSpacingBetweenEntries =
- context.getResources().getDimensionPixelSize(R.dimen.widget_list_entry_spacing);
}
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
mRecyclerView = recyclerView;
-
- mRecyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
- @Override
- public void getItemOffsets(
- @NonNull Rect outRect,
- @NonNull View view,
- @NonNull RecyclerView parent,
- @NonNull RecyclerView.State state) {
- super.getItemOffsets(outRect, view, parent, state);
- int position = ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition();
- boolean isHeader =
- view.getTag(R.id.tag_widget_entry) instanceof WidgetsListBaseEntry.Header;
- outRect.top += position > 0 && isHeader ? mSpacingBetweenEntries : 0;
- }
- });
}
@Override
@@ -286,7 +266,6 @@
listPos |= POSITION_LAST;
}
viewHolderBinder.bindViewHolder(holder, mVisibleEntries.get(pos), listPos, payloads);
- holder.itemView.setTag(R.id.tag_widget_entry, entry);
}
@Override
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListDrawableFactory.java b/src/com/android/launcher3/widget/picker/WidgetsListDrawableFactory.java
index c61e3a4..984a274 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListDrawableFactory.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListDrawableFactory.java
@@ -27,6 +27,7 @@
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.InsetDrawable;
import android.graphics.drawable.RippleDrawable;
import android.graphics.drawable.StateListDrawable;
@@ -40,6 +41,8 @@
private final float mMiddleCornerRadius;
private final ColorStateList mSurfaceColor;
private final ColorStateList mRippleColor;
+ private final int mVerticalPadding;
+ private final int mHeaderMargin;
WidgetsListDrawableFactory(Context context) {
Resources res = context.getResources();
@@ -48,6 +51,9 @@
mSurfaceColor = context.getColorStateList(R.color.surface);
mRippleColor = ColorStateList.valueOf(
Themes.getAttrColor(context, android.R.attr.colorControlHighlight));
+ mVerticalPadding =
+ res.getDimensionPixelSize(R.dimen.widget_list_header_view_vertical_padding);
+ mHeaderMargin = res.getDimensionPixelSize(R.dimen.widget_list_entry_spacing);
}
/**
@@ -74,7 +80,10 @@
stateList.addState(
LAST.mStateSet,
createRoundedRectDrawable(mMiddleCornerRadius, mTopBottomCornerRadius));
- return new RippleDrawable(mRippleColor, /* content= */ stateList, /* mask= */ stateList);
+ RippleDrawable ripple =
+ new RippleDrawable(mRippleColor, /* content= */ stateList, /* mask= */ stateList);
+ ripple.setPadding(0, mVerticalPadding, 0, mVerticalPadding);
+ return new InsetDrawable(ripple, 0, mHeaderMargin, 0, 0);
}
/**
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
index bdf646b..4c0e0d5 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
@@ -19,24 +19,15 @@
import android.content.Context;
import android.graphics.Point;
import android.util.AttributeSet;
+import android.util.SparseIntArray;
import android.view.MotionEvent;
-import android.view.View;
-import android.widget.TableLayout;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.FastScrollRecyclerView;
import com.android.launcher3.R;
-import com.android.launcher3.views.ActivityContext;
-import com.android.launcher3.widget.model.WidgetListSpaceEntry;
-import com.android.launcher3.widget.model.WidgetsListBaseEntry;
-import com.android.launcher3.widget.model.WidgetsListContentEntry;
-import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
-import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry;
-import com.android.launcher3.widget.picker.WidgetsSpaceViewHolderBinder.EmptySpaceView;
/**
* The widgets recycler view.
@@ -51,12 +42,13 @@
private boolean mTouchDownOnScroller;
private HeaderViewDimensionsProvider mHeaderViewDimensionsProvider;
- // Cached sizes
- private int mLastVisibleWidgetContentTableHeight = 0;
- private int mWidgetHeaderHeight = 0;
- private int mWidgetEmptySpaceHeight = 0;
-
- private final int mSpacingBetweenEntries;
+ /**
+ * There is always 1 or 0 item of VIEW_TYPE_WIDGETS_LIST. Other types have fixes sizes, so the
+ * the size can be used for all other items of same type. Caching the last know size for
+ * VIEW_TYPE_WIDGETS_LIST allows us to use it to estimate full size even when
+ * VIEW_TYPE_WIDGETS_LIST is not visible on the screen.
+ */
+ private final SparseIntArray mCachedSizes = new SparseIntArray();
public WidgetsRecyclerView(Context context) {
this(context, null);
@@ -71,13 +63,6 @@
super(context, attrs, defStyleAttr);
mScrollbarTop = getResources().getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
addOnItemTouchListener(this);
-
- ActivityContext activity = ActivityContext.lookupContext(getContext());
- DeviceProfile grid = activity.getDeviceProfile();
-
- // The spacing used between entries.
- mSpacingBetweenEntries =
- getResources().getDimensionPixelSize(R.dimen.widget_list_entry_spacing);
}
@Override
@@ -138,67 +123,6 @@
synchronizeScrollBarThumbOffsetToViewScroll(scrollY, getAvailableScrollHeight());
}
- @Override
- public int getCurrentScrollY() {
- // Skip early if widgets are not bound.
- if (isModelNotReady() || getChildCount() == 0) {
- return -1;
- }
-
- int rowIndex = -1;
- View child = null;
-
- LayoutManager layoutManager = getLayoutManager();
- if (layoutManager instanceof LinearLayoutManager) {
- // Use the LayoutManager as the source of truth for visible positions. During
- // animations, the view group child may not correspond to the visible views that appear
- // at the top.
- rowIndex = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
- child = layoutManager.findViewByPosition(rowIndex);
- }
-
- if (child == null) {
- // If the layout manager returns null for any reason, which can happen before layout
- // has occurred for the position, then look at the child of this view as a ViewGroup.
- child = getChildAt(0);
- rowIndex = getChildPosition(child);
- }
-
- for (int i = 0; i < getChildCount(); i++) {
- View view = getChildAt(i);
- if (view instanceof TableLayout) {
- // This assumes there is ever only one content shown in this recycler view.
- mLastVisibleWidgetContentTableHeight = view.getMeasuredHeight();
- } else if (view instanceof WidgetsListHeader
- && mWidgetHeaderHeight == 0
- && view.getMeasuredHeight() > 0) {
- // This assumes all header views are of the same height.
- mWidgetHeaderHeight = view.getMeasuredHeight();
- } else if (view instanceof EmptySpaceView && view.getMeasuredHeight() > 0) {
- mWidgetEmptySpaceHeight = view.getMeasuredHeight();
- }
- }
-
- int scrollPosition = getItemsHeight(rowIndex);
- int offset = getLayoutManager().getDecoratedTop(child);
-
- return getPaddingTop() + scrollPosition - offset;
- }
-
- /**
- * Returns the available scroll height, in pixel.
- *
- * <p>If the recycler view can't be scrolled, returns 0.
- */
- @Override
- protected int getAvailableScrollHeight() {
- // AvailableScrollHeight = Total height of the all items - first page height
- int firstPageHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
- int totalHeightOfAllItems = getItemsHeight(/* untilIndex= */ mAdapter.getItemCount());
- int availableScrollHeight = totalHeightOfAllItems - firstPageHeight;
- return Math.max(0, availableScrollHeight);
- }
-
private boolean isModelNotReady() {
return mAdapter.getItemCount() == 0;
}
@@ -246,28 +170,27 @@
* <p>If the untilIndex is larger than the total number of items in this adapter, returns the
* sum of all items' height.
*/
- private int getItemsHeight(int untilIndex) {
+ @Override
+ protected int getItemsHeight(int untilIndex) {
+ // Initialize cache
+ int childCount = Math.min(getChildCount(), getAdapter().getItemCount());
+ int startPosition;
+ if (childCount > 0
+ && ((startPosition = getChildAdapterPosition(getChildAt(0))) != NO_POSITION)) {
+ for (int i = 0; i < childCount; i++) {
+ mCachedSizes.put(
+ mAdapter.getItemViewType(startPosition + i),
+ getChildAt(i).getMeasuredHeight());
+ }
+ }
+
if (untilIndex > mAdapter.getItems().size()) {
untilIndex = mAdapter.getItems().size();
}
int totalItemsHeight = 0;
for (int i = 0; i < untilIndex; i++) {
- WidgetsListBaseEntry entry = mAdapter.getItems().get(i);
- if (entry instanceof WidgetsListHeaderEntry
- || entry instanceof WidgetsListSearchHeaderEntry) {
- totalItemsHeight += mWidgetHeaderHeight;
- if (i > 0) {
- // Each header contains the spacing between entries as top decoration, except
- // the first one.
- totalItemsHeight += mSpacingBetweenEntries;
- }
- } else if (entry instanceof WidgetsListContentEntry) {
- totalItemsHeight += mLastVisibleWidgetContentTableHeight;
- } else if (entry instanceof WidgetListSpaceEntry) {
- totalItemsHeight += mWidgetEmptySpaceHeight;
- } else {
- throw new UnsupportedOperationException("Can't estimate height for " + entry);
- }
+ int type = mAdapter.getItemViewType(i);
+ totalItemsHeight += mCachedSizes.get(type);
}
return totalItemsHeight;
}
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index e00b569..0d74f52 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -53,6 +53,7 @@
import com.android.launcher3.widget.picker.WidgetsRecyclerView;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -376,6 +377,7 @@
@Test
@PortraitLandscape
@ScreenRecord
+ @Ignore // b/233075289
public void testDragToFolder() {
// TODO: add the use case to drag an icon to an existing folder. Currently it either fails
// on tablets or phones due to difference in resolution.
@@ -521,6 +523,25 @@
}
}
+ @Test
+ @PortraitLandscape
+ public void testDragShortcutToWorkspaceCell() throws Exception {
+ Point[] targets = getCornersAndCenterPositions();
+
+ for (Point target : targets) {
+ final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ allApps.freeze();
+ try {
+ allApps.getAppIcon(APP_NAME)
+ .openDeepShortcutMenu()
+ .getMenuItem(0)
+ .dragToWorkspace(target.x, target.y);
+ } finally {
+ allApps.unfreeze();
+ }
+ }
+ }
+
/**
* @return List of workspace grid coordinates. Those are not pixels. See {@link
* Workspace#getIconGridDimensions()}
diff --git a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
index 4c41d7e..0a0dfcb 100644
--- a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
+++ b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
@@ -32,7 +32,6 @@
public FailureWatcher(UiDevice device, LauncherInstrumentation launcher) {
mDevice = device;
mLauncher = launcher;
- Log.d("b/196820244", "FailureWatcher.ctor", new Exception());
}
@Override
@@ -48,10 +47,8 @@
public void evaluate() throws Throwable {
boolean success = false;
try {
- Log.d("b/196820244", "Before evaluate");
mDevice.executeShellCommand("cmd statusbar tracing start");
FailureWatcher.super.apply(base, description).evaluate();
- Log.d("b/196820244", "After evaluate");
success = true;
} finally {
// Save artifact for Launcher Winscope trace.
@@ -96,9 +93,7 @@
public static void onError(LauncherInstrumentation launcher, Description description,
Throwable e) {
final UiDevice device = launcher.getDevice();
- Log.d("b/196820244", "onError 1");
if (device == null) return;
- Log.d("b/196820244", "onError 2");
final File sceenshot = diagFile(description, "TestScreenshot", "png");
final File hierarchy = diagFile(description, "Hierarchy", "zip");
diff --git a/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java b/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java
index 71d8ba9..7546504 100644
--- a/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java
@@ -22,8 +22,6 @@
import androidx.annotation.NonNull;
import androidx.test.uiautomator.UiObject2;
-import java.util.function.Supplier;
-
/**
* App icon on the workspace or all apps.
*/
@@ -102,38 +100,6 @@
}
}
- /**
- * Drag an object to the given cell in workspace. The target cell must be empty.
- *
- * @param cellX zero based column number, starting from the left of the screen.
- * @param cellY zero based row number, starting from the top of the screen.
- */
- public HomeAppIcon dragToWorkspace(int cellX, int cellY) {
- try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
- LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- String.format("want to drag the icon to cell(%d, %d)", cellX, cellY))
- ) {
- final Supplier<Point> dest = () -> Workspace.getCellCenter(mLauncher, cellX, cellY);
- Workspace.dragIconToWorkspace(
- mLauncher,
- /* launchable= */ this,
- dest,
- () -> addExpectedEventsForLongClick(),
- /*expectDropEvents= */ null);
- try (LauncherInstrumentation.Closable ignore = mLauncher.addContextLayer("dragged")) {
- WorkspaceAppIcon appIcon =
- (WorkspaceAppIcon) mLauncher.getWorkspace().getWorkspaceAppIcon(mAppName);
- mLauncher.assertTrue(
- String.format(
- "The %s icon should be in the cell (%d, %d).", mAppName, cellX,
- cellY),
- appIcon.isInCell(cellX, cellY));
- return appIcon;
- }
- }
- }
-
-
/** This method requires public access, however should not be called in tests. */
@Override
public Launchable getLaunchable() {
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 9d25b1b..99cab84 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -171,7 +171,7 @@
private static final String WIDGETS_RES_ID = "primary_widgets_list_view";
private static final String CONTEXT_MENU_RES_ID = "popup_container";
private static final String TASKBAR_RES_ID = "taskbar_view";
- public static final int WAIT_TIME_MS = 60000;
+ public static final int WAIT_TIME_MS = 30000;
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
private static final String ANDROID_PACKAGE = "android";
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index e919740..42ba18c 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -228,10 +228,11 @@
private void dragIcon(UiObject2 workspace, HomeAppIcon homeAppIcon, int pageDelta) {
int pageWidth = mLauncher.getDevice().getDisplayWidth() / pagesPerScreen();
int targetX = (pageWidth / 2) + pageWidth * pageDelta;
+ int targetY = mLauncher.getVisibleBounds(workspace).centerY();
dragIconToWorkspace(
mLauncher,
homeAppIcon,
- new Point(targetX, mLauncher.getVisibleBounds(workspace).centerY()),
+ () -> new Point(targetX, targetY),
false,
false,
() -> mLauncher.expectEvent(
@@ -386,7 +387,7 @@
}
static void dragIconToWorkspace(LauncherInstrumentation launcher, Launchable launchable,
- Point dest, boolean startsActivity, boolean isWidgetShortcut,
+ Supplier<Point> dest, boolean startsActivity, boolean isWidgetShortcut,
Runnable expectLongClickEvents) {
Runnable expectDropEvents = null;
if (startsActivity || isWidgetShortcut) {
@@ -394,7 +395,7 @@
LauncherInstrumentation.EVENT_START);
}
dragIconToWorkspace(
- launcher, launchable, () -> dest, expectLongClickEvents, expectDropEvents);
+ launcher, launchable, dest, expectLongClickEvents, expectDropEvents);
}
/**
diff --git a/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java b/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java
index d8d4420..021cc98 100644
--- a/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java
+++ b/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java
@@ -17,6 +17,8 @@
import android.graphics.Point;
+import java.util.function.Supplier;
+
/** Launchable that can serve as a source for dragging and dropping to the workspace. */
interface WorkspaceDragSource {
@@ -36,7 +38,7 @@
Workspace.dragIconToWorkspace(
launcher,
launchable,
- new Point(
+ () -> new Point(
launchableCenter.x >= width
? launchableCenter.x - width / 2
: launchableCenter.x + width / 2,
@@ -47,6 +49,40 @@
}
}
+ /**
+ * Drag an object to the given cell in workspace. The target cell must be empty.
+ *
+ * @param cellX zero based column number, starting from the left of the screen.
+ * @param cellY zero based row number, starting from the top of the screen. *
+ */
+ default HomeAppIcon dragToWorkspace(int cellX, int cellY) {
+ Launchable launchable = getLaunchable();
+ final String iconName = launchable.getObject().getText();
+ LauncherInstrumentation launcher = launchable.mLauncher;
+ try (LauncherInstrumentation.Closable e = launcher.eventsCheck();
+ LauncherInstrumentation.Closable c = launcher.addContextLayer(
+ String.format("want to drag the icon to cell(%d, %d)", cellX, cellY))) {
+ final Supplier<Point> dest = () -> Workspace.getCellCenter(launcher, cellX, cellY);
+ Workspace.dragIconToWorkspace(
+ launcher,
+ launchable,
+ dest,
+ launchable::addExpectedEventsForLongClick,
+ /*expectDropEvents= */ null);
+
+ try (LauncherInstrumentation.Closable ignore = launcher.addContextLayer("dragged")) {
+ WorkspaceAppIcon appIcon =
+ (WorkspaceAppIcon) launcher.getWorkspace().getWorkspaceAppIcon(iconName);
+ launcher.assertTrue(
+ String.format(
+ "The %s icon should be in the cell (%d, %d).", iconName, cellX,
+ cellY),
+ appIcon.isInCell(cellX, cellY));
+ return appIcon;
+ }
+ }
+ }
+
/** This method requires public access, however should not be called in tests. */
Launchable getLaunchable();
}