From 8ad9144ca2910b09f1f847849de6b6a4f6e6632c Mon Sep 17 00:00:00 2001 From: Charlie Anderson Date: Mon, 9 Jan 2023 13:55:59 -0500 Subject: [PATCH] adding the new Material U App Shortcut Popup design Bug: 247880037 Test: tested manually Change-Id: I66c291df54dfc2a76fc974082a19091deb167f73 --- .../taskbar/TaskbarPopupController.java | 36 ++- res/drawable/popup_background_material_u.xml | 20 ++ res/layout/deep_shortcut_container.xml | 24 ++ res/layout/deep_shortcut_material_u.xml | 50 +++++ res/layout/popup_container_material_u.xml | 21 ++ res/layout/system_shortcut.xml | 1 + ...ml => system_shortcut_icons_container.xml} | 6 +- ...em_shortcut_icons_container_material_u.xml | 32 +++ ...tem_shortcut_rows_container_material_u.xml | 25 +++ .../widget_shortcut_container_material_u.xml | 27 +++ res/values/dimens.xml | 2 +- src/com/android/launcher3/Launcher.java | 2 +- .../android/launcher3/popup/ArrowPopup.java | 38 +++- .../popup/PopupContainerWithArrow.java | 208 ++++++++++++++---- .../secondarydisplay/SecondaryDragLayer.java | 25 ++- .../launcher3/views/ActivityContext.java | 4 +- .../launcher3/views/OptionsPopupView.java | 15 ++ 17 files changed, 461 insertions(+), 75 deletions(-) create mode 100644 res/drawable/popup_background_material_u.xml create mode 100644 res/layout/deep_shortcut_container.xml create mode 100644 res/layout/deep_shortcut_material_u.xml create mode 100644 res/layout/popup_container_material_u.xml rename res/layout/{system_shortcut_icons.xml => system_shortcut_icons_container.xml} (90%) create mode 100644 res/layout/system_shortcut_icons_container_material_u.xml create mode 100644 res/layout/system_shortcut_rows_container_material_u.xml create mode 100644 res/layout/widget_shortcut_container_material_u.xml diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java index 30d6eb4dda..115b99e3be 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java @@ -15,6 +15,7 @@ */ package com.android.launcher3.taskbar; +import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP; import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition; import android.content.Intent; @@ -56,6 +57,7 @@ import com.android.quickstep.util.LogUtils; import java.io.PrintWriter; import java.util.HashMap; +import java.util.List; import java.util.Objects; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -152,9 +154,28 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba return null; } - final PopupContainerWithArrow container = - (PopupContainerWithArrow) context.getLayoutInflater().inflate( - R.layout.popup_container, context.getDragLayer(), false); + PopupContainerWithArrow container; + int deepShortcutCount = mPopupDataProvider.getShortcutCountForItem(item); + // TODO(b/198438631): add support for INSTALL shortcut factory + List systemShortcuts = getSystemShortcuts() + .map(s -> s.getShortcut(context, item, icon)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + if (ENABLE_MATERIAL_U_POPUP.get()) { + container = (PopupContainerWithArrow) context.getLayoutInflater().inflate( + R.layout.popup_container_material_u, context.getDragLayer(), false); + container.populateAndShowRowsMaterialU(icon, deepShortcutCount, systemShortcuts); + } else { + container = (PopupContainerWithArrow) context.getLayoutInflater().inflate( + R.layout.popup_container, context.getDragLayer(), false); + container.populateAndShow( + icon, + deepShortcutCount, + mPopupDataProvider.getNotificationKeysForItem(item), + systemShortcuts); + } + container.addOnAttachStateChangeListener( new PopupLiveUpdateHandler(context, container) { @Override @@ -165,15 +186,6 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba // TODO (b/198438631): configure for taskbar/context container.setPopupItemDragHandler(new TaskbarPopupItemDragHandler()); mControllers.taskbarDragController.addDragListener(container); - - container.populateAndShow(icon, - mPopupDataProvider.getShortcutCountForItem(item), - mPopupDataProvider.getNotificationKeysForItem(item), - // TODO (b/198438631): add support for INSTALL shortcut factory - getSystemShortcuts() - .map(s -> s.getShortcut(context, item, icon)) - .filter(Objects::nonNull) - .collect(Collectors.toList())); container.requestFocus(); // Make focusable to receive back events diff --git a/res/drawable/popup_background_material_u.xml b/res/drawable/popup_background_material_u.xml new file mode 100644 index 0000000000..4d40ba8afd --- /dev/null +++ b/res/drawable/popup_background_material_u.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/res/layout/deep_shortcut_container.xml b/res/layout/deep_shortcut_container.xml new file mode 100644 index 0000000000..b6c3f56576 --- /dev/null +++ b/res/layout/deep_shortcut_container.xml @@ -0,0 +1,24 @@ + + + \ No newline at end of file diff --git a/res/layout/deep_shortcut_material_u.xml b/res/layout/deep_shortcut_material_u.xml new file mode 100644 index 0000000000..fc019e921f --- /dev/null +++ b/res/layout/deep_shortcut_material_u.xml @@ -0,0 +1,50 @@ + + + + + + + + \ No newline at end of file diff --git a/res/layout/popup_container_material_u.xml b/res/layout/popup_container_material_u.xml new file mode 100644 index 0000000000..d3036b68d7 --- /dev/null +++ b/res/layout/popup_container_material_u.xml @@ -0,0 +1,21 @@ + + + \ No newline at end of file diff --git a/res/layout/system_shortcut.xml b/res/layout/system_shortcut.xml index 21d532eb91..cbd7fa4f78 100644 --- a/res/layout/system_shortcut.xml +++ b/res/layout/system_shortcut.xml @@ -18,6 +18,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="@dimen/bg_popup_item_width" android:layout_height="wrap_content" + android:id="@+id/system_shortcut" android:minHeight="@dimen/bg_popup_item_height" android:elevation="@dimen/deep_shortcuts_elevation" android:background="@drawable/middle_item_primary" diff --git a/res/layout/system_shortcut_icons.xml b/res/layout/system_shortcut_icons_container.xml similarity index 90% rename from res/layout/system_shortcut_icons.xml rename to res/layout/system_shortcut_icons_container.xml index 775a45f47b..ee104d9b32 100644 --- a/res/layout/system_shortcut_icons.xml +++ b/res/layout/system_shortcut_icons_container.xml @@ -26,7 +26,7 @@ android:clipToPadding="true"> + android:layout_height="match_parent" + android:layout_weight="1" + android:id="@+id/separator"/> diff --git a/res/layout/system_shortcut_icons_container_material_u.xml b/res/layout/system_shortcut_icons_container_material_u.xml new file mode 100644 index 0000000000..afd11e6bf9 --- /dev/null +++ b/res/layout/system_shortcut_icons_container_material_u.xml @@ -0,0 +1,32 @@ + + + + + + + diff --git a/res/layout/system_shortcut_rows_container_material_u.xml b/res/layout/system_shortcut_rows_container_material_u.xml new file mode 100644 index 0000000000..006e28060a --- /dev/null +++ b/res/layout/system_shortcut_rows_container_material_u.xml @@ -0,0 +1,25 @@ + + + + diff --git a/res/layout/widget_shortcut_container_material_u.xml b/res/layout/widget_shortcut_container_material_u.xml new file mode 100644 index 0000000000..aab34e3aea --- /dev/null +++ b/res/layout/widget_shortcut_container_material_u.xml @@ -0,0 +1,27 @@ + + + + \ No newline at end of file diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 9d2aa06e43..d292017f24 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -349,7 +349,7 @@ 10dp - 8dp + 26dp @dimen/default_dialog_corner_radius diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 41632f7325..8097fd7cef 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -3211,7 +3211,7 @@ public class Launcher extends StatefulActivity } @Override - public boolean shouldUseColorExtractionForPopup() { + public boolean canUseMultipleShadesForPopup() { return getTopOpenViewWithType(this, TYPE_FOLDER) == null && getStateManager().getState() != LauncherState.ALL_APPS; } diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java index 9a745ab9f4..c23ea8aa4f 100644 --- a/src/com/android/launcher3/popup/ArrowPopup.java +++ b/src/com/android/launcher3/popup/ArrowPopup.java @@ -21,6 +21,7 @@ import static androidx.core.content.ContextCompat.getColorStateList; import static com.android.launcher3.anim.Interpolators.ACCELERATED_EASE; import static com.android.launcher3.anim.Interpolators.DECELERATED_EASE; import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -116,7 +117,7 @@ public abstract class ArrowPopup private final String mIterateChildrenTag; - private final int[] mColorIds; + protected final int[] mColorIds; public ArrowPopup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); @@ -125,8 +126,8 @@ public abstract class ArrowPopup mActivityContext = ActivityContext.lookupContext(context); mIsRtl = Utilities.isRtl(getResources()); - int backgroundColor = Themes.getAttrColor(context, R.attr.popupColorPrimary); - mArrowColor = backgroundColor; + int popupPrimaryColor = Themes.getAttrColor(context, R.attr.popupColorPrimary); + mArrowColor = popupPrimaryColor; mElevation = getResources().getDimension(R.dimen.deep_shortcuts_elevation); // Initialize arrow view @@ -143,18 +144,18 @@ public abstract class ArrowPopup int smallerRadius = resources.getDimensionPixelSize(R.dimen.popup_smaller_radius); mRoundedTop = new GradientDrawable(); - mRoundedTop.setColor(backgroundColor); + mRoundedTop.setColor(popupPrimaryColor); mRoundedTop.setCornerRadii(new float[] { mOutlineRadius, mOutlineRadius, mOutlineRadius, mOutlineRadius, smallerRadius, smallerRadius, smallerRadius, smallerRadius}); mRoundedBottom = new GradientDrawable(); - mRoundedBottom.setColor(backgroundColor); + mRoundedBottom.setColor(popupPrimaryColor); mRoundedBottom.setCornerRadii(new float[] { smallerRadius, smallerRadius, smallerRadius, smallerRadius, mOutlineRadius, mOutlineRadius, mOutlineRadius, mOutlineRadius}); mIterateChildrenTag = getContext().getString(R.string.popup_container_iterate_children); - if (mActivityContext.shouldUseColorExtractionForPopup()) { + if (!ENABLE_MATERIAL_U_POPUP.get() && mActivityContext.canUseMultipleShadesForPopup()) { mColorIds = new int[]{R.color.popup_shade_first, R.color.popup_shade_second, R.color.popup_shade_third}; } else { @@ -241,15 +242,23 @@ public abstract class ArrowPopup mlp.bottomMargin = 0; if (colors != null) { - backgroundColor = colors[numVisibleChild % colors.length]; + if (!ENABLE_MATERIAL_U_POPUP.get()) { + backgroundColor = colors[numVisibleChild % colors.length]; + } + + if (ENABLE_MATERIAL_U_POPUP.get() && isShortcutContainer(view)) { + setChildColor(view, colors[0], colorAnimator); + mArrowColor = colors[0]; + } } // Arrow color matches the first child or the last child. - if (mIsAboveIcon || (numVisibleChild == 0 && viewGroup == this)) { + if (!ENABLE_MATERIAL_U_POPUP.get() + && (mIsAboveIcon || (numVisibleChild == 0 && viewGroup == this))) { mArrowColor = backgroundColor; } - if (view instanceof ViewGroup && mIterateChildrenTag.equals(view.getTag())) { + if (view instanceof ViewGroup && isShortcutContainer(view)) { assignMarginsAndBackgrounds((ViewGroup) view, backgroundColor); numVisibleChild++; continue; @@ -286,6 +295,13 @@ public abstract class ArrowPopup return view instanceof DeepShortcutView; } + /** + * Returns {@code true} if view is a layout container of shortcuts + */ + boolean isShortcutContainer(View view) { + return mIterateChildrenTag.equals(view.getTag()); + } + /** * Sets the background color of the child. */ @@ -308,7 +324,7 @@ public abstract class ArrowPopup */ protected void reorderAndShow(int viewsToFlip) { setupForDisplay(); - boolean reverseOrder = mIsAboveIcon; + boolean reverseOrder = !ENABLE_MATERIAL_U_POPUP.get() && mIsAboveIcon; if (reverseOrder) { reverseOrder(viewsToFlip); } @@ -634,7 +650,7 @@ public abstract class ArrowPopup for (int i = group.getChildCount() - 1; i >= 0; --i) { View view = group.getChildAt(i); if (view.getVisibility() == VISIBLE && view instanceof ViewGroup) { - if (mIterateChildrenTag.equals(view.getTag())) { + if (isShortcutContainer(view)) { fadeInChildViews((ViewGroup) view, alphaValues, startDelay, duration, out); continue; } diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java index 4da588e839..8fef5c6bef 100644 --- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java +++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java @@ -17,12 +17,16 @@ package com.android.launcher3.popup; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SHORTCUTS; +import static com.android.launcher3.Utilities.ATLEAST_P; import static com.android.launcher3.Utilities.squaredHypot; import static com.android.launcher3.Utilities.squaredTouchSlop; +import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP; import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS; import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS_IF_NOTIFICATIONS; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; +import static java.util.Collections.emptyList; + import android.animation.AnimatorSet; import android.animation.LayoutTransition; import android.annotation.TargetApi; @@ -39,6 +43,8 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; +import androidx.annotation.LayoutRes; + import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.BubbleTextView; @@ -82,20 +88,20 @@ import java.util.stream.Collectors; public class PopupContainerWithArrow extends ArrowPopup implements DragSource, DragController.DragListener { - private final List mShortcuts = new ArrayList<>(); + private final List mDeepShortcuts = new ArrayList<>(); private final PointF mInterceptTouchDown = new PointF(); private final int mStartDragThreshold; + private static final int SHORTCUT_COLLAPSE_THRESHOLD = 6; + private BubbleTextView mOriginalIcon; private int mNumNotifications; private NotificationContainer mNotificationContainer; private int mContainerWidth; private ViewGroup mWidgetContainer; - private ViewGroup mDeepShortcutContainer; - private ViewGroup mSystemShortcutContainer; protected PopupItemDragHandler mPopupItemDragHandler; @@ -211,19 +217,27 @@ public class PopupContainerWithArrow return null; } - final PopupContainerWithArrow container = - (PopupContainerWithArrow) launcher.getLayoutInflater().inflate( - R.layout.popup_container, launcher.getDragLayer(), false); - container.configureForLauncher(launcher); - + PopupContainerWithArrow container; PopupDataProvider popupDataProvider = launcher.getPopupDataProvider(); - container.populateAndShow(icon, - popupDataProvider.getShortcutCountForItem(item), - popupDataProvider.getNotificationKeysForItem(item), - launcher.getSupportedShortcuts() - .map(s -> s.getShortcut(launcher, item, icon)) - .filter(Objects::nonNull) - .collect(Collectors.toList())); + int deepShortcutCount = popupDataProvider.getShortcutCountForItem(item); + List systemShortcuts = launcher.getSupportedShortcuts() + .map(s -> s.getShortcut(launcher, item, icon)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + if (ENABLE_MATERIAL_U_POPUP.get()) { + container = (PopupContainerWithArrow) launcher.getLayoutInflater().inflate( + R.layout.popup_container_material_u, launcher.getDragLayer(), false); + container.populateAndShowRowsMaterialU(icon, deepShortcutCount, systemShortcuts); + } else { + container = (PopupContainerWithArrow) launcher.getLayoutInflater().inflate( + R.layout.popup_container, launcher.getDragLayer(), false); + container.populateAndShow( + icon, + deepShortcutCount, + popupDataProvider.getNotificationKeysForItem(item), + systemShortcuts); + } + container.configureForLauncher(launcher); launcher.refreshAndBindWidgetsForPackageUser(PackageUserKey.fromItemInfo(item)); container.requestFocus(); return container; @@ -246,7 +260,7 @@ public class PopupContainerWithArrow initializeSystemShortcut(R.layout.system_shortcut, this, shortcuts.get(0)); return; } - mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_icons, this); + mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_icons_container, this); for (SystemShortcut shortcut : shortcuts) { initializeSystemShortcut( R.layout.system_shortcut_icon_only, mSystemShortcutContainer, @@ -281,17 +295,7 @@ public class PopupContainerWithArrow mDeepShortcutContainer = findViewById(R.id.deep_shortcuts_container); } if (hasDeepShortcuts) { - // Remove the widget shortcut fom the list - List systemShortcuts = shortcuts - .stream() - .filter(shortcut -> !(shortcut instanceof SystemShortcut.Widgets)) - .collect(Collectors.toList()); - Optional widgetShortcutOpt = shortcuts - .stream() - .filter(shortcut -> shortcut instanceof SystemShortcut.Widgets) - .map(SystemShortcut.Widgets.class::cast) - .findFirst(); - + List systemShortcuts = getNonWidgetSystemShortcuts(shortcuts); // 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, @@ -304,10 +308,10 @@ public class PopupContainerWithArrow for (int i = shortcutCount; i > 0; i--) { DeepShortcutView v = inflateAndAdd(R.layout.deep_shortcut, mDeepShortcutContainer); v.getLayoutParams().width = mContainerWidth; - mShortcuts.add(v); + mDeepShortcuts.add(v); } updateHiddenShortcuts(); - + Optional widgetShortcutOpt = getWidgetShortcut(shortcuts); if (widgetShortcutOpt.isPresent()) { if (mWidgetContainer == null) { mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container, @@ -327,21 +331,151 @@ public class PopupContainerWithArrow } reorderAndShow(viewsToFlip); + showPopupContainer((ItemInfo) originalIcon.getTag(), notificationKeys); + } - ItemInfo originalItemInfo = (ItemInfo) originalIcon.getTag(); - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - setAccessibilityPaneTitle(getTitleForAccessibility()); + /** + * Populate and show shortcuts for the Launcher U app shortcut design. + * Will inflate the container and shortcut View instances for the popup container. + * @param originalIcon App icon that the popup is shown for + * @param deepShortcutCount Number of DeepShortcutView instances to add to container + * @param systemShortcuts List of SystemShortcuts to add to container + */ + public void populateAndShowRowsMaterialU(final BubbleTextView originalIcon, + int deepShortcutCount, List systemShortcuts) { + + mOriginalIcon = originalIcon; + mContainerWidth = getResources().getDimensionPixelSize(R.dimen.bg_popup_item_width); + + if (deepShortcutCount > 0) { + addAllShortcutsMaterialU(deepShortcutCount, systemShortcuts); + } else if (!systemShortcuts.isEmpty()) { + addSystemShortcutsMaterialU(systemShortcuts, + R.layout.system_shortcut_rows_container_material_u, + R.layout.system_shortcut); } - mOriginalIcon.setForceHideDot(true); + // no reversing needed for U design + reorderAndShow(0); + showPopupContainer((ItemInfo) originalIcon.getTag(), /* notificationKeys= */ emptyList()); + } + /** + * Animates and loads shortcuts on background thread for this popup container + */ + private void showPopupContainer(ItemInfo originalItemInfo, + List notificationKeys) { + + if (ATLEAST_P) { + setAccessibilityPaneTitle(getTitleForAccessibility()); + } + mOriginalIcon.setForceHideDot(true); // All views are added. Animate layout from now on. setLayoutTransition(new LayoutTransition()); - // Load the shortcuts on a background thread and update the container as it animates. MODEL_EXECUTOR.getHandler().postAtFrontOfQueue(PopupPopulator.createUpdateRunnable( mActivityContext, originalItemInfo, new Handler(Looper.getMainLooper()), - this, mShortcuts, notificationKeys)); + this, mDeepShortcuts, notificationKeys)); + } + + /** + * Adds any Deep Shortcuts, System Shortcuts and the Widget Shortcut to their respective + * containers + * @param deepShortcutCount number of DeepShortcutView instances + * @param systemShortcuts List of SystemShortcuts + */ + private void addAllShortcutsMaterialU(int deepShortcutCount, + List systemShortcuts) { + + if (deepShortcutCount + systemShortcuts.size() <= SHORTCUT_COLLAPSE_THRESHOLD) { + // add all system shortcuts including widgets shortcut to same container + addSystemShortcutsMaterialU(systemShortcuts, + R.layout.system_shortcut_rows_container_material_u, + R.layout.system_shortcut); + addDeepShortcutsMaterialU(deepShortcutCount); + return; + } + + List nonWidgetSystemShortcuts = + getNonWidgetSystemShortcuts(systemShortcuts); + // If total shortcuts over threshold, collapse system shortcuts to single row + addSystemShortcutsMaterialU(nonWidgetSystemShortcuts, + R.layout.system_shortcut_icons_container_material_u, + R.layout.system_shortcut_icon_only); + // May need to recalculate row width + mContainerWidth = Math.max(mContainerWidth, + nonWidgetSystemShortcuts.size() * getResources() + .getDimensionPixelSize(R.dimen.system_shortcut_header_icon_touch_size)); + // Add widget shortcut to separate container + Optional widgetShortcutOpt = getWidgetShortcut(systemShortcuts); + if (widgetShortcutOpt.isPresent()) { + mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container_material_u, + this); + initializeWidgetShortcut(mWidgetContainer, widgetShortcutOpt.get()); + } + addDeepShortcutsMaterialU(deepShortcutCount); + } + + /** + * Finds the first instance of the Widgets Shortcut from the SystemShortcut List + * @param systemShortcuts List of SystemShortcut instances to search + * @return Optional Widgets SystemShortcut + */ + private static Optional getWidgetShortcut( + List systemShortcuts) { + return systemShortcuts + .stream() + .filter(shortcut -> shortcut instanceof SystemShortcut.Widgets) + .map(SystemShortcut.Widgets.class::cast) + .findFirst(); + } + + /** + * Returns list of [systemShortcuts] without the Widgets shortcut instance if found + * @param systemShortcuts list of SystemShortcuts to filter from + * @return systemShortcuts without the Widgets Shortcut + */ + private static List getNonWidgetSystemShortcuts( + List systemShortcuts) { + + return systemShortcuts + .stream() + .filter(shortcut -> !(shortcut instanceof SystemShortcut.Widgets)) + .collect(Collectors.toList()); + } + + /** + * Inflates the given systemShortcutContainerLayout as a container, and populates with + * the systemShortcuts as views using the systemShortcutLayout + * @param systemShortcuts List of SystemShortcut to inflate as Views + * @param systemShortcutContainerLayout Layout Resource for the Container of shortcut Views + * @param systemShortcutLayout Layout Resource for the individual shortcut Views + */ + private void addSystemShortcutsMaterialU(List systemShortcuts, + @LayoutRes int systemShortcutContainerLayout, @LayoutRes int systemShortcutLayout) { + + if (systemShortcuts.size() == 0) { + return; + } + mSystemShortcutContainer = inflateAndAdd(systemShortcutContainerLayout, this); + for (SystemShortcut shortcut : systemShortcuts) { + initializeSystemShortcut(systemShortcutLayout, mSystemShortcutContainer, shortcut); + } + } + + /** + * Inflates and adds [deepShortcutCount] number of DeepShortcutView for the to a new container + * @param deepShortcutCount number of DeepShortcutView instances to add + */ + private void addDeepShortcutsMaterialU(int deepShortcutCount) { + mDeepShortcutContainer = inflateAndAdd(R.layout.deep_shortcut_container, this); + for (int i = deepShortcutCount; i > 0; i--) { + DeepShortcutView v = inflateAndAdd(R.layout.deep_shortcut_material_u, + mDeepShortcutContainer); + v.getLayoutParams().width = mContainerWidth; + mDeepShortcuts.add(v); + } + updateHiddenShortcuts(); } protected NotificationContainer getNotificationContainer() { @@ -391,9 +525,9 @@ public class PopupContainerWithArrow int allowedCount = mNotificationContainer != null ? MAX_SHORTCUTS_IF_NOTIFICATIONS : MAX_SHORTCUTS; - int total = mShortcuts.size(); + int total = mDeepShortcuts.size(); for (int i = 0; i < total; i++) { - DeepShortcutView view = mShortcuts.get(i); + DeepShortcutView view = mDeepShortcuts.get(i); view.setVisibility(i >= allowedCount ? GONE : VISIBLE); } } diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java index c8455b8a2b..2ffe34f415 100644 --- a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java +++ b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java @@ -18,6 +18,7 @@ package com.android.launcher3.secondarydisplay; import static android.view.View.MeasureSpec.EXACTLY; import static android.view.View.MeasureSpec.makeMeasureSpec; +import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP; import static com.android.launcher3.popup.SystemShortcut.APP_INFO; import android.content.Context; @@ -203,14 +204,22 @@ public class SecondaryDragLayer extends BaseDragLayer systemShortcuts.add(mPinnedAppsAdapter.getSystemShortcut(item, v)); } systemShortcuts.add(APP_INFO.getShortcut(mActivity, item, v)); - - final PopupContainerWithArrow container = - (PopupContainerWithArrow) mActivity.getLayoutInflater().inflate( - R.layout.popup_container, mActivity.getDragLayer(), false); - - container.populateAndShow((BubbleTextView) v, - popupDataProvider.getShortcutCountForItem(item), - Collections.emptyList(), systemShortcuts); + int deepShortcutCount = popupDataProvider.getShortcutCountForItem(item); + final PopupContainerWithArrow container; + if (ENABLE_MATERIAL_U_POPUP.get()) { + container = (PopupContainerWithArrow) mActivity.getLayoutInflater().inflate( + R.layout.popup_container_material_u, mActivity.getDragLayer(), false); + container.populateAndShowRowsMaterialU((BubbleTextView) v, deepShortcutCount, + systemShortcuts); + } else { + container = (PopupContainerWithArrow) mActivity.getLayoutInflater().inflate( + R.layout.popup_container, mActivity.getDragLayer(), false); + container.populateAndShow( + (BubbleTextView) v, + deepShortcutCount, + Collections.emptyList(), + systemShortcuts); + } container.requestFocus(); if (!FeatureFlags.SECONDARY_DRAG_N_DROP_TO_PIN.get() || !mActivity.isAppDrawerShown()) { diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java index 2ab46016c0..f7837f50b0 100644 --- a/src/com/android/launcher3/views/ActivityContext.java +++ b/src/com/android/launcher3/views/ActivityContext.java @@ -199,9 +199,9 @@ public interface ActivityContext { } /** - * Returns {@code true} if popups should use color extraction. + * Returns {@code true} if popups can use a range of color shades instead of a singular color. */ - default boolean shouldUseColorExtractionForPopup() { + default boolean canUseMultipleShadesForPopup() { return true; } diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java index 5b57e22d81..315cbadd04 100644 --- a/src/com/android/launcher3/views/OptionsPopupView.java +++ b/src/com/android/launcher3/views/OptionsPopupView.java @@ -15,12 +15,16 @@ */ package com.android.launcher3.views; +import static androidx.core.content.ContextCompat.getColorStateList; + +import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SETTINGS_BUTTON_TAP_OR_LONGPRESS; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGETSTRAY_BUTTON_TAP_OR_LONGPRESS; import android.content.Context; import android.content.Intent; +import android.graphics.Color; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; @@ -31,6 +35,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; +import android.view.ViewGroup; import android.widget.Toast; import androidx.annotation.Nullable; @@ -139,6 +144,16 @@ public class OptionsPopupView extends ArrowPopup mTargetRect.roundOut(outPos); } + @Override + public void assignMarginsAndBackgrounds(ViewGroup viewGroup) { + if (ENABLE_MATERIAL_U_POPUP.get()) { + assignMarginsAndBackgrounds(viewGroup, + getColorStateList(getContext(), mColorIds[0]).getDefaultColor()); + } else { + assignMarginsAndBackgrounds(viewGroup, Color.TRANSPARENT); + } + } + public static OptionsPopupView show(ActivityContext launcher, RectF targetRect, List items, boolean shouldAddArrow) { return show(launcher, targetRect, items, shouldAddArrow, 0 /* width */);