Loading res/layout/shortcuts_item.xml +9 −1 Original line number Diff line number Diff line Loading @@ -22,10 +22,18 @@ android:elevation="@dimen/deep_shortcuts_elevation"> <LinearLayout android:id="@+id/deep_shortcuts" android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <!-- The shortcuts header is added at runtime when necessary. --> <LinearLayout android:id="@+id/shortcuts" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" /> </LinearLayout> </com.android.launcher3.shortcuts.ShortcutsItemView> res/layout/system_shortcut_icons.xml +4 −1 Original line number Diff line number Diff line Loading @@ -21,4 +21,7 @@ android:layout_height="@dimen/system_shortcut_header_height" android:orientation="horizontal" android:gravity="end|center_vertical" android:background="?attr/popupColorSecondary" /> android:background="?attr/popupColorSecondary" android:elevation="1dp" android:outlineProvider="none" /> <!-- We have elevation so this is drawn on top, but no outline provider to remove shadow --> src/com/android/launcher3/notification/NotificationItemView.java +8 −3 Original line number Diff line number Diff line Loading @@ -86,11 +86,16 @@ public class NotificationItemView extends PopupItemView implements LogContainerP return getHeight() - footerHeight; } public Animator animateHeightRemoval(int heightToRemove) { public Animator animateHeightRemoval(int heightToRemove, boolean shouldRemoveFromTop) { Rect startRect = new Rect(mPillRect); Rect endRect = new Rect(mPillRect); if (shouldRemoveFromTop) { endRect.top += heightToRemove; } else { endRect.bottom -= heightToRemove; } return new RoundedRectRevealOutlineProvider(getBackgroundRadius(), getBackgroundRadius(), mPillRect, endRect, mRoundedCorners).createRevealAnimator(this, false); startRect, endRect, mRoundedCorners).createRevealAnimator(this, false); } public void updateHeader(int notificationCount, @Nullable IconPalette palette) { Loading src/com/android/launcher3/popup/PopupContainerWithArrow.java +49 −17 Original line number Diff line number Diff line Loading @@ -82,6 +82,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS_IF_NOTIFICATIONS; import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import static com.android.launcher3.userevent.nano.LauncherLogProto.ItemType; import static com.android.launcher3.userevent.nano.LauncherLogProto.Target; Loading Loading @@ -191,7 +192,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra // Add dummy views first, and populate with real info when ready. PopupPopulator.Item[] itemsToPopulate = PopupPopulator .getItemsToPopulate(shortcutIds, notificationKeys, systemShortcuts); addDummyViews(itemsToPopulate, notificationKeys.size() > 1); addDummyViews(itemsToPopulate, notificationKeys.size()); measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset); Loading @@ -202,7 +203,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra mNotificationItemView = null; mShortcutsItemView = null; itemsToPopulate = PopupPopulator.reverseItems(itemsToPopulate); addDummyViews(itemsToPopulate, notificationKeys.size() > 1); addDummyViews(itemsToPopulate, notificationKeys.size()); measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset); Loading Loading @@ -252,8 +253,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra systemShortcuts, systemShortcutViews)); } private void addDummyViews(PopupPopulator.Item[] itemTypesToPopulate, boolean notificationFooterHasIcons) { private void addDummyViews(PopupPopulator.Item[] itemTypesToPopulate, int numNotifications) { final Resources res = getResources(); final LayoutInflater inflater = mLauncher.getLayoutInflater(); Loading @@ -274,6 +274,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra if (itemTypeToPopulate == PopupPopulator.Item.NOTIFICATION) { mNotificationItemView = (NotificationItemView) item; boolean notificationFooterHasIcons = numNotifications > 1; int footerHeight = notificationFooterHasIcons ? res.getDimensionPixelSize(R.dimen.notification_footer_height) : 0; item.findViewById(R.id.footer).getLayoutParams().height = footerHeight; Loading Loading @@ -316,6 +317,9 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra int backgroundColor = Themes.getAttrColor(mLauncher, mNotificationItemView == null ? R.attr.popupColorPrimary : R.attr.popupColorSecondary); mShortcutsItemView.setBackgroundWithCorners(backgroundColor, shortcutsItemRoundedCorners); if (numNotifications > 0) { mShortcutsItemView.hideShortcuts(mIsAboveIcon, MAX_SHORTCUTS_IF_NOTIFICATIONS); } } protected PopupItemView getItemViewAt(int index) { Loading Loading @@ -639,11 +643,22 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra ItemInfo originalInfo = (ItemInfo) mOriginalIcon.getTag(); BadgeInfo badgeInfo = updatedBadges.get(PackageUserKey.fromItemInfo(originalInfo)); if (badgeInfo == null || badgeInfo.getNotificationKeys().size() == 0) { // There are no more notifications, so create an animation to remove // the notifications view and expand the shortcuts view (if possible). AnimatorSet removeNotification = LauncherAnimUtils.createAnimatorSet(); int hiddenShortcutsHeight = 0; if (mShortcutsItemView != null) { hiddenShortcutsHeight = mShortcutsItemView.getHiddenShortcutsHeight(); int backgroundColor = Themes.getAttrColor(mLauncher, R.attr.popupColorPrimary); // With notifications gone, all corners of shortcuts item should be rounded. mShortcutsItemView.setBackgroundWithCorners(backgroundColor, ROUNDED_TOP_CORNERS | ROUNDED_BOTTOM_CORNERS); removeNotification.play(mShortcutsItemView.showAllShortcuts(mIsAboveIcon)); } final int duration = getResources().getInteger( R.integer.config_removeNotificationViewDuration); removeNotification.play(reduceNotificationViewHeight( mNotificationItemView.getHeightMinusFooter(), duration)); removeNotification.play(adjustItemHeights(mNotificationItemView.getHeightMinusFooter(), hiddenShortcutsHeight, duration)); Animator fade = ObjectAnimator.ofFloat(mNotificationItemView, ALPHA, 0) .setDuration(duration); fade.addListener(new AnimatorListenerAdapter() { Loading @@ -665,12 +680,6 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra showArrow.setStartDelay((long) (duration - arrowScaleDuration * 1.5)); removeNotification.playSequentially(hideArrow, showArrow); removeNotification.start(); if (mShortcutsItemView != null) { int backgroundColor = Themes.getAttrColor(mLauncher, R.attr.popupColorPrimary); // With notifications gone, all corners of shortcuts item should be rounded. mShortcutsItemView.setBackgroundWithCorners(backgroundColor, ROUNDED_TOP_CORNERS | ROUNDED_BOTTOM_CORNERS); } return; } mNotificationItemView.trimNotifications(NotificationKeyData.extractKeysOnly( Loading @@ -689,28 +698,50 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra mArrow, new PropertyListBuilder().scale(scale).build()); } public Animator reduceNotificationViewHeight(int heightToRemove, int duration) { return adjustItemHeights(heightToRemove, 0, duration); } /** * Animates the height of the notification item and the translationY of other items accordingly. */ public Animator reduceNotificationViewHeight(int heightToRemove, int duration) { public Animator adjustItemHeights(int notificationHeightToRemove, int shortcutHeightToAdd, int duration) { if (mReduceHeightAnimatorSet != null) { mReduceHeightAnimatorSet.cancel(); } final int translateYBy = mIsAboveIcon ? heightToRemove : -heightToRemove; final int translateYBy = mIsAboveIcon ? notificationHeightToRemove - shortcutHeightToAdd : -notificationHeightToRemove; mReduceHeightAnimatorSet = LauncherAnimUtils.createAnimatorSet(); mReduceHeightAnimatorSet.play(mNotificationItemView.animateHeightRemoval(heightToRemove)); boolean removingNotification = notificationHeightToRemove == mNotificationItemView.getHeightMinusFooter(); boolean shouldRemoveNotificationHeightFromTop = mIsAboveIcon && removingNotification; mReduceHeightAnimatorSet.play(mNotificationItemView.animateHeightRemoval( notificationHeightToRemove, shouldRemoveNotificationHeightFromTop)); PropertyResetListener<View, Float> resetTranslationYListener = new PropertyResetListener<>(TRANSLATION_Y, 0f); boolean itemIsAfterShortcuts = false; for (int i = 0; i < getItemCount(); i++) { final PopupItemView itemView = getItemViewAt(i); if (!mIsAboveIcon && itemView == mNotificationItemView) { // The notification view is already in the right place when container is below icon. if (itemIsAfterShortcuts) { // Every item after the shortcuts item needs to adjust for the new height. itemView.setTranslationY(itemView.getTranslationY() - shortcutHeightToAdd); } if (itemView == mNotificationItemView && (!mIsAboveIcon || removingNotification)) { // The notification view is already in the right place. continue; } ValueAnimator translateItem = ObjectAnimator.ofFloat(itemView, TRANSLATION_Y, itemView.getTranslationY() + translateYBy).setDuration(duration); translateItem.addListener(resetTranslationYListener); mReduceHeightAnimatorSet.play(translateItem); if (itemView == mShortcutsItemView) { itemIsAfterShortcuts = true; } } if (mIsAboveIcon) { // We also need to adjust the arrow position to account for the new shortcuts height. mArrow.setTranslationY(mArrow.getTranslationY() - shortcutHeightToAdd); } mReduceHeightAnimatorSet.addListener(new AnimatorListenerAdapter() { @Override Loading @@ -720,6 +751,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra // container itself did not. This means the items would jump back to their // original translation unless we update the container's translationY here. setTranslationY(getTranslationY() + translateYBy); mArrow.setTranslationY(0); } mReduceHeightAnimatorSet = null; } Loading src/com/android/launcher3/popup/PopupPopulator.java +11 −14 Original line number Diff line number Diff line Loading @@ -52,9 +52,9 @@ import java.util.List; */ public class PopupPopulator { public static final int MAX_ITEMS = 4; public static final int MAX_SHORTCUTS = 4; @VisibleForTesting static final int NUM_DYNAMIC = 2; private static final int MAX_SHORTCUTS_IF_NOTIFICATIONS = 2; public static final int MAX_SHORTCUTS_IF_NOTIFICATIONS = 2; public enum Item { SHORTCUT(R.layout.deep_shortcut, true), Loading @@ -77,10 +77,7 @@ public class PopupPopulator { boolean hasNotifications = notificationKeys.size() > 0; int numNotificationItems = hasNotifications ? 1 : 0; int numShortcuts = shortcutIds.size(); if (hasNotifications && numShortcuts > MAX_SHORTCUTS_IF_NOTIFICATIONS) { numShortcuts = MAX_SHORTCUTS_IF_NOTIFICATIONS; } int numItems = Math.min(MAX_ITEMS, numShortcuts + numNotificationItems) int numItems = Math.min(MAX_SHORTCUTS, numShortcuts) + numNotificationItems + systemShortcuts.size(); Item[] items = new Item[numItems]; for (int i = 0; i < numItems; i++) { Loading Loading @@ -126,12 +123,12 @@ public class PopupPopulator { }; /** * Filters the shortcuts so that only MAX_ITEMS or fewer shortcuts are retained. * Filters the shortcuts so that only MAX_SHORTCUTS or fewer shortcuts are retained. * We want the filter to include both static and dynamic shortcuts, so we always * include NUM_DYNAMIC dynamic shortcuts, if at least that many are present. * * @param shortcutIdToRemoveFirst An id that should be filtered out first, if any. * @return a subset of shortcuts, in sorted order, with size <= MAX_ITEMS. * @return a subset of shortcuts, in sorted order, with size <= MAX_SHORTCUTS. */ public static List<ShortcutInfoCompat> sortAndFilterShortcuts( List<ShortcutInfoCompat> shortcuts, @Nullable String shortcutIdToRemoveFirst) { Loading @@ -147,27 +144,27 @@ public class PopupPopulator { } Collections.sort(shortcuts, SHORTCUT_RANK_COMPARATOR); if (shortcuts.size() <= MAX_ITEMS) { if (shortcuts.size() <= MAX_SHORTCUTS) { return shortcuts; } // The list of shortcuts is now sorted with static shortcuts followed by dynamic // shortcuts. We want to preserve this order, but only keep MAX_ITEMS. List<ShortcutInfoCompat> filteredShortcuts = new ArrayList<>(MAX_ITEMS); // shortcuts. We want to preserve this order, but only keep MAX_SHORTCUTS. List<ShortcutInfoCompat> filteredShortcuts = new ArrayList<>(MAX_SHORTCUTS); int numDynamic = 0; int size = shortcuts.size(); for (int i = 0; i < size; i++) { ShortcutInfoCompat shortcut = shortcuts.get(i); int filteredSize = filteredShortcuts.size(); if (filteredSize < MAX_ITEMS) { // Always add the first MAX_ITEMS to the filtered list. if (filteredSize < MAX_SHORTCUTS) { // Always add the first MAX_SHORTCUTS to the filtered list. filteredShortcuts.add(shortcut); if (shortcut.isDynamic()) { numDynamic++; } continue; } // At this point, we have MAX_ITEMS already, but they may all be static. // At this point, we have MAX_SHORTCUTS already, but they may all be static. // If there are dynamic shortcuts, remove static shortcuts to add them. if (shortcut.isDynamic() && numDynamic < NUM_DYNAMIC) { numDynamic++; Loading Loading
res/layout/shortcuts_item.xml +9 −1 Original line number Diff line number Diff line Loading @@ -22,10 +22,18 @@ android:elevation="@dimen/deep_shortcuts_elevation"> <LinearLayout android:id="@+id/deep_shortcuts" android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <!-- The shortcuts header is added at runtime when necessary. --> <LinearLayout android:id="@+id/shortcuts" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" /> </LinearLayout> </com.android.launcher3.shortcuts.ShortcutsItemView>
res/layout/system_shortcut_icons.xml +4 −1 Original line number Diff line number Diff line Loading @@ -21,4 +21,7 @@ android:layout_height="@dimen/system_shortcut_header_height" android:orientation="horizontal" android:gravity="end|center_vertical" android:background="?attr/popupColorSecondary" /> android:background="?attr/popupColorSecondary" android:elevation="1dp" android:outlineProvider="none" /> <!-- We have elevation so this is drawn on top, but no outline provider to remove shadow -->
src/com/android/launcher3/notification/NotificationItemView.java +8 −3 Original line number Diff line number Diff line Loading @@ -86,11 +86,16 @@ public class NotificationItemView extends PopupItemView implements LogContainerP return getHeight() - footerHeight; } public Animator animateHeightRemoval(int heightToRemove) { public Animator animateHeightRemoval(int heightToRemove, boolean shouldRemoveFromTop) { Rect startRect = new Rect(mPillRect); Rect endRect = new Rect(mPillRect); if (shouldRemoveFromTop) { endRect.top += heightToRemove; } else { endRect.bottom -= heightToRemove; } return new RoundedRectRevealOutlineProvider(getBackgroundRadius(), getBackgroundRadius(), mPillRect, endRect, mRoundedCorners).createRevealAnimator(this, false); startRect, endRect, mRoundedCorners).createRevealAnimator(this, false); } public void updateHeader(int notificationCount, @Nullable IconPalette palette) { Loading
src/com/android/launcher3/popup/PopupContainerWithArrow.java +49 −17 Original line number Diff line number Diff line Loading @@ -82,6 +82,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS_IF_NOTIFICATIONS; import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import static com.android.launcher3.userevent.nano.LauncherLogProto.ItemType; import static com.android.launcher3.userevent.nano.LauncherLogProto.Target; Loading Loading @@ -191,7 +192,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra // Add dummy views first, and populate with real info when ready. PopupPopulator.Item[] itemsToPopulate = PopupPopulator .getItemsToPopulate(shortcutIds, notificationKeys, systemShortcuts); addDummyViews(itemsToPopulate, notificationKeys.size() > 1); addDummyViews(itemsToPopulate, notificationKeys.size()); measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset); Loading @@ -202,7 +203,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra mNotificationItemView = null; mShortcutsItemView = null; itemsToPopulate = PopupPopulator.reverseItems(itemsToPopulate); addDummyViews(itemsToPopulate, notificationKeys.size() > 1); addDummyViews(itemsToPopulate, notificationKeys.size()); measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset); Loading Loading @@ -252,8 +253,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra systemShortcuts, systemShortcutViews)); } private void addDummyViews(PopupPopulator.Item[] itemTypesToPopulate, boolean notificationFooterHasIcons) { private void addDummyViews(PopupPopulator.Item[] itemTypesToPopulate, int numNotifications) { final Resources res = getResources(); final LayoutInflater inflater = mLauncher.getLayoutInflater(); Loading @@ -274,6 +274,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra if (itemTypeToPopulate == PopupPopulator.Item.NOTIFICATION) { mNotificationItemView = (NotificationItemView) item; boolean notificationFooterHasIcons = numNotifications > 1; int footerHeight = notificationFooterHasIcons ? res.getDimensionPixelSize(R.dimen.notification_footer_height) : 0; item.findViewById(R.id.footer).getLayoutParams().height = footerHeight; Loading Loading @@ -316,6 +317,9 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra int backgroundColor = Themes.getAttrColor(mLauncher, mNotificationItemView == null ? R.attr.popupColorPrimary : R.attr.popupColorSecondary); mShortcutsItemView.setBackgroundWithCorners(backgroundColor, shortcutsItemRoundedCorners); if (numNotifications > 0) { mShortcutsItemView.hideShortcuts(mIsAboveIcon, MAX_SHORTCUTS_IF_NOTIFICATIONS); } } protected PopupItemView getItemViewAt(int index) { Loading Loading @@ -639,11 +643,22 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra ItemInfo originalInfo = (ItemInfo) mOriginalIcon.getTag(); BadgeInfo badgeInfo = updatedBadges.get(PackageUserKey.fromItemInfo(originalInfo)); if (badgeInfo == null || badgeInfo.getNotificationKeys().size() == 0) { // There are no more notifications, so create an animation to remove // the notifications view and expand the shortcuts view (if possible). AnimatorSet removeNotification = LauncherAnimUtils.createAnimatorSet(); int hiddenShortcutsHeight = 0; if (mShortcutsItemView != null) { hiddenShortcutsHeight = mShortcutsItemView.getHiddenShortcutsHeight(); int backgroundColor = Themes.getAttrColor(mLauncher, R.attr.popupColorPrimary); // With notifications gone, all corners of shortcuts item should be rounded. mShortcutsItemView.setBackgroundWithCorners(backgroundColor, ROUNDED_TOP_CORNERS | ROUNDED_BOTTOM_CORNERS); removeNotification.play(mShortcutsItemView.showAllShortcuts(mIsAboveIcon)); } final int duration = getResources().getInteger( R.integer.config_removeNotificationViewDuration); removeNotification.play(reduceNotificationViewHeight( mNotificationItemView.getHeightMinusFooter(), duration)); removeNotification.play(adjustItemHeights(mNotificationItemView.getHeightMinusFooter(), hiddenShortcutsHeight, duration)); Animator fade = ObjectAnimator.ofFloat(mNotificationItemView, ALPHA, 0) .setDuration(duration); fade.addListener(new AnimatorListenerAdapter() { Loading @@ -665,12 +680,6 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra showArrow.setStartDelay((long) (duration - arrowScaleDuration * 1.5)); removeNotification.playSequentially(hideArrow, showArrow); removeNotification.start(); if (mShortcutsItemView != null) { int backgroundColor = Themes.getAttrColor(mLauncher, R.attr.popupColorPrimary); // With notifications gone, all corners of shortcuts item should be rounded. mShortcutsItemView.setBackgroundWithCorners(backgroundColor, ROUNDED_TOP_CORNERS | ROUNDED_BOTTOM_CORNERS); } return; } mNotificationItemView.trimNotifications(NotificationKeyData.extractKeysOnly( Loading @@ -689,28 +698,50 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra mArrow, new PropertyListBuilder().scale(scale).build()); } public Animator reduceNotificationViewHeight(int heightToRemove, int duration) { return adjustItemHeights(heightToRemove, 0, duration); } /** * Animates the height of the notification item and the translationY of other items accordingly. */ public Animator reduceNotificationViewHeight(int heightToRemove, int duration) { public Animator adjustItemHeights(int notificationHeightToRemove, int shortcutHeightToAdd, int duration) { if (mReduceHeightAnimatorSet != null) { mReduceHeightAnimatorSet.cancel(); } final int translateYBy = mIsAboveIcon ? heightToRemove : -heightToRemove; final int translateYBy = mIsAboveIcon ? notificationHeightToRemove - shortcutHeightToAdd : -notificationHeightToRemove; mReduceHeightAnimatorSet = LauncherAnimUtils.createAnimatorSet(); mReduceHeightAnimatorSet.play(mNotificationItemView.animateHeightRemoval(heightToRemove)); boolean removingNotification = notificationHeightToRemove == mNotificationItemView.getHeightMinusFooter(); boolean shouldRemoveNotificationHeightFromTop = mIsAboveIcon && removingNotification; mReduceHeightAnimatorSet.play(mNotificationItemView.animateHeightRemoval( notificationHeightToRemove, shouldRemoveNotificationHeightFromTop)); PropertyResetListener<View, Float> resetTranslationYListener = new PropertyResetListener<>(TRANSLATION_Y, 0f); boolean itemIsAfterShortcuts = false; for (int i = 0; i < getItemCount(); i++) { final PopupItemView itemView = getItemViewAt(i); if (!mIsAboveIcon && itemView == mNotificationItemView) { // The notification view is already in the right place when container is below icon. if (itemIsAfterShortcuts) { // Every item after the shortcuts item needs to adjust for the new height. itemView.setTranslationY(itemView.getTranslationY() - shortcutHeightToAdd); } if (itemView == mNotificationItemView && (!mIsAboveIcon || removingNotification)) { // The notification view is already in the right place. continue; } ValueAnimator translateItem = ObjectAnimator.ofFloat(itemView, TRANSLATION_Y, itemView.getTranslationY() + translateYBy).setDuration(duration); translateItem.addListener(resetTranslationYListener); mReduceHeightAnimatorSet.play(translateItem); if (itemView == mShortcutsItemView) { itemIsAfterShortcuts = true; } } if (mIsAboveIcon) { // We also need to adjust the arrow position to account for the new shortcuts height. mArrow.setTranslationY(mArrow.getTranslationY() - shortcutHeightToAdd); } mReduceHeightAnimatorSet.addListener(new AnimatorListenerAdapter() { @Override Loading @@ -720,6 +751,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra // container itself did not. This means the items would jump back to their // original translation unless we update the container's translationY here. setTranslationY(getTranslationY() + translateYBy); mArrow.setTranslationY(0); } mReduceHeightAnimatorSet = null; } Loading
src/com/android/launcher3/popup/PopupPopulator.java +11 −14 Original line number Diff line number Diff line Loading @@ -52,9 +52,9 @@ import java.util.List; */ public class PopupPopulator { public static final int MAX_ITEMS = 4; public static final int MAX_SHORTCUTS = 4; @VisibleForTesting static final int NUM_DYNAMIC = 2; private static final int MAX_SHORTCUTS_IF_NOTIFICATIONS = 2; public static final int MAX_SHORTCUTS_IF_NOTIFICATIONS = 2; public enum Item { SHORTCUT(R.layout.deep_shortcut, true), Loading @@ -77,10 +77,7 @@ public class PopupPopulator { boolean hasNotifications = notificationKeys.size() > 0; int numNotificationItems = hasNotifications ? 1 : 0; int numShortcuts = shortcutIds.size(); if (hasNotifications && numShortcuts > MAX_SHORTCUTS_IF_NOTIFICATIONS) { numShortcuts = MAX_SHORTCUTS_IF_NOTIFICATIONS; } int numItems = Math.min(MAX_ITEMS, numShortcuts + numNotificationItems) int numItems = Math.min(MAX_SHORTCUTS, numShortcuts) + numNotificationItems + systemShortcuts.size(); Item[] items = new Item[numItems]; for (int i = 0; i < numItems; i++) { Loading Loading @@ -126,12 +123,12 @@ public class PopupPopulator { }; /** * Filters the shortcuts so that only MAX_ITEMS or fewer shortcuts are retained. * Filters the shortcuts so that only MAX_SHORTCUTS or fewer shortcuts are retained. * We want the filter to include both static and dynamic shortcuts, so we always * include NUM_DYNAMIC dynamic shortcuts, if at least that many are present. * * @param shortcutIdToRemoveFirst An id that should be filtered out first, if any. * @return a subset of shortcuts, in sorted order, with size <= MAX_ITEMS. * @return a subset of shortcuts, in sorted order, with size <= MAX_SHORTCUTS. */ public static List<ShortcutInfoCompat> sortAndFilterShortcuts( List<ShortcutInfoCompat> shortcuts, @Nullable String shortcutIdToRemoveFirst) { Loading @@ -147,27 +144,27 @@ public class PopupPopulator { } Collections.sort(shortcuts, SHORTCUT_RANK_COMPARATOR); if (shortcuts.size() <= MAX_ITEMS) { if (shortcuts.size() <= MAX_SHORTCUTS) { return shortcuts; } // The list of shortcuts is now sorted with static shortcuts followed by dynamic // shortcuts. We want to preserve this order, but only keep MAX_ITEMS. List<ShortcutInfoCompat> filteredShortcuts = new ArrayList<>(MAX_ITEMS); // shortcuts. We want to preserve this order, but only keep MAX_SHORTCUTS. List<ShortcutInfoCompat> filteredShortcuts = new ArrayList<>(MAX_SHORTCUTS); int numDynamic = 0; int size = shortcuts.size(); for (int i = 0; i < size; i++) { ShortcutInfoCompat shortcut = shortcuts.get(i); int filteredSize = filteredShortcuts.size(); if (filteredSize < MAX_ITEMS) { // Always add the first MAX_ITEMS to the filtered list. if (filteredSize < MAX_SHORTCUTS) { // Always add the first MAX_SHORTCUTS to the filtered list. filteredShortcuts.add(shortcut); if (shortcut.isDynamic()) { numDynamic++; } continue; } // At this point, we have MAX_ITEMS already, but they may all be static. // At this point, we have MAX_SHORTCUTS already, but they may all be static. // If there are dynamic shortcuts, remove static shortcuts to add them. if (shortcut.isDynamic() && numDynamic < NUM_DYNAMIC) { numDynamic++; Loading