import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
-import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
-import android.graphics.Point;
+import android.graphics.CornerPathEffect;
+import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.ShapeDrawable;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
-import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
+import com.android.launcher3.FastBitmapDrawable;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.LauncherViewPropertyAnimator;
import com.android.launcher3.LogAccelerateInterpolator;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.accessibility.ShortcutMenuAccessibilityDelegate;
+import com.android.launcher3.anim.PropertyListBuilder;
+import com.android.launcher3.anim.PropertyResetListener;
import com.android.launcher3.badge.BadgeInfo;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragOptions;
-import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.graphics.TriangleShape;
import com.android.launcher3.notification.NotificationItemView;
+import com.android.launcher3.notification.NotificationKeyData;
+import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.DeepShortcutView;
-import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
+import com.android.launcher3.shortcuts.ShortcutsItemView;
import com.android.launcher3.util.PackageUserKey;
-import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
* A container for shortcuts to deep links within apps.
*/
@TargetApi(Build.VERSION_CODES.N)
-public class PopupContainerWithArrow extends AbstractFloatingView
- implements View.OnLongClickListener, View.OnTouchListener, DragSource,
+public class PopupContainerWithArrow extends AbstractFloatingView implements DragSource,
DragController.DragListener {
- private final Point mIconShift = new Point();
- private final Point mIconLastTouchPos = new Point();
-
protected final Launcher mLauncher;
private final int mStartDragThreshold;
private LauncherAccessibilityDelegate mAccessibilityDelegate;
private final boolean mIsRtl;
+ public ShortcutsItemView mShortcutsItemView;
+ private NotificationItemView mNotificationItemView;
+
protected BubbleTextView mOriginalIcon;
private final Rect mTempRect = new Rect();
private PointF mInterceptTouchDown = new PointF();
return null;
}
ItemInfo itemInfo = (ItemInfo) icon.getTag();
+ if (!DeepShortcutManager.supportsShortcuts(itemInfo)) {
+ return null;
+ }
+
List<String> shortcutIds = launcher.getPopupDataProvider().getShortcutIdsForItem(itemInfo);
- String[] notificationKeys = launcher.getPopupDataProvider()
+ List<NotificationKeyData> notificationKeys = launcher.getPopupDataProvider()
.getNotificationKeysForItem(itemInfo);
- if (shortcutIds.size() > 0 || notificationKeys.length > 0) {
- final PopupContainerWithArrow container =
- (PopupContainerWithArrow) launcher.getLayoutInflater().inflate(
- R.layout.popup_container, launcher.getDragLayer(), false);
- container.setVisibility(View.INVISIBLE);
- launcher.getDragLayer().addView(container);
- container.populateAndShow(icon, shortcutIds, notificationKeys);
- return container;
- }
- return null;
+
+ final PopupContainerWithArrow container =
+ (PopupContainerWithArrow) launcher.getLayoutInflater().inflate(
+ R.layout.popup_container, launcher.getDragLayer(), false);
+ container.setVisibility(View.INVISIBLE);
+ launcher.getDragLayer().addView(container);
+ container.populateAndShow(icon, shortcutIds, notificationKeys);
+ return container;
}
public void populateAndShow(final BubbleTextView originalIcon, final List<String> shortcutIds,
- final String[] notificationKeys) {
+ final List<NotificationKeyData> notificationKeys) {
final Resources resources = getResources();
- final int arrowWidth = resources.getDimensionPixelSize(R.dimen.deep_shortcuts_arrow_width);
- final int arrowHeight = resources.getDimensionPixelSize(R.dimen.deep_shortcuts_arrow_height);
+ final int arrowWidth = resources.getDimensionPixelSize(R.dimen.popup_arrow_width);
+ final int arrowHeight = resources.getDimensionPixelSize(R.dimen.popup_arrow_height);
final int arrowHorizontalOffset = resources.getDimensionPixelSize(
- R.dimen.deep_shortcuts_arrow_horizontal_offset);
+ R.dimen.popup_arrow_horizontal_offset);
final int arrowVerticalOffset = resources.getDimensionPixelSize(
- R.dimen.deep_shortcuts_arrow_vertical_offset);
+ R.dimen.popup_arrow_vertical_offset);
// Add dummy views first, and populate with real info when ready.
PopupPopulator.Item[] itemsToPopulate = PopupPopulator
.getItemsToPopulate(shortcutIds, notificationKeys);
- addDummyViews(originalIcon, itemsToPopulate, notificationKeys.length > 1);
+ addDummyViews(originalIcon, itemsToPopulate, notificationKeys.size() > 1);
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset);
boolean reverseOrder = mIsAboveIcon;
if (reverseOrder) {
removeAllViews();
+ mNotificationItemView = null;
+ mShortcutsItemView = null;
itemsToPopulate = PopupPopulator.reverseItems(itemsToPopulate);
- addDummyViews(originalIcon, itemsToPopulate, notificationKeys.length > 1);
+ addDummyViews(originalIcon, itemsToPopulate, notificationKeys.size() > 1);
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset);
}
- List<DeepShortcutView> shortcutViews = new ArrayList<>();
- NotificationItemView notificationView = null;
- for (int i = 0; i < getChildCount(); i++) {
- View item = getChildAt(i);
- switch (itemsToPopulate[i]) {
- case SHORTCUT:
- if (reverseOrder) {
- shortcutViews.add(0, (DeepShortcutView) item);
- } else {
- shortcutViews.add((DeepShortcutView) item);
- }
- break;
- case NOTIFICATION:
- notificationView = (NotificationItemView) item;
- IconPalette iconPalette = originalIcon.getIconPalette();
- notificationView.applyColors(iconPalette);
- break;
- }
+ ItemInfo originalItemInfo = (ItemInfo) originalIcon.getTag();
+ List<DeepShortcutView> shortcutViews = mShortcutsItemView == null
+ ? Collections.EMPTY_LIST
+ : mShortcutsItemView.getDeepShortcutViews(reverseOrder);
+ List<View> systemShortcutViews = mShortcutsItemView == null
+ ? Collections.EMPTY_LIST
+ : mShortcutsItemView.getSystemShortcutViews(reverseOrder);
+ if (mNotificationItemView != null) {
+ BadgeInfo badgeInfo = mLauncher.getPopupDataProvider()
+ .getBadgeInfoForItem(originalItemInfo);
+ updateNotificationHeader(badgeInfo, originalIcon);
}
// Add the arrow.
mArrow = addArrowView(arrowHorizontalOffset, arrowVerticalOffset, arrowWidth, arrowHeight);
mArrow.setPivotX(arrowWidth / 2);
mArrow.setPivotY(mIsAboveIcon ? 0 : arrowHeight);
- PopupItemView firstItem = getItemViewAt(mIsAboveIcon ? getItemCount() - 1 : 0);
- mArrow.setBackgroundTintList(firstItem.getAttachedArrowColor());
animateOpen();
// Load the shortcuts on a background thread and update the container as it animates.
final Looper workerLooper = LauncherModel.getWorkerLooper();
new Handler(workerLooper).postAtFrontOfQueue(PopupPopulator.createUpdateRunnable(
- mLauncher, (ItemInfo) originalIcon.getTag(), new Handler(Looper.getMainLooper()),
- this, shortcutIds, shortcutViews, notificationKeys, notificationView));
+ mLauncher, originalItemInfo, new Handler(Looper.getMainLooper()),
+ this, shortcutIds, shortcutViews, notificationKeys, mNotificationItemView,
+ systemShortcutViews));
}
private void addDummyViews(BubbleTextView originalIcon,
- PopupPopulator.Item[] itemsToPopulate, boolean secondaryNotificationViewHasIcons) {
+ PopupPopulator.Item[] itemTypesToPopulate, boolean notificationFooterHasIcons) {
final Resources res = getResources();
- final int spacing = res.getDimensionPixelSize(R.dimen.deep_shortcuts_spacing);
+ final int spacing = res.getDimensionPixelSize(R.dimen.popup_items_spacing);
final LayoutInflater inflater = mLauncher.getLayoutInflater();
- int numItems = itemsToPopulate.length;
+
+ int numItems = itemTypesToPopulate.length;
for (int i = 0; i < numItems; i++) {
- final PopupItemView item = (PopupItemView) inflater.inflate(
- itemsToPopulate[i].layoutId, this, false);
- if (itemsToPopulate[i] == PopupPopulator.Item.NOTIFICATION) {
- int secondaryHeight = secondaryNotificationViewHasIcons ?
- res.getDimensionPixelSize(R.dimen.notification_footer_height) :
- res.getDimensionPixelSize(R.dimen.notification_footer_collapsed_height);
- item.findViewById(R.id.footer).getLayoutParams().height = secondaryHeight;
- }
- if (i < numItems - 1) {
- ((LayoutParams) item.getLayoutParams()).bottomMargin = spacing;
+ PopupPopulator.Item itemTypeToPopulate = itemTypesToPopulate[i];
+ PopupPopulator.Item nextItemTypeToPopulate =
+ i < numItems - 1 ? itemTypesToPopulate[i + 1] : null;
+ final View item = inflater.inflate(itemTypeToPopulate.layoutId, this, false);
+
+ if (itemTypeToPopulate == PopupPopulator.Item.NOTIFICATION) {
+ mNotificationItemView = (NotificationItemView) item;
+ int footerHeight = notificationFooterHasIcons ?
+ res.getDimensionPixelSize(R.dimen.notification_footer_height) : 0;
+ item.findViewById(R.id.footer).getLayoutParams().height = footerHeight;
}
+
+ boolean shouldAddBottomMargin = nextItemTypeToPopulate != null
+ && itemTypeToPopulate.isShortcut ^ nextItemTypeToPopulate.isShortcut;
+
item.setAccessibilityDelegate(mAccessibilityDelegate);
- addView(item);
+ if (itemTypeToPopulate.isShortcut) {
+ if (mShortcutsItemView == null) {
+ mShortcutsItemView = (ShortcutsItemView) inflater.inflate(
+ R.layout.shortcuts_item, this, false);
+ addView(mShortcutsItemView);
+ }
+ mShortcutsItemView.addShortcutView(item, itemTypeToPopulate);
+ if (shouldAddBottomMargin) {
+ ((LayoutParams) mShortcutsItemView.getLayoutParams()).bottomMargin = spacing;
+ }
+ } else {
+ addView(item);
+ if (shouldAddBottomMargin) {
+ ((LayoutParams) item.getLayoutParams()).bottomMargin = spacing;
+ }
+ }
}
// TODO: update this, since not all items are shortcuts
setContentDescription(getContext().getString(R.string.shortcuts_menu_description,
anim.setInterpolator(interpolator);
shortcutAnims.play(anim);
- Animator fadeAnim = new LauncherViewPropertyAnimator(popupItemView).alpha(1);
+ Animator fadeAnim = ObjectAnimator.ofFloat(popupItemView, View.ALPHA, 1);
fadeAnim.setInterpolator(fadeInterpolator);
// We want the shortcut to be fully opaque before the arrow starts animating.
fadeAnim.setDuration(arrowScaleDelay);
// Animate the arrow
mArrow.setScaleX(0);
mArrow.setScaleY(0);
- Animator arrowScale = new LauncherViewPropertyAnimator(mArrow).scaleX(1).scaleY(1);
+ Animator arrowScale = createArrowScaleAnim(1).setDuration(arrowScaleDuration);
arrowScale.setStartDelay(arrowScaleDelay);
- arrowScale.setDuration(arrowScaleDuration);
shortcutAnims.play(arrowScale);
mOpenCloseAnimator = shortcutAnims;
// Aligning with the shortcut icon.
int shortcutIconWidth = resources.getDimensionPixelSize(R.dimen.deep_shortcut_icon_size);
int shortcutPaddingStart = resources.getDimensionPixelSize(
- R.dimen.deep_shortcut_padding_start);
+ R.dimen.popup_padding_start);
xOffset = iconWidth / 2 - shortcutIconWidth / 2 - shortcutPaddingStart;
} else {
// Aligning with the drag handle.
int shortcutDragHandleWidth = resources.getDimensionPixelSize(
R.dimen.deep_shortcut_drag_handle_size);
int shortcutPaddingEnd = resources.getDimensionPixelSize(
- R.dimen.deep_shortcut_padding_end);
+ R.dimen.popup_padding_end);
xOffset = iconWidth / 2 - shortcutDragHandleWidth / 2 - shortcutPaddingEnd;
}
x += mIsLeftAligned ? xOffset : -xOffset;
} else {
ShapeDrawable arrowDrawable = new ShapeDrawable(TriangleShape.create(
width, height, !mIsAboveIcon));
- arrowDrawable.getPaint().setColor(Color.WHITE);
+ Paint arrowPaint = arrowDrawable.getPaint();
+ arrowPaint.setColor(Color.WHITE);
+ // The corner path effect won't be reflected in the shadow, but shouldn't be noticeable.
+ int radius = getResources().getDimensionPixelSize(R.dimen.popup_arrow_corner_radius);
+ arrowPaint.setPathEffect(new CornerPathEffect(radius));
arrowView.setBackground(arrowDrawable);
arrowView.setElevation(getElevation());
}
}
/**
- * We need to handle touch events to prevent them from falling through to the workspace below.
+ * Updates the notification header to reflect the badge info. Since this can be called
+ * for any badge info (not necessarily the one associated with this app), we first
+ * check that the ItemInfo matches the one of this popup.
*/
- @SuppressLint("ClickableViewAccessibility")
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- return true;
- }
-
- @Override
- public boolean onTouch(View v, MotionEvent ev) {
- // Touched a shortcut, update where it was touched so we can drag from there on long click.
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_MOVE:
- mIconLastTouchPos.set((int) ev.getX(), (int) ev.getY());
- break;
+ public void updateNotificationHeader(BadgeInfo badgeInfo, ItemInfo originalItemInfo) {
+ if (originalItemInfo != mOriginalIcon.getTag()) {
+ return;
}
- return false;
+ updateNotificationHeader(badgeInfo, mOriginalIcon);
}
- public boolean onLongClick(View v) {
- // Return early if this is not initiated from a touch or not the correct view
- if (!v.isInTouchMode() || !(v.getParent() instanceof DeepShortcutView)) return false;
- // Return early if global dragging is not enabled
- if (!mLauncher.isDraggingEnabled()) return false;
- // Return early if an item is already being dragged (e.g. when long-pressing two shortcuts)
- if (mLauncher.getDragController().isDragging()) return false;
-
- // Long clicked on a shortcut.
- mDeferContainerRemoval = true;
- DeepShortcutView sv = (DeepShortcutView) v.getParent();
- sv.setWillDrawIcon(false);
-
- // Move the icon to align with the center-top of the touch point
- mIconShift.x = mIconLastTouchPos.x - sv.getIconCenter().x;
- mIconShift.y = mIconLastTouchPos.y - mLauncher.getDeviceProfile().iconSizePx;
-
- DragView dv = mLauncher.getWorkspace().beginDragShared(
- sv.getBubbleText(), this, sv.getFinalInfo(),
- new ShortcutDragPreviewProvider(sv.getIconView(), mIconShift), new DragOptions());
- dv.animateShift(-mIconShift.x, -mIconShift.y);
-
- // TODO: support dragging from within folder without having to close it
- AbstractFloatingView.closeOpenContainer(mLauncher, AbstractFloatingView.TYPE_FOLDER);
- return false;
+ private void updateNotificationHeader(BadgeInfo badgeInfo, BubbleTextView originalIcon) {
+ if (mNotificationItemView != null && badgeInfo != null) {
+ IconPalette palette = originalIcon.getIcon() instanceof FastBitmapDrawable
+ ? ((FastBitmapDrawable) originalIcon.getIcon()).getIconPalette()
+ : null;
+ mNotificationItemView.updateHeader(badgeInfo.getNotificationCount(), palette);
+ }
}
public void trimNotifications(Map<PackageUserKey, BadgeInfo> updatedBadges) {
- final NotificationItemView notificationView = (NotificationItemView) findViewById(R.id.notification_view);
- if (notificationView == null) {
+ if (mNotificationItemView == null) {
return;
}
ItemInfo originalInfo = (ItemInfo) mOriginalIcon.getTag();
AnimatorSet removeNotification = LauncherAnimUtils.createAnimatorSet();
final int duration = getResources().getInteger(
R.integer.config_removeNotificationViewDuration);
- final int spacing = getResources().getDimensionPixelSize(R.dimen.deep_shortcuts_spacing);
- removeNotification.play(animateTranslationYBy(notificationView.getHeight() + spacing,
- duration));
- Animator reduceHeight = notificationView.createRemovalAnimation(duration);
+ final int spacing = getResources().getDimensionPixelSize(R.dimen.popup_items_spacing);
+ removeNotification.play(reduceNotificationViewHeight(
+ mNotificationItemView.getHeight() + spacing, duration));
final View removeMarginView = mIsAboveIcon ? getItemViewAt(getItemCount() - 2)
- : notificationView;
+ : mNotificationItemView;
if (removeMarginView != null) {
ValueAnimator removeMargin = ValueAnimator.ofFloat(1, 0).setDuration(duration);
removeMargin.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
});
removeNotification.play(removeMargin);
}
- removeNotification.play(reduceHeight);
- Animator fade = new LauncherViewPropertyAnimator(notificationView).alpha(0)
+ Animator fade = ObjectAnimator.ofFloat(mNotificationItemView, ALPHA, 0)
.setDuration(duration);
fade.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- removeView(notificationView);
+ removeView(mNotificationItemView);
+ mNotificationItemView = null;
if (getItemCount() == 0) {
close(false);
return;
}
- View firstItem = getItemViewAt(mIsAboveIcon ? getItemCount() - 1 : 0);
- mArrow.setBackgroundTintList(firstItem.getBackgroundTintList());
}
});
removeNotification.play(fade);
final long arrowScaleDuration = getResources().getInteger(
R.integer.config_deepShortcutArrowOpenDuration);
- Animator hideArrow = new LauncherViewPropertyAnimator(mArrow)
- .scaleX(0).scaleY(0).setDuration(arrowScaleDuration);
+ Animator hideArrow = createArrowScaleAnim(0).setDuration(arrowScaleDuration);
hideArrow.setStartDelay(0);
- Animator showArrow = new LauncherViewPropertyAnimator(mArrow)
- .scaleX(1).scaleY(1).setDuration(arrowScaleDuration);
+ Animator showArrow = createArrowScaleAnim(1).setDuration(arrowScaleDuration);
showArrow.setStartDelay((long) (duration - arrowScaleDuration * 1.5));
removeNotification.playSequentially(hideArrow, showArrow);
removeNotification.start();
return;
}
- notificationView.trimNotifications(badgeInfo.getNotificationKeys());
+ mNotificationItemView.trimNotifications(NotificationKeyData.extractKeysOnly(
+ badgeInfo.getNotificationKeys()));
+ }
+
+ @Override
+ protected void onWidgetsBound() {
+ enableWidgets();
+ }
+
+ public boolean enableWidgets() {
+ return mShortcutsItemView != null && mShortcutsItemView.enableWidgets(
+ (ItemInfo) mOriginalIcon.getTag());
+ }
+
+ private ObjectAnimator createArrowScaleAnim(float scale) {
+ return LauncherAnimUtils.ofPropertyValuesHolder(
+ mArrow, new PropertyListBuilder().scale(scale).build());
}
/**
- * Animates the translationY of this container if it is open above the icon.
- * If it is below the icon, the container already shifts up when the height
- * of a child (e.g. NotificationView) changes, so the translation isn't necessary.
+ * Animates the height of the notification item and the translationY of other items accordingly.
*/
- public @Nullable Animator animateTranslationYBy(int translationY, int duration) {
+ public Animator reduceNotificationViewHeight(int heightToRemove, int duration) {
+ final int translateYBy = mIsAboveIcon ? heightToRemove : -heightToRemove;
+ AnimatorSet animatorSet = LauncherAnimUtils.createAnimatorSet();
+ animatorSet.play(mNotificationItemView.animateHeightRemoval(heightToRemove));
+ PropertyResetListener<View, Float> resetTranslationYListener
+ = new PropertyResetListener<>(TRANSLATION_Y, 0f);
+ 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.
+ continue;
+ }
+ ValueAnimator translateItem = ObjectAnimator.ofFloat(itemView, TRANSLATION_Y,
+ itemView.getTranslationY() + translateYBy).setDuration(duration);
+ translateItem.addListener(resetTranslationYListener);
+ animatorSet.play(translateItem);
+ }
if (mIsAboveIcon) {
- return new LauncherViewPropertyAnimator(this)
- .translationY(getTranslationY() + translationY).setDuration(duration);
+ // All the items, including the notification item, translated down, but the
+ // container itself did not. This means the items would jump back to their
+ // original translation unless we update the container's translationY here.
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ setTranslationY(getTranslationY() + translateYBy);
+ }
+ });
}
- return null;
+ return animatorSet;
}
@Override
public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
// Either the original icon or one of the shortcuts was dragged.
// Hide the container, but don't remove it yet because that interferes with touch events.
+ mDeferContainerRemoval = true;
animateClose();
}
@Override
public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) {
target.itemType = ItemType.DEEPSHORTCUT;
- target.rank = info.rank;
targetParent.containerType = ContainerType.DEEPSHORTCUTS;
}
for (int i = firstOpenItemIndex; i < firstOpenItemIndex + numOpenShortcuts; i++) {
final PopupItemView view = getItemViewAt(i);
Animator anim;
- if (view.willDrawIcon()) {
- anim = view.createCloseAnimation(mIsAboveIcon, mIsLeftAligned, duration);
- int animationIndex = mIsAboveIcon ? i - firstOpenItemIndex
- : numOpenShortcuts - i - 1;
- anim.setStartDelay(stagger * animationIndex);
-
- Animator fadeAnim = new LauncherViewPropertyAnimator(view).alpha(0);
- // Don't start fading until the arrow is gone.
- fadeAnim.setStartDelay(stagger * animationIndex + arrowScaleDuration);
- fadeAnim.setDuration(duration - arrowScaleDuration);
- fadeAnim.setInterpolator(fadeInterpolator);
- shortcutAnims.play(fadeAnim);
- } else {
- // The view is being dragged. Animate it such that it collapses with the drag view
- anim = view.collapseToIcon();
- anim.setDuration(DragView.VIEW_ZOOM_DURATION);
-
- // Scale and translate the view to follow the drag view.
- Point iconCenter = view.getIconCenter();
- view.setPivotX(iconCenter.x);
- view.setPivotY(iconCenter.y);
-
- float scale = ((float) mLauncher.getDeviceProfile().iconSizePx) / view.getHeight();
- LauncherViewPropertyAnimator anim2 = new LauncherViewPropertyAnimator(view)
- .scaleX(scale)
- .scaleY(scale)
- .translationX(mIconShift.x)
- .translationY(mIconShift.y);
- anim2.setDuration(DragView.VIEW_ZOOM_DURATION);
- shortcutAnims.play(anim2);
- }
+ anim = view.createCloseAnimation(mIsAboveIcon, mIsLeftAligned, duration);
+ int animationIndex = mIsAboveIcon ? i - firstOpenItemIndex
+ : numOpenShortcuts - i - 1;
+ anim.setStartDelay(stagger * animationIndex);
+
+ Animator fadeAnim = ObjectAnimator.ofFloat(view, View.ALPHA, 0);
+ // Don't start fading until the arrow is gone.
+ fadeAnim.setStartDelay(stagger * animationIndex + arrowScaleDuration);
+ fadeAnim.setDuration(duration - arrowScaleDuration);
+ fadeAnim.setInterpolator(fadeInterpolator);
+ shortcutAnims.play(fadeAnim);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
});
shortcutAnims.play(anim);
}
- Animator arrowAnim = new LauncherViewPropertyAnimator(mArrow)
- .scaleX(0).scaleY(0).setDuration(arrowScaleDuration);
+ Animator arrowAnim = createArrowScaleAnim(0).setDuration(arrowScaleDuration);
arrowAnim.setStartDelay(0);
shortcutAnims.play(arrowAnim);