summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/popup
diff options
context:
space:
mode:
authorTony <twickham@google.com>2017-05-30 21:22:06 -0700
committerTony Wickham <twickham@google.com>2017-06-15 16:21:34 -0700
commit887bd1fe1af9a37aad78ad51f5b38b265aa09c3a (patch)
tree9c1b74b18d46db8c07bf7be343620a2400ae8ad8 /src/com/android/launcher3/popup
parent7847d10f389425a92e11b29f181acbbebc8b1dab (diff)
downloadandroid_packages_apps_Trebuchet-887bd1fe1af9a37aad78ad51f5b38b265aa09c3a.tar.gz
android_packages_apps_Trebuchet-887bd1fe1af9a37aad78ad51f5b38b265aa09c3a.tar.bz2
android_packages_apps_Trebuchet-887bd1fe1af9a37aad78ad51f5b38b265aa09c3a.zip
Show more shortcuts when last notification is dimissed
We currently only show 2 shortcuts when notifications are present, but support up to 4 otherwise. With this change, the hidden shortcuts are added back after dismissing the notifications, instead of only after closing and reopening the container. To ensure the transition is as elegant as possible, we also separated the shortcuts header from the rest of the shortcuts. That way we can reveal the new shortcuts without removing the header (the shortcuts come out from behind the header). Bug: 38036250 Change-Id: Ie9ab35f9be57cec1d5345e9e70e84e09ea52c9fc
Diffstat (limited to 'src/com/android/launcher3/popup')
-rw-r--r--src/com/android/launcher3/popup/PopupContainerWithArrow.java66
-rw-r--r--src/com/android/launcher3/popup/PopupPopulator.java25
2 files changed, 60 insertions, 31 deletions
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 5463ef772..35e56ac68 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -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;
@@ -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);
@@ -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);
@@ -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();
@@ -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;
@@ -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) {
@@ -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() {
@@ -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(
@@ -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
@@ -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;
}
diff --git a/src/com/android/launcher3/popup/PopupPopulator.java b/src/com/android/launcher3/popup/PopupPopulator.java
index fd0010599..0dc1ca061 100644
--- a/src/com/android/launcher3/popup/PopupPopulator.java
+++ b/src/com/android/launcher3/popup/PopupPopulator.java
@@ -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),
@@ -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++) {
@@ -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) {
@@ -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++;