summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher3/DeviceProfile.java48
-rw-r--r--src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java29
-rw-r--r--src/com/android/launcher3/allapps/AllAppsTransitionController.java3
-rw-r--r--src/com/android/launcher3/dragndrop/DragController.java13
-rw-r--r--src/com/android/launcher3/dragndrop/LauncherDragController.java43
-rw-r--r--src/com/android/launcher3/folder/Folder.java17
-rw-r--r--src/com/android/launcher3/folder/FolderPagedView.java3
-rw-r--r--src/com/android/launcher3/graphics/GridCustomizationsProxy.java14
-rw-r--r--src/com/android/launcher3/graphics/ShapeDelegate.kt88
-rw-r--r--src/com/android/launcher3/pageindicators/PageIndicator.java10
-rw-r--r--src/com/android/launcher3/pageindicators/PageIndicatorArrowClickListener.kt26
-rw-r--r--src/com/android/launcher3/pageindicators/PageIndicatorDots.java195
-rw-r--r--src/com/android/launcher3/touch/AllAppsSwipeController.java26
-rw-r--r--src/com/android/launcher3/touch/WorkspaceTouchListener.java2
-rw-r--r--src/com/android/launcher3/util/SimpleBroadcastReceiver.java26
-rw-r--r--src/com/android/launcher3/views/ScrimView.java3
-rw-r--r--src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java8
17 files changed, 442 insertions, 112 deletions
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index c85ca49c43..090208a33c 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -30,8 +30,8 @@ import static com.android.launcher3.testing.shared.ResourceUtils.INVALID_RESOURC
import static com.android.launcher3.testing.shared.ResourceUtils.pxFromDp;
import static com.android.launcher3.testing.shared.ResourceUtils.roundPxValueFromFloat;
import static com.android.wm.shell.Flags.enableBubbleBar;
-import static com.android.wm.shell.Flags.enableTinyTaskbar;
import static com.android.wm.shell.Flags.enableBubbleBarOnPhones;
+import static com.android.wm.shell.Flags.enableTinyTaskbar;
import android.annotation.SuppressLint;
import android.content.Context;
@@ -508,9 +508,11 @@ public class DeviceProfile {
bottomSheetOpenDuration = res.getInteger(R.integer.config_bottomSheetOpenDuration);
bottomSheetCloseDuration = res.getInteger(R.integer.config_bottomSheetCloseDuration);
- if (isTablet) {
+ if (shouldShowAllAppsOnSheet()) {
bottomSheetWorkspaceScale = workspaceContentScale;
- if (isMultiDisplay) {
+ if (Flags.allAppsBlur()) {
+ bottomSheetDepth = 2f;
+ } else if (isMultiDisplay) {
// TODO(b/259893832): Revert to use maxWallpaperScale to calculate bottomSheetDepth
// when screen recorder bug is fixed.
if (enableScalingRevealHomeAnimation()) {
@@ -1830,10 +1832,17 @@ public class DeviceProfile {
workspacePageIndicatorHeight - mWorkspacePageIndicatorOverlapWorkspace;
}
int paddingTop = workspaceTopPadding + (mIsScalableGrid ? 0 : edgeMarginPx);
- // On isFixedLandscapeMode on phones we already have padding because of the camera hole
- int paddingSide = inv.isFixedLandscape ? 0 : desiredWorkspaceHorizontalMarginPx;
+ int paddingLeft = desiredWorkspaceHorizontalMarginPx;
+ int paddingRight = desiredWorkspaceHorizontalMarginPx;
- padding.set(paddingSide, paddingTop, paddingSide, paddingBottom);
+ // In fixed Landscape we don't need padding on the side next to the cutout because
+ // the cutout is already adding padding to all of Launcher, we only need on the other
+ // side
+ if (inv.isFixedLandscape) {
+ paddingLeft = isSeascape() ? desiredWorkspaceHorizontalMarginPx : 0;
+ paddingRight = isSeascape() ? 0 : desiredWorkspaceHorizontalMarginPx;
+ }
+ padding.set(paddingLeft, paddingTop, paddingRight, paddingBottom);
}
insetPadding(workspacePadding, cellLayoutPaddingPx);
}
@@ -1931,7 +1940,24 @@ public class DeviceProfile {
hotseatBarPadding.set(mHotseatBarWorkspaceSpacePx, paddingTop,
mInsets.right + mHotseatBarEdgePaddingPx, paddingBottom);
}
- } else if (isTaskbarPresent || inv.isFixedLandscape) {
+ } else if (inv.isFixedLandscape) {
+ // Center the QSB vertically with hotseat
+ int hotseatBarBottomPadding = getHotseatBarBottomPadding();
+ int hotseatPlusQSBWidth = getHotseatRequiredWidth();
+ int qsbWidth = getAdditionalQsbSpace();
+ int availableWidthPxForHotseat = availableWidthPx - Math.abs(workspacePadding.width())
+ - Math.abs(cellLayoutPaddingPx.width());
+ int remainingSpaceOnSide = (availableWidthPxForHotseat - hotseatPlusQSBWidth) / 2;
+
+ hotseatBarPadding.set(
+ (remainingSpaceOnSide + qsbWidth) + mInsets.left + workspacePadding.left
+ + cellLayoutPaddingPx.left,
+ hotseatBarSizePx - hotseatBarBottomPadding - hotseatCellHeightPx,
+ remainingSpaceOnSide + mInsets.right + workspacePadding.right
+ + cellLayoutPaddingPx.right,
+ hotseatBarBottomPadding
+ );
+ } else if (isTaskbarPresent) {
// Center the QSB vertically with hotseat
int hotseatBarBottomPadding = getHotseatBarBottomPadding();
int hotseatBarTopPadding =
@@ -1950,11 +1976,6 @@ public class DeviceProfile {
}
startSpacing += getAdditionalQsbSpace();
- if (inv.isFixedLandscape) {
- endSpacing += mInsets.right;
- startSpacing += mInsets.left;
- }
-
hotseatBarPadding.top = hotseatBarTopPadding;
hotseatBarPadding.bottom = hotseatBarBottomPadding;
boolean isRtl = Utilities.isRtl(context.getResources());
@@ -2164,7 +2185,8 @@ public class DeviceProfile {
}
public boolean isSeascape() {
- return rotationHint == Surface.ROTATION_270 && isVerticalBarLayout();
+ return rotationHint == Surface.ROTATION_270
+ && (isVerticalBarLayout() || inv.isFixedLandscape);
}
public boolean shouldFadeAdjacentWorkspaceScreens() {
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index fafa60bf6d..f60896eb6d 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -181,6 +181,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
private ScrimView mScrimView;
private int mHeaderColor;
private int mBottomSheetBackgroundColor;
+ private float mBottomSheetBackgroundAlpha = 1f;
private int mTabsProtectionAlpha;
@Nullable private AllAppsTransitionController mAllAppsTransitionController;
@@ -311,7 +312,17 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
0,
0 // Bottom left
};
- mBottomSheetBackgroundColor = getContext().getColor(R.color.materialColorSurfaceDim);
+ if (Flags.allAppsBlur()) {
+ int resId = Utilities.isDarkTheme(getContext())
+ ? android.R.color.system_accent1_800 : android.R.color.system_accent1_100;
+ int layerAbove = ColorUtils.setAlphaComponent(getResources().getColor(resId, null),
+ (int) (0.4f * 255));
+ int layerBelow = ColorUtils.setAlphaComponent(Color.WHITE, (int) (0.1f * 255));
+ mBottomSheetBackgroundColor = ColorUtils.compositeColors(layerAbove, layerBelow);
+ } else {
+ mBottomSheetBackgroundColor = getContext().getColor(R.color.materialColorSurfaceDim);
+ }
+ mBottomSheetBackgroundAlpha = Color.alpha(mBottomSheetBackgroundColor) / 255.0f;
updateBackgroundVisibility(mActivityContext.getDeviceProfile());
mSearchUiManager.initializeSearch(this);
}
@@ -1152,7 +1163,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
if (!grid.isVerticalBarLayout() || FeatureFlags.enableResponsiveWorkspace()) {
int topPadding = grid.allAppsPadding.top;
- if (isSearchBarFloating() && !grid.isTablet) {
+ if (isSearchBarFloating() && !grid.shouldShowAllAppsOnSheet()) {
topPadding += getResources().getDimensionPixelSize(
R.dimen.all_apps_additional_top_padding_floating_search);
}
@@ -1401,7 +1412,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
// Draw full background panel for tablets.
if (hasBottomSheet) {
mHeaderPaint.setColor(mBottomSheetBackgroundColor);
- mHeaderPaint.setAlpha(255);
+ mHeaderPaint.setAlpha((int) (mBottomSheetBackgroundAlpha * 255));
mTmpRectF.set(
leftWithScale,
@@ -1424,6 +1435,10 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
return;
}
+ if (hasBottomSheet) {
+ mHeaderPaint.setAlpha((int) (mHeaderPaint.getAlpha() * mBottomSheetBackgroundAlpha));
+ }
+
// Draw header on background panel
final float headerBottomNoScale =
getHeaderBottom() + getVisibleContainerView().getPaddingTop();
@@ -1455,7 +1470,11 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
mHeaderPaint.setColor(Color.BLUE);
mHeaderPaint.setAlpha(255);
} else {
- mHeaderPaint.setAlpha((int) (getAlpha() * mTabsProtectionAlpha));
+ float tabAlpha = getAlpha() * mTabsProtectionAlpha;
+ if (hasBottomSheet) {
+ tabAlpha *= mBottomSheetBackgroundAlpha;
+ }
+ mHeaderPaint.setAlpha((int) tabAlpha);
}
float left = 0f;
float right = canvas.getWidth();
@@ -1507,7 +1526,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
public int getHeaderBottom() {
int bottom = (int) getTranslationY() + mHeader.getClipTop();
if (isSearchBarFloating()) {
- if (mActivityContext.getDeviceProfile().isTablet) {
+ if (mActivityContext.getDeviceProfile().shouldShowAllAppsOnSheet()) {
return bottom + mBottomSheetBackground.getTop();
}
return bottom;
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 4cc31d296e..350f763939 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -290,7 +290,8 @@ public class AllAppsTransitionController
private void onScaleProgressChanged() {
final float scaleProgress = mAllAppScale.value;
SCALE_PROPERTY.set(mLauncher.getAppsView(), scaleProgress);
- if (!mLauncher.getAppsView().isSearching() || !mLauncher.getDeviceProfile().isTablet) {
+ if (!mLauncher.getAppsView().isSearching()
+ || !mLauncher.getDeviceProfile().shouldShowAllAppsOnSheet()) {
mLauncher.getScrimView().setScrimHeaderScale(scaleProgress);
}
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 4127dd15ad..284faba9da 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -16,6 +16,7 @@
package com.android.launcher3.dragndrop;
+import static com.android.launcher3.Flags.removeAppsRefreshOnRightClick;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_NOT_PINNABLE;
import android.graphics.Point;
@@ -521,17 +522,21 @@ public abstract class DragController<T extends ActivityContext>
mDragObject.dragComplete = true;
if (mIsInPreDrag) {
- if (dropTarget != null) {
- dropTarget.onDragExit(mDragObject);
+ if (removeAppsRefreshOnRightClick()) {
+ mDragObject.cancelled = true;
+ } else {
+ if (dropTarget != null) {
+ dropTarget.onDragExit(mDragObject);
+ }
+ return;
}
- return;
}
// Drop onto the target.
boolean accepted = false;
if (dropTarget != null) {
dropTarget.onDragExit(mDragObject);
- if (dropTarget.acceptDrop(mDragObject)) {
+ if (!mIsInPreDrag && dropTarget.acceptDrop(mDragObject)) {
if (flingAnimation != null) {
flingAnimation.run();
} else {
diff --git a/src/com/android/launcher3/dragndrop/LauncherDragController.java b/src/com/android/launcher3/dragndrop/LauncherDragController.java
index 4aa3673586..dd433c02d3 100644
--- a/src/com/android/launcher3/dragndrop/LauncherDragController.java
+++ b/src/com/android/launcher3/dragndrop/LauncherDragController.java
@@ -15,7 +15,10 @@
*/
package com.android.launcher3.dragndrop;
+import static android.view.View.VISIBLE;
+
import static com.android.launcher3.AbstractFloatingView.TYPE_DISCOVERY_BOUNCE;
+import static com.android.launcher3.Flags.removeAppsRefreshOnRightClick;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
import static com.android.launcher3.LauncherState.EDIT_MODE;
import static com.android.launcher3.LauncherState.NORMAL;
@@ -25,6 +28,7 @@ import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.HapticFeedbackConstants;
+import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
@@ -33,10 +37,13 @@ import androidx.annotation.VisibleForTesting;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
+import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
+import com.android.launcher3.dragndrop.DragOptions.PreDragCondition;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.util.TouchUtil;
import com.android.launcher3.widget.util.WidgetDragScaleUtils;
/**
@@ -47,6 +54,9 @@ public class LauncherDragController extends DragController<Launcher> {
private static final boolean PROFILE_DRAWING_DURING_DRAG = false;
private final FlingToDeleteHelper mFlingToDeleteHelper;
+ /** Whether or not the drag operation is triggered by mouse right click. */
+ private boolean mIsInMouseRightClick = false;
+
public LauncherDragController(Launcher launcher) {
super(launcher);
mFlingToDeleteHelper = new FlingToDeleteHelper(launcher);
@@ -69,6 +79,28 @@ public class LauncherDragController extends DragController<Launcher> {
android.os.Debug.startMethodTracing("Launcher");
}
+ if (removeAppsRefreshOnRightClick() && mIsInMouseRightClick
+ && options.preDragCondition == null
+ && originalView instanceof View v) {
+ options.preDragCondition = new PreDragCondition() {
+
+ @Override
+ public boolean shouldStartDrag(double distanceDragged) {
+ return false;
+ }
+
+ @Override
+ public void onPreDragStart(DragObject dragObject) {
+ // Set it to visible so the text of FolderIcon would not flash (avoid it from
+ // being invisible and then visible)
+ v.setVisibility(VISIBLE);
+ }
+
+ @Override
+ public void onPreDragEnd(DragObject dragObject, boolean dragStarted) { }
+ };
+ }
+
mActivity.hideKeyboard();
AbstractFloatingView.closeOpenViews(mActivity, false, TYPE_DISCOVERY_BOUNCE);
@@ -191,7 +223,7 @@ public class LauncherDragController extends DragController<Launcher> {
@Override
protected void exitDrag() {
- if (!mActivity.isInState(EDIT_MODE)) {
+ if (!mIsInPreDrag && !mActivity.isInState(EDIT_MODE)) {
mActivity.getStateManager().goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
}
}
@@ -218,4 +250,13 @@ public class LauncherDragController extends DragController<Launcher> {
dropCoordinates);
return mActivity.getWorkspace();
}
+
+ /**
+ * Intercepts touch events from a drag source view.
+ */
+ @Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ mIsInMouseRightClick = TouchUtil.isMouseRightClickDownOrMove(ev);
+ return super.onControllerInterceptTouchEvent(ev);
+ }
}
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 28032569b2..0ae95196fd 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -102,7 +102,6 @@ import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pageindicators.PageIndicatorDots;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.LauncherBindableItemsContainer;
-import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
@@ -1116,13 +1115,15 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
View icon = (mCurrentDragView != null && mCurrentDragView.getTag() == info)
? mCurrentDragView : mContent.createNewView(info);
ArrayList<View> views = getIconsInReadingOrder();
- info.rank = Utilities.boundToRange(info.rank, 0, views.size());
- views.add(info.rank, icon);
- mContent.arrangeChildren(views);
- mItemsInvalidated = true;
-
- try (SuppressInfoChanges s = new SuppressInfoChanges()) {
- mFolderIcon.onDrop(d, true /* itemReturnedOnFailedDrop */);
+ if (!views.contains(icon)) {
+ info.rank = Utilities.boundToRange(info.rank, 0, views.size());
+ views.add(info.rank, icon);
+ mContent.arrangeChildren(views);
+ mItemsInvalidated = true;
+
+ try (SuppressInfoChanges s = new SuppressInfoChanges()) {
+ mFolderIcon.onDrop(d, true /* itemReturnedOnFailedDrop */);
+ }
}
}
diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java
index bebe1a49ef..0963421f8a 100644
--- a/src/com/android/launcher3/folder/FolderPagedView.java
+++ b/src/com/android/launcher3/folder/FolderPagedView.java
@@ -47,6 +47,7 @@ import com.android.launcher3.keyboard.ViewGroupFocusHelper;
import com.android.launcher3.model.data.AppPairInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.pageindicators.Direction;
import com.android.launcher3.pageindicators.PageIndicatorDots;
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
import com.android.launcher3.util.Thunk;
@@ -129,6 +130,8 @@ public class FolderPagedView extends PagedView<PageIndicatorDots> implements Cli
public void setFolder(Folder folder) {
mFolder = folder;
mPageIndicator = folder.findViewById(R.id.folder_page_indicator);
+ mPageIndicator.setArrowClickListener(direction -> snapToPageImmediately(
+ (Direction.END == direction) ? mCurrentPage + 1 : mCurrentPage - 1));
initParentViews(folder);
}
diff --git a/src/com/android/launcher3/graphics/GridCustomizationsProxy.java b/src/com/android/launcher3/graphics/GridCustomizationsProxy.java
index 70b9f46c1f..48519ce8bc 100644
--- a/src/com/android/launcher3/graphics/GridCustomizationsProxy.java
+++ b/src/com/android/launcher3/graphics/GridCustomizationsProxy.java
@@ -113,6 +113,7 @@ public class GridCustomizationsProxy implements ProxyProvider {
private static final String KEY_SHAPE_OPTIONS = "/shape_options";
// default_grid is for setting grid and shape to system settings
private static final String KEY_DEFAULT_GRID = "/default_grid";
+ private static final String SET_SHAPE = "/shape";
private static final String METHOD_GET_PREVIEW = "get_preview";
@@ -130,6 +131,7 @@ public class GridCustomizationsProxy implements ProxyProvider {
private static final int MESSAGE_ID_UPDATE_SHAPE = 2586;
private static final int MESSAGE_ID_UPDATE_GRID = 7414;
private static final int MESSAGE_ID_UPDATE_COLOR = 856;
+ private static final int MESSAGE_ID_UPDATE_ICON_THEMED = 311;
// Set of all active previews used to track duplicate memory allocations
private final Set<PreviewLifecycleObserver> mActivePreviews =
@@ -264,6 +266,12 @@ public class GridCustomizationsProxy implements ProxyProvider {
mContext.getContentResolver().notifyChange(uri, null);
return 1;
}
+ case SET_SHAPE:
+ if (Flags.newCustomizationPickerUi()) {
+ mPrefs.put(PREF_ICON_SHAPE,
+ requireNonNullElse(values.getAsString(KEY_SHAPE_KEY), ""));
+ }
+ return 1;
case ICON_THEMED:
case SET_ICON_THEMED: {
mThemeManager.setMonoThemeEnabled(values.getAsBoolean(BOOLEAN_VALUE));
@@ -384,6 +392,12 @@ public class GridCustomizationsProxy implements ProxyProvider {
renderer.previewColor(message.getData());
}
break;
+ case MESSAGE_ID_UPDATE_ICON_THEMED:
+ if (Flags.newCustomizationPickerUi()) {
+ Boolean iconThemed = message.getData().getBoolean(BOOLEAN_VALUE);
+ // TODO Update icon themed in the preview
+ }
+ break;
default:
// Unknown command, destroy lifecycle
Log.d(TAG, "Unknown preview command: " + message.what + ", destroying preview");
diff --git a/src/com/android/launcher3/graphics/ShapeDelegate.kt b/src/com/android/launcher3/graphics/ShapeDelegate.kt
index 7c042929e2..01bfe3018c 100644
--- a/src/com/android/launcher3/graphics/ShapeDelegate.kt
+++ b/src/com/android/launcher3/graphics/ShapeDelegate.kt
@@ -18,6 +18,7 @@ package com.android.launcher3.graphics
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
+import android.animation.ValueAnimator.AnimatorUpdateListener
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Matrix
@@ -41,7 +42,6 @@ import androidx.graphics.shapes.SvgPathParser
import androidx.graphics.shapes.rectangle
import androidx.graphics.shapes.toPath
import androidx.graphics.shapes.transformed
-import com.android.launcher3.anim.RoundedRectRevealOutlineProvider
import com.android.launcher3.icons.GraphicsUtils
import com.android.launcher3.views.ClipPathView
@@ -127,16 +127,20 @@ interface ShapeDelegate {
endRadius: Float,
isReversed: Boolean,
): ValueAnimator where T : View, T : ClipPathView {
- return object :
- RoundedRectRevealOutlineProvider(
- (startRect.width() / 2f) * radiusRatio,
- endRadius,
- startRect,
- endRect,
- ) {
- override fun shouldRemoveElevationDuringAnimation() = true
- }
- .createRevealAnimator(target, isReversed)
+ val startRadius = (startRect.width() / 2f) * radiusRatio
+ return ClipAnimBuilder(target) { progress, path ->
+ val radius = (1 - progress) * startRadius + progress * endRadius
+ path.addRoundRect(
+ (1 - progress) * startRect.left + progress * endRect.left,
+ (1 - progress) * startRect.top + progress * endRect.top,
+ (1 - progress) * startRect.right + progress * endRect.right,
+ (1 - progress) * startRect.bottom + progress * endRect.bottom,
+ radius,
+ radius,
+ Path.Direction.CW,
+ )
+ }
+ .toAnim(isReversed)
}
override fun equals(other: Any?) =
@@ -220,38 +224,44 @@ interface ShapeDelegate {
),
)
- val va =
- if (isReversed) ValueAnimator.ofFloat(1f, 0f) else ValueAnimator.ofFloat(0f, 1f)
- va.addListener(
- object : AnimatorListenerAdapter() {
- private var oldOutlineProvider: ViewOutlineProvider? = null
-
- override fun onAnimationStart(animation: Animator) {
- target.apply {
- oldOutlineProvider = outlineProvider
- outlineProvider = null
- translationZ = -target.elevation
- }
- }
+ return ClipAnimBuilder(target, morph::toPath).toAnim(isReversed)
+ }
+ }
- override fun onAnimationEnd(animation: Animator) {
- target.apply {
- translationZ = 0f
- setClipPath(null)
- outlineProvider = oldOutlineProvider
- }
- }
- }
- )
+ private class ClipAnimBuilder<T>(val target: T, val pathProvider: (Float, Path) -> Unit) :
+ AnimatorListenerAdapter(), AnimatorUpdateListener where T : View, T : ClipPathView {
- val path = Path()
- va.addUpdateListener { anim: ValueAnimator ->
- path.reset()
- morph.toPath(anim.animatedValue as Float, path)
- target.setClipPath(path)
+ private var oldOutlineProvider: ViewOutlineProvider? = null
+ val path = Path()
+
+ override fun onAnimationStart(animation: Animator) {
+ target.apply {
+ oldOutlineProvider = outlineProvider
+ outlineProvider = null
+ translationZ = -target.elevation
+ }
+ }
+
+ override fun onAnimationEnd(animation: Animator) {
+ target.apply {
+ translationZ = 0f
+ setClipPath(null)
+ outlineProvider = oldOutlineProvider
}
- return va
}
+
+ override fun onAnimationUpdate(anim: ValueAnimator) {
+ path.reset()
+ pathProvider.invoke(anim.animatedValue as Float, path)
+ target.setClipPath(path)
+ }
+
+ fun toAnim(isReversed: Boolean) =
+ (if (isReversed) ValueAnimator.ofFloat(1f, 0f) else ValueAnimator.ofFloat(0f, 1f))
+ .also {
+ it.addListener(this)
+ it.addUpdateListener(this)
+ }
}
companion object {
diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java
index 0640bf3672..a6f76c4d44 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicator.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.pageindicators;
+import java.util.function.Consumer;
+
/**
* Base class for a page indicator.
*/
@@ -27,6 +29,14 @@ public interface PageIndicator {
void setMarkersCount(int numMarkers);
/**
+ * This is only going to be used by the FolderPagedView's PageIndicator. A refactor is planned
+ * to separate the two purposes of this class, but in the meantime, this indicator will serve to
+ * let the folder snap to the page of its click, and also tell the PageIndicator not to draw
+ * arrows if the click listener is null (at least until after this is refactored).
+ */
+ void setArrowClickListener(Consumer<Direction> listener);
+
+ /**
* Sets a flag indicating whether to pause scroll.
* <p>Should be set to {@code true} while the screen is binding or new data is being applied,
* and to {@code false} once done. This prevents animation conflicts due to scrolling during
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorArrowClickListener.kt b/src/com/android/launcher3/pageindicators/PageIndicatorArrowClickListener.kt
new file mode 100644
index 0000000000..970d210ad9
--- /dev/null
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorArrowClickListener.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.pageindicators
+
+interface PageIndicatorArrowClickListener {
+ fun onArrowClick(direction: Direction)
+}
+
+enum class Direction {
+ END,
+ START,
+}
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
index a9a26a1631..384f87623a 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
@@ -32,11 +32,13 @@ import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.graphics.drawable.VectorDrawable;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.IntProperty;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewOutlineProvider;
@@ -51,6 +53,8 @@ import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.Themes;
+import java.util.function.Consumer;
+
/**
* {@link PageIndicator} which shows dots per page. The active page is shown with the current
* accent color.
@@ -71,6 +75,12 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
private static final int ENTER_ANIMATION_STAGGERED_DELAY = 150;
private static final int ENTER_ANIMATION_DURATION = 400;
+ private static final int LARGE_HEIGHT_MULTIPLIER = 12;
+ private static final int SMALL_HEIGHT_MULTIPLIER = 4;
+ private static final int LARGE_WIDTH_MULTIPLIER = 5;
+ private static final int SMALL_WIDTH_MULTIPLIER = 3;
+ private static final float ARROW_TOUCH_BOX_FACTOR = 5f;
+
private static final int PAGE_INDICATOR_ALPHA = 255;
private static final int DOT_ALPHA = 128;
private static final float DOT_ALPHA_FRACTION = 0.5f;
@@ -78,12 +88,14 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
private static final int VISIBLE_ALPHA = 255;
private static final int INVISIBLE_ALPHA = 0;
private Paint mPaginationPaint;
+ private Consumer<Direction> mOnArrowClickListener;
// This value approximately overshoots to 1.5 times the original size.
private static final float ENTER_ANIMATION_OVERSHOOT_TENSION = 4.9f;
// This is used to optimize the onDraw method by not constructing a new RectF each draw.
private static final RectF sTempRect = new RectF();
+ private static final RectF sLastActiveRect = new RectF();
private static final FloatProperty<PageIndicatorDots> CURRENT_POSITION =
new FloatProperty<PageIndicatorDots>("current_position") {
@@ -102,23 +114,27 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
private static final IntProperty<PageIndicatorDots> PAGINATION_ALPHA =
new IntProperty<PageIndicatorDots>("pagination_alpha") {
- @Override
- public Integer get(PageIndicatorDots obj) {
- return obj.mPaginationPaint.getAlpha();
- }
+ @Override
+ public Integer get(PageIndicatorDots obj) {
+ return obj.mPaginationPaint.getAlpha();
+ }
- @Override
- public void setValue(PageIndicatorDots obj, int alpha) {
- obj.mPaginationPaint.setAlpha(alpha);
- obj.invalidate();
- }
- };
+ @Override
+ public void setValue(PageIndicatorDots obj, int alpha) {
+ obj.mPaginationPaint.setAlpha(alpha);
+ obj.invalidate();
+ }
+ };
private final Handler mDelayedPaginationFadeHandler = new Handler(Looper.getMainLooper());
private final float mDotRadius;
private final float mGapWidth;
private final float mCircleGap;
private final boolean mIsRtl;
+ private final VectorDrawable mArrowRight;
+ private final VectorDrawable mArrowLeft;
+ private final Rect mArrowRightBounds = new Rect();
+ private final Rect mArrowLeftBounds = new Rect();
private int mNumPages;
private int mActivePage;
@@ -170,6 +186,8 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
: DOT_GAP_FACTOR * mDotRadius;
setOutlineProvider(new MyOutlineProver());
mIsRtl = Utilities.isRtl(getResources());
+ mArrowRight = (VectorDrawable) getResources().getDrawable(R.drawable.ic_chevron_end);
+ mArrowLeft = (VectorDrawable) getResources().getDrawable(R.drawable.ic_chevron_start);
}
@Override
@@ -408,6 +426,11 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
}
@Override
+ public void setArrowClickListener(Consumer<Direction> listener) {
+ mOnArrowClickListener = listener;
+ }
+
+ @Override
public void setPauseScroll(boolean pause, boolean isTwoPanels) {
mIsTwoPanels = isTwoPanels;
@@ -422,11 +445,16 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO(b/394355070): Verify Folder Entry Animation works correctly with visual updates
- // Add extra spacing of mDotRadius on all sides so than entry animation could be run.
+ // Add extra spacing of mDotRadius on all sides so than entry animation could be run
+ // and so the hitboxes of arrows can be clicked easier.
int width = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY ?
- MeasureSpec.getSize(widthMeasureSpec) : (int) ((mNumPages * 3 + 2) * mDotRadius);
+ MeasureSpec.getSize(widthMeasureSpec)
+ : (int) ((mNumPages * ((enableLauncherVisualRefresh())
+ ? LARGE_WIDTH_MULTIPLIER : SMALL_WIDTH_MULTIPLIER) + 2) * mDotRadius);
int height = MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY
- ? MeasureSpec.getSize(heightMeasureSpec) : (int) (4 * mDotRadius);
+ ? MeasureSpec.getSize(heightMeasureSpec)
+ : (int) (((enableLauncherVisualRefresh())
+ ? LARGE_HEIGHT_MULTIPLIER : SMALL_HEIGHT_MULTIPLIER) * mDotRadius);
setMeasuredDimension(width, height);
}
@@ -446,18 +474,51 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
float y = getHeight() / 2;
if (mEntryAnimationRadiusFactors != null) {
- // During entry animation, only draw the circles
- // TODO(b/394355070): Verify Folder Entry Animation works correctly - visual updates
+ if (enableLauncherVisualRefresh()) {
+ x -= mDotRadius;
+ if (mIsRtl) {
+ x = getWidth() - x;
+ circleGap = -circleGap;
+ }
+ sTempRect.top = y - mDotRadius;
+ sTempRect.bottom = y + mDotRadius;
- if (mIsRtl) {
- x = getWidth() - x;
- circleGap = -circleGap;
- }
- for (int i = 0; i < mEntryAnimationRadiusFactors.length; i++) {
- mPaginationPaint.setAlpha(i == mActivePage ? PAGE_INDICATOR_ALPHA : DOT_ALPHA);
- canvas.drawCircle(x, y, mDotRadius * mEntryAnimationRadiusFactors[i],
- mPaginationPaint);
- x += circleGap;
+ for (int i = 0; i < mEntryAnimationRadiusFactors.length; i++) {
+ if (i == mActivePage) {
+ if (mIsRtl) {
+ sTempRect.left = x - (mDotRadius * 3);
+ sTempRect.right = x + mDotRadius;
+ x += circleGap - (mDotRadius * 2);
+ } else {
+ sTempRect.left = x - mDotRadius;
+ sTempRect.right = x + (mDotRadius * 3);
+ x += circleGap + (mDotRadius * 2);
+ }
+ scale(sTempRect, mEntryAnimationRadiusFactors[i]);
+ float scaledRadius = mDotRadius * mEntryAnimationRadiusFactors[i];
+ mPaginationPaint.setAlpha(PAGE_INDICATOR_ALPHA);
+ canvas.drawRoundRect(sTempRect, scaledRadius, scaledRadius,
+ mPaginationPaint);
+ } else {
+ mPaginationPaint.setAlpha(DOT_ALPHA);
+ canvas.drawCircle(x, y, mDotRadius * mEntryAnimationRadiusFactors[i],
+ mPaginationPaint);
+ x += circleGap;
+ }
+ }
+ } else {
+ // During entry animation, only draw the circles
+
+ if (mIsRtl) {
+ x = getWidth() - x;
+ circleGap = -circleGap;
+ }
+ for (int i = 0; i < mEntryAnimationRadiusFactors.length; i++) {
+ mPaginationPaint.setAlpha(i == mActivePage ? PAGE_INDICATOR_ALPHA : DOT_ALPHA);
+ canvas.drawCircle(x, y, mDotRadius * mEntryAnimationRadiusFactors[i],
+ mPaginationPaint);
+ x += circleGap;
+ }
}
} else {
// Save the current alpha value, so we can reset to it again after drawing the dots
@@ -471,12 +532,31 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
sTempRect.bottom = y + mDotRadius;
sTempRect.left = x - diameter;
- float posDif = Math.abs(mLastPosition - mCurrentPosition);
+ float currentPosition = mCurrentPosition;
+ float lastPosition = mLastPosition;
+
+ if (mIsRtl) {
+ currentPosition = mNumPages - currentPosition - 1;
+ lastPosition = mNumPages - lastPosition - 1;
+ }
+ float posDif = Math.abs(lastPosition - currentPosition);
float boundedPosition = (posDif > 1)
- ? Math.round(mCurrentPosition)
- : mCurrentPosition;
+ ? Math.round(currentPosition)
+ : currentPosition;
float bounceProgress = (posDif > 1) ? posDif - 1 : 0;
- float bounceAdjustment = Math.abs(mCurrentPosition - boundedPosition) * diameter;
+ float bounceAdjustment = Math.abs(currentPosition - boundedPosition) * diameter;
+
+ if (mOnArrowClickListener != null && boundedPosition >= 1) {
+ // Here we draw the Left Arrow
+ mArrowLeft.setAlpha(alpha);
+ int size = (int) (mGapWidth * 4);
+ mArrowLeftBounds.left = (int) (sTempRect.left - mGapWidth - size);
+ mArrowLeftBounds.top = (int) (y - size / 2);
+ mArrowLeftBounds.right = (int) (sTempRect.left - mGapWidth);
+ mArrowLeftBounds.bottom = (int) (y + size / 2);
+ mArrowLeft.setBounds(mArrowLeftBounds);
+ mArrowLeft.draw(canvas);
+ }
// Here we draw the dots, one at a time from the left-most dot to the right-most dot
// 1.0 => 000000 000000111111 000000
@@ -498,10 +578,10 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
// While the animation is shifting the active pagination dots size from
// the previously active one, to the newly active dot, there is no bounce
// adjustment. The bounce happens in the "Overshoot" phase of the animation.
- // mLastPosition is used to determine when the currentPosition is just
+ // lastPosition is used to determine when the currentPosition is just
// leaving the page, or if it is in the overshoot phase.
if (boundedPosition == i && bounceProgress != 0) {
- if (mLastPosition < mCurrentPosition) {
+ if (lastPosition < currentPosition) {
sTempRect.left -= bounceAdjustment;
} else {
sTempRect.right += bounceAdjustment;
@@ -510,19 +590,34 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
} else {
sTempRect.right = sTempRect.left + diameter;
- if (mLastPosition == i && bounceProgress != 0) {
- if (mLastPosition > mCurrentPosition) {
+ if (lastPosition == i && bounceProgress != 0) {
+ if (lastPosition > currentPosition) {
sTempRect.left += bounceAdjustment;
} else {
sTempRect.right -= bounceAdjustment;
}
}
}
+ if (Math.round(mCurrentPosition) == i) {
+ sLastActiveRect.set(sTempRect);
+ }
canvas.drawRoundRect(sTempRect, mDotRadius, mDotRadius, mPaginationPaint);
// TODO(b/394355070) Verify RTL experience works correctly with visual updates
sTempRect.left = sTempRect.right + mGapWidth;
}
+
+ if (mOnArrowClickListener != null && boundedPosition <= mNumPages - 2) {
+ // Here we draw the Right Arrow
+ mArrowRight.setAlpha(alpha);
+ int size = (int) (mGapWidth * 4);
+ mArrowRightBounds.left = (int) sTempRect.left;
+ mArrowRightBounds.top = (int) (y - size / 2);
+ mArrowRightBounds.right = (int) (int) (sTempRect.left + size);
+ mArrowRightBounds.bottom = (int) (y + size / 2);
+ mArrowRight.setBounds(mArrowRightBounds);
+ mArrowRight.draw(canvas);
+ }
} else {
// Here we draw the dots
mPaginationPaint.setAlpha((int) (alpha * DOT_ALPHA_FRACTION));
@@ -541,6 +636,38 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
}
}
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (mOnArrowClickListener == null) {
+ // No - Op. Don't care about touch events
+ } else if ((mIsRtl && withinExpandedBounds(mArrowRightBounds, ev))
+ || (!mIsRtl && withinExpandedBounds(mArrowLeftBounds, ev))) {
+ mOnArrowClickListener.accept(Direction.START);
+ } else if ((mIsRtl && withinExpandedBounds(mArrowLeftBounds, ev))
+ || (!mIsRtl && withinExpandedBounds(mArrowRightBounds, ev))) {
+ mOnArrowClickListener.accept(Direction.END);
+ }
+ return super.onTouchEvent(ev);
+ }
+
+ // For larger Touch box
+ private boolean withinExpandedBounds(Rect rect, MotionEvent ev) {
+ RectF scaledRect = new RectF(rect);
+ scale(scaledRect, ARROW_TOUCH_BOX_FACTOR);
+ return scaledRect.contains(ev.getX(), ev.getY());
+ }
+
+ private static void scale(RectF rect, float factor) {
+ float horizontalAdjustment = rect.width() * (factor - 1) / 2;
+ float verticalAdjustment = rect.height() * (factor - 1) / 2;
+
+ rect.top -= verticalAdjustment;
+ rect.bottom += verticalAdjustment;
+
+ rect.left -= horizontalAdjustment;
+ rect.right += horizontalAdjustment;
+ }
+
private RectF getActiveRect() {
float startCircle = (int) mCurrentPosition;
float delta = mCurrentPosition - startCircle;
@@ -593,8 +720,8 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
@Override
public void getOutline(View view, Outline outline) {
if (mEntryAnimationRadiusFactors == null) {
- // TODO(b/394355070): Verify Outline works correctly with visual updates
- RectF activeRect = getActiveRect();
+ RectF activeRect = enableLauncherVisualRefresh()
+ ? sLastActiveRect : getActiveRect();
outline.setRoundRect(
(int) activeRect.left,
(int) activeRect.top,
diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java
index 2cc4909712..f86fd6ac33 100644
--- a/src/com/android/launcher3/touch/AllAppsSwipeController.java
+++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java
@@ -22,6 +22,7 @@ import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
import static com.android.app.animation.Interpolators.FINAL_FRAME;
import static com.android.app.animation.Interpolators.INSTANT;
import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.clampToProgress;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
@@ -39,6 +40,7 @@ import android.view.animation.Interpolator;
import com.android.app.animation.Interpolators;
import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.Flags;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.states.StateAnimationConfig;
@@ -53,10 +55,10 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController {
private static final float ALL_APPS_SCRIM_VISIBLE_THRESHOLD = 0.1f;
private static final float ALL_APPS_STAGGERED_FADE_THRESHOLD = 0.5f;
- public static final Interpolator ALL_APPS_SCRIM_RESPONDER =
+ private 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 =
+ private static final Interpolator ALL_APPS_CLAMPING_RESPONDER =
Interpolators.clampToProgress(
LINEAR,
1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
@@ -207,7 +209,16 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController {
}
config.setInterpolator(ANIM_WORKSPACE_SCALE, DECELERATED_EASE);
config.setInterpolator(ANIM_DEPTH, DECELERATED_EASE);
- if (launcher.getDeviceProfile().isPhone) {
+ if (Flags.allAppsBlur()) {
+ if (!config.isUserControlled()) {
+ config.setInterpolator(ANIM_DEPTH, EMPHASIZED_DECELERATE);
+ }
+ config.setInterpolator(ANIM_WORKSPACE_FADE,
+ clampToProgress(LINEAR, 1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD, 1));
+ config.setInterpolator(ANIM_HOTSEAT_FADE,
+ clampToProgress(LINEAR, 1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD, 1));
+ } else if (launcher.getDeviceProfile().isPhone) {
+ // On phones without blur, reveal the workspace and hotseat when leaving All Apps.
config.setInterpolator(ANIM_WORKSPACE_FADE, INSTANT);
config.setInterpolator(ANIM_HOTSEAT_FADE, INSTANT);
config.animFlags |= StateAnimationConfig.SKIP_DEPTH_CONTROLLER;
@@ -253,7 +264,14 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController {
}
config.setInterpolator(ANIM_WORKSPACE_SCALE, DECELERATED_EASE);
config.setInterpolator(ANIM_DEPTH, DECELERATED_EASE);
- if (launcher.getDeviceProfile().isPhone) {
+ if (Flags.allAppsBlur()) {
+ config.setInterpolator(ANIM_DEPTH, LINEAR);
+ config.setInterpolator(ANIM_WORKSPACE_FADE,
+ clampToProgress(LINEAR, 0, ALL_APPS_SCRIM_VISIBLE_THRESHOLD));
+ config.setInterpolator(ANIM_HOTSEAT_FADE,
+ clampToProgress(LINEAR, 0, ALL_APPS_SCRIM_VISIBLE_THRESHOLD));
+ } else if (launcher.getDeviceProfile().isPhone) {
+ // On phones without blur, hide the workspace and hotseat when entering All Apps.
config.setInterpolator(ANIM_WORKSPACE_FADE, FINAL_FRAME);
config.setInterpolator(ANIM_HOTSEAT_FADE, FINAL_FRAME);
config.animFlags |= StateAnimationConfig.SKIP_DEPTH_CONTROLLER;
diff --git a/src/com/android/launcher3/touch/WorkspaceTouchListener.java b/src/com/android/launcher3/touch/WorkspaceTouchListener.java
index d72e6f9e39..576f17616b 100644
--- a/src/com/android/launcher3/touch/WorkspaceTouchListener.java
+++ b/src/com/android/launcher3/touch/WorkspaceTouchListener.java
@@ -131,7 +131,7 @@ public class WorkspaceTouchListener extends GestureDetector.SimpleOnGestureListe
}
boolean isInAllAppsBottomSheet = mLauncher.isInState(ALL_APPS)
- && mLauncher.getDeviceProfile().isTablet;
+ && mLauncher.getDeviceProfile().shouldShowAllAppsOnSheet();
final boolean result;
if (mLongPressState == STATE_COMPLETED) {
diff --git a/src/com/android/launcher3/util/SimpleBroadcastReceiver.java b/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
index 7a40abe62b..53e0bce182 100644
--- a/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
+++ b/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
@@ -123,6 +123,32 @@ public class SimpleBroadcastReceiver extends BroadcastReceiver {
}
}
+ /**
+ * Same as {@link #register(Runnable, int, String...)} above but with additional permission
+ * params utilizine the original {@link Context}.
+ */
+ @AnyThread
+ public void register(@Nullable Runnable completionCallback,
+ String broadcastPermission, int flags, String... actions) {
+ if (Looper.myLooper() == mHandler.getLooper()) {
+ registerInternal(mContext, completionCallback, broadcastPermission, flags, actions);
+ } else {
+ mHandler.post(() -> registerInternal(mContext, completionCallback, broadcastPermission,
+ flags, actions));
+ }
+ }
+
+ /** Register broadcast receiver with permission and run completion callback if passed. */
+ @AnyThread
+ private void registerInternal(
+ @NonNull Context context, @Nullable Runnable completionCallback,
+ String broadcastPermission, int flags, String... actions) {
+ context.registerReceiver(this, getFilter(actions), broadcastPermission, null, flags);
+ if (completionCallback != null) {
+ completionCallback.run();
+ }
+ }
+
/** Same as {@link #register(Runnable, String...)} above but with pkg name. */
@AnyThread
public void registerPkgActions(@Nullable String pkg, String... actions) {
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index ce58de1ee5..ec71f3118a 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -54,8 +54,7 @@ public class ScrimView extends View implements Insettable {
}
@Override
- public void setInsets(Rect insets) {
- }
+ public void setInsets(Rect insets) {}
@Override
public boolean hasOverlappingRendering() {
diff --git a/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java b/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java
index e94f3a065d..185c3ee9ed 100644
--- a/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java
+++ b/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java
@@ -26,9 +26,12 @@ import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
+import com.android.launcher3.pageindicators.Direction;
import com.android.launcher3.pageindicators.PageIndicator;
import com.android.launcher3.views.ActivityContext;
+import java.util.function.Consumer;
+
/**
* Supports two indicator colors, dedicated for personal and work tabs.
*/
@@ -78,6 +81,11 @@ public class PersonalWorkSlidingTabStrip extends LinearLayout implements PageInd
}
@Override
+ public void setArrowClickListener(Consumer<Direction> listener) {
+ // No-Op. All Apps doesn't need accessibility arrows for single click navigation.
+ }
+
+ @Override
public boolean hasOverlappingRendering() {
return false;
}