14c98d9235d164680186180974719f551cf935d08Winson Chung/* 24c98d9235d164680186180974719f551cf935d08Winson Chung * Copyright (C) 2011 The Android Open Source Project 34c98d9235d164680186180974719f551cf935d08Winson Chung * 44c98d9235d164680186180974719f551cf935d08Winson Chung * Licensed under the Apache License, Version 2.0 (the "License"); 54c98d9235d164680186180974719f551cf935d08Winson Chung * you may not use this file except in compliance with the License. 64c98d9235d164680186180974719f551cf935d08Winson Chung * You may obtain a copy of the License at 74c98d9235d164680186180974719f551cf935d08Winson Chung * 84c98d9235d164680186180974719f551cf935d08Winson Chung * http://www.apache.org/licenses/LICENSE-2.0 94c98d9235d164680186180974719f551cf935d08Winson Chung * 104c98d9235d164680186180974719f551cf935d08Winson Chung * Unless required by applicable law or agreed to in writing, software 114c98d9235d164680186180974719f551cf935d08Winson Chung * distributed under the License is distributed on an "AS IS" BASIS, 124c98d9235d164680186180974719f551cf935d08Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134c98d9235d164680186180974719f551cf935d08Winson Chung * See the License for the specific language governing permissions and 144c98d9235d164680186180974719f551cf935d08Winson Chung * limitations under the License. 154c98d9235d164680186180974719f551cf935d08Winson Chung */ 164c98d9235d164680186180974719f551cf935d08Winson Chung 17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3; 184c98d9235d164680186180974719f551cf935d08Winson Chung 19043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.animation.TimeInterpolator; 20043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.animation.ValueAnimator; 21043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.animation.ValueAnimator.AnimatorUpdateListener; 221e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurkaimport android.content.ComponentName; 234c98d9235d164680186180974719f551cf935d08Winson Chungimport android.content.Context; 24a62e9fd95ae10cff4676f2cc1f4d68334ca27a0bWinson Chungimport android.content.res.ColorStateList; 25201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chungimport android.content.res.Configuration; 264c98d9235d164680186180974719f551cf935d08Winson Chungimport android.content.res.Resources; 27043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.graphics.PointF; 28d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohenimport android.graphics.Rect; 29967289b6d5fec77f5c381d11ffb2319f3bb5e737Winson Chungimport android.graphics.drawable.TransitionDrawable; 304346746ef37413168a5cbec46bb6db8f96b0123aMichael Jurkaimport android.os.AsyncTask; 316a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monkimport android.os.Build; 326a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monkimport android.os.Bundle; 33950a467b180c78d3ce3bbe7b4a227a13d28b2536Jason Monkimport android.os.UserManager; 344c98d9235d164680186180974719f551cf935d08Winson Chungimport android.util.AttributeSet; 354c98d9235d164680186180974719f551cf935d08Winson Chungimport android.view.View; 36043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.view.ViewConfiguration; 37a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chungimport android.view.ViewGroup; 38043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.view.animation.AnimationUtils; 39d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohenimport android.view.animation.DecelerateInterpolator; 4061967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chungimport android.view.animation.LinearInterpolator; 414c98d9235d164680186180974719f551cf935d08Winson Chung 42ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.UserHandleCompat; 43ed13187a745866483139e2878037e1f8427ce567Kenny Guy 4461fa4197c4316bb0f9b05fcefb676f86197a2273Winson Chungpublic class DeleteDropTarget extends ButtonDropTarget { 45043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private static int DELETE_ANIMATION_DURATION = 285; 466e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung private static int FLING_DELETE_ANIMATION_DURATION = 350; 476e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung private static float FLING_TO_DELETE_FRICTION = 0.035f; 48043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private static int MODE_FLING_DELETE_TO_TRASH = 0; 49043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private static int MODE_FLING_DELETE_ALONG_VECTOR = 1; 50043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 51043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private final int mFlingDeleteMode = MODE_FLING_DELETE_ALONG_VECTOR; 524c98d9235d164680186180974719f551cf935d08Winson Chung 53a62e9fd95ae10cff4676f2cc1f4d68334ca27a0bWinson Chung private ColorStateList mOriginalTextColor; 54ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen private TransitionDrawable mUninstallDrawable; 55ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen private TransitionDrawable mRemoveDrawable; 56ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen private TransitionDrawable mCurrentDrawable; 574c98d9235d164680186180974719f551cf935d08Winson Chung 5824715c751513ea2b24058b8d1a1e5263f5c31607Michael Jurka private boolean mWaitingForUninstall = false; 5924715c751513ea2b24058b8d1a1e5263f5c31607Michael Jurka 604c98d9235d164680186180974719f551cf935d08Winson Chung public DeleteDropTarget(Context context, AttributeSet attrs) { 614c98d9235d164680186180974719f551cf935d08Winson Chung this(context, attrs, 0); 624c98d9235d164680186180974719f551cf935d08Winson Chung } 634c98d9235d164680186180974719f551cf935d08Winson Chung 644c98d9235d164680186180974719f551cf935d08Winson Chung public DeleteDropTarget(Context context, AttributeSet attrs, int defStyle) { 654c98d9235d164680186180974719f551cf935d08Winson Chung super(context, attrs, defStyle); 664c98d9235d164680186180974719f551cf935d08Winson Chung } 674c98d9235d164680186180974719f551cf935d08Winson Chung 684c98d9235d164680186180974719f551cf935d08Winson Chung @Override 694c98d9235d164680186180974719f551cf935d08Winson Chung protected void onFinishInflate() { 704c98d9235d164680186180974719f551cf935d08Winson Chung super.onFinishInflate(); 714c98d9235d164680186180974719f551cf935d08Winson Chung 724c98d9235d164680186180974719f551cf935d08Winson Chung // Get the drawable 73a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung mOriginalTextColor = getTextColors(); 744c98d9235d164680186180974719f551cf935d08Winson Chung 754c98d9235d164680186180974719f551cf935d08Winson Chung // Get the hover color 764c98d9235d164680186180974719f551cf935d08Winson Chung Resources r = getResources(); 774c98d9235d164680186180974719f551cf935d08Winson Chung mHoverColor = r.getColor(R.color.delete_target_hover_tint); 78ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen mUninstallDrawable = (TransitionDrawable) 79ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen r.getDrawable(R.drawable.uninstall_target_selector); 80ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen mRemoveDrawable = (TransitionDrawable) r.getDrawable(R.drawable.remove_target_selector); 81ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen 82ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen mRemoveDrawable.setCrossFadeEnabled(true); 83ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen mUninstallDrawable.setCrossFadeEnabled(true); 84ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen 85ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen // The current drawable is set to either the remove drawable or the uninstall drawable 86ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen // and is initially set to the remove drawable, as set in the layout xml. 87947245ba8ad74aee3dadd02693514765dbb4b5a2Winson Chung mCurrentDrawable = (TransitionDrawable) getCurrentDrawable(); 88201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung 89201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung // Remove the text in the Phone UI in landscape 90201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung int orientation = getResources().getConfiguration().orientation; 91201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung if (orientation == Configuration.ORIENTATION_LANDSCAPE) { 92e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler if (!LauncherAppState.getInstance().isScreenLarge()) { 93a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung setText(""); 94201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung } 95201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung } 964c98d9235d164680186180974719f551cf935d08Winson Chung } 974c98d9235d164680186180974719f551cf935d08Winson Chung 984c98d9235d164680186180974719f551cf935d08Winson Chung private boolean isAllAppsApplication(DragSource source, Object info) { 991eeb3fc9d874d98dfb43883d17efb4202d83d88aMathew Inwood return source.supportsAppInfoDropTarget() && (info instanceof AppInfo); 1004c98d9235d164680186180974719f551cf935d08Winson Chung } 1014c98d9235d164680186180974719f551cf935d08Winson Chung private boolean isAllAppsWidget(DragSource source, Object info) { 10211a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung if (source instanceof AppsCustomizePagedView) { 10311a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung if (info instanceof PendingAddItemInfo) { 10411a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung PendingAddItemInfo addInfo = (PendingAddItemInfo) info; 10511a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung switch (addInfo.itemType) { 10611a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: 10711a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: 10811a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung return true; 10911a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung } 11011a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung } 11111a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung } 11211a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung return false; 1134c98d9235d164680186180974719f551cf935d08Winson Chung } 1140b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka private boolean isDragSourceWorkspaceOrFolder(DragObject d) { 1150b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka return (d.dragSource instanceof Workspace) || (d.dragSource instanceof Folder); 1164c98d9235d164680186180974719f551cf935d08Winson Chung } 1170b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka private boolean isWorkspaceOrFolderApplication(DragObject d) { 1180b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof ShortcutInfo); 1190b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka } 1200b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka private boolean isWorkspaceOrFolderWidget(DragObject d) { 1210b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof LauncherAppWidgetInfo); 1224c98d9235d164680186180974719f551cf935d08Winson Chung } 1234c98d9235d164680186180974719f551cf935d08Winson Chung private boolean isWorkspaceFolder(DragObject d) { 1244c98d9235d164680186180974719f551cf935d08Winson Chung return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof FolderInfo); 1254c98d9235d164680186180974719f551cf935d08Winson Chung } 1264c98d9235d164680186180974719f551cf935d08Winson Chung 127a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung private void setHoverColor() { 128fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen if (mCurrentDrawable != null) { 129fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen mCurrentDrawable.startTransition(mTransitionDuration); 130fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen } 131a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung setTextColor(mHoverColor); 132a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 133a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung private void resetHoverColor() { 134fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen if (mCurrentDrawable != null) { 135fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen mCurrentDrawable.resetTransition(); 136fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen } 137a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung setTextColor(mOriginalTextColor); 138a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 139a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung 1404c98d9235d164680186180974719f551cf935d08Winson Chung @Override 1414c98d9235d164680186180974719f551cf935d08Winson Chung public boolean acceptDrop(DragObject d) { 1427c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen return willAcceptDrop(d.dragInfo); 1437c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen } 1447c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen 1457c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen public static boolean willAcceptDrop(Object info) { 1467c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen if (info instanceof ItemInfo) { 1477c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen ItemInfo item = (ItemInfo) info; 1487c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET || 1497c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) { 1507c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen return true; 1517c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen } 152ed3d4df1f5e9042742293e172c89b8cf273e969aMichael Jurka 15316f3ea870aac47292cd6cbe1a4b4343173097aa9Nilesh Agrawal if (!LauncherAppState.isDisableAllApps() && 1545e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka item.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) { 155ed3d4df1f5e9042742293e172c89b8cf273e969aMichael Jurka return true; 156ed3d4df1f5e9042742293e172c89b8cf273e969aMichael Jurka } 157ed3d4df1f5e9042742293e172c89b8cf273e969aMichael Jurka 15816f3ea870aac47292cd6cbe1a4b4343173097aa9Nilesh Agrawal if (!LauncherAppState.isDisableAllApps() && 1595e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION && 1605e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka item instanceof AppInfo) { 1615e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka AppInfo appInfo = (AppInfo) info; 1625e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka return (appInfo.flags & AppInfo.DOWNLOADED_FLAG) != 0; 1635e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka } 1645e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka 1659bd4d28163e3872de9c9019528cbb570f504fe05Michael Jurka if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION && 1661e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka item instanceof ShortcutInfo) { 16716f3ea870aac47292cd6cbe1a4b4343173097aa9Nilesh Agrawal if (LauncherAppState.isDisableAllApps()) { 1689bd4d28163e3872de9c9019528cbb570f504fe05Michael Jurka ShortcutInfo shortcutInfo = (ShortcutInfo) info; 1699bd4d28163e3872de9c9019528cbb570f504fe05Michael Jurka return (shortcutInfo.flags & AppInfo.DOWNLOADED_FLAG) != 0; 1709bd4d28163e3872de9c9019528cbb570f504fe05Michael Jurka } else { 1719bd4d28163e3872de9c9019528cbb570f504fe05Michael Jurka return true; 1729bd4d28163e3872de9c9019528cbb570f504fe05Michael Jurka } 1731e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } 174947dc5431981e40ffc8d687604f7777d35915034Adam Cohen } 1757c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen return false; 1764c98d9235d164680186180974719f551cf935d08Winson Chung } 1774c98d9235d164680186180974719f551cf935d08Winson Chung 1784c98d9235d164680186180974719f551cf935d08Winson Chung @Override 1794c98d9235d164680186180974719f551cf935d08Winson Chung public void onDragStart(DragSource source, Object info, int dragAction) { 1804c98d9235d164680186180974719f551cf935d08Winson Chung boolean isVisible = true; 18116f3ea870aac47292cd6cbe1a4b4343173097aa9Nilesh Agrawal boolean useUninstallLabel = !LauncherAppState.isDisableAllApps() && 182addcba65e94a11af24028b792cd1a8e02d563938Michael Jurka isAllAppsApplication(source, info); 1831eeb3fc9d874d98dfb43883d17efb4202d83d88aMathew Inwood boolean useDeleteLabel = !useUninstallLabel && source.supportsDeleteDropTarget(); 1844c98d9235d164680186180974719f551cf935d08Winson Chung 1854c98d9235d164680186180974719f551cf935d08Winson Chung // If we are dragging an application from AppsCustomize, only show the control if we can 186e01af631dc98fa3e97b01b4d3ac135cf7ca5917eWinson Chung // delete the app (it was downloaded), and rename the string to "uninstall" in such a case. 187e01af631dc98fa3e97b01b4d3ac135cf7ca5917eWinson Chung // Hide the delete target if it is a widget from AppsCustomize. 188e01af631dc98fa3e97b01b4d3ac135cf7ca5917eWinson Chung if (!willAcceptDrop(info) || isAllAppsWidget(source, info)) { 189947dc5431981e40ffc8d687604f7777d35915034Adam Cohen isVisible = false; 1904c98d9235d164680186180974719f551cf935d08Winson Chung } 191950a467b180c78d3ce3bbe7b4a227a13d28b2536Jason Monk if (useUninstallLabel) { 1926a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 1936a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk UserManager userManager = (UserManager) 1946a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk getContext().getSystemService(Context.USER_SERVICE); 1956a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk Bundle restrictions = userManager.getUserRestrictions(); 1966a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk if (restrictions.getBoolean(UserManager.DISALLOW_APPS_CONTROL, false) 1976a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk || restrictions.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS, false)) { 1986a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk isVisible = false; 1996a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk } 200950a467b180c78d3ce3bbe7b4a227a13d28b2536Jason Monk } 201950a467b180c78d3ce3bbe7b4a227a13d28b2536Jason Monk } 2024c98d9235d164680186180974719f551cf935d08Winson Chung 203addcba65e94a11af24028b792cd1a8e02d563938Michael Jurka if (useUninstallLabel) { 204d6a33c6f348d1316e0fdc519eda43468fcdcbfe7Fabrice Di Meglio setCompoundDrawablesRelativeWithIntrinsicBounds(mUninstallDrawable, null, null, null); 2051eeb3fc9d874d98dfb43883d17efb4202d83d88aMathew Inwood } else if (useDeleteLabel) { 206d6a33c6f348d1316e0fdc519eda43468fcdcbfe7Fabrice Di Meglio setCompoundDrawablesRelativeWithIntrinsicBounds(mRemoveDrawable, null, null, null); 2071eeb3fc9d874d98dfb43883d17efb4202d83d88aMathew Inwood } else { 2081eeb3fc9d874d98dfb43883d17efb4202d83d88aMathew Inwood isVisible = false; 209ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen } 210947245ba8ad74aee3dadd02693514765dbb4b5a2Winson Chung mCurrentDrawable = (TransitionDrawable) getCurrentDrawable(); 211ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen 2124c98d9235d164680186180974719f551cf935d08Winson Chung mActive = isVisible; 213a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung resetHoverColor(); 214a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung ((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE); 2151eeb3fc9d874d98dfb43883d17efb4202d83d88aMathew Inwood if (isVisible && getText().length() > 0) { 216addcba65e94a11af24028b792cd1a8e02d563938Michael Jurka setText(useUninstallLabel ? R.string.delete_target_uninstall_label 2174c98d9235d164680186180974719f551cf935d08Winson Chung : R.string.delete_target_label); 2184c98d9235d164680186180974719f551cf935d08Winson Chung } 2194c98d9235d164680186180974719f551cf935d08Winson Chung } 2204c98d9235d164680186180974719f551cf935d08Winson Chung 2214c98d9235d164680186180974719f551cf935d08Winson Chung @Override 2224c98d9235d164680186180974719f551cf935d08Winson Chung public void onDragEnd() { 2234c98d9235d164680186180974719f551cf935d08Winson Chung super.onDragEnd(); 2244c98d9235d164680186180974719f551cf935d08Winson Chung mActive = false; 2254c98d9235d164680186180974719f551cf935d08Winson Chung } 2264c98d9235d164680186180974719f551cf935d08Winson Chung 2274c98d9235d164680186180974719f551cf935d08Winson Chung public void onDragEnter(DragObject d) { 2284c98d9235d164680186180974719f551cf935d08Winson Chung super.onDragEnter(d); 2294c98d9235d164680186180974719f551cf935d08Winson Chung 230a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung setHoverColor(); 2314c98d9235d164680186180974719f551cf935d08Winson Chung } 2324c98d9235d164680186180974719f551cf935d08Winson Chung 2334c98d9235d164680186180974719f551cf935d08Winson Chung public void onDragExit(DragObject d) { 2344c98d9235d164680186180974719f551cf935d08Winson Chung super.onDragExit(d); 2354c98d9235d164680186180974719f551cf935d08Winson Chung 236aaa530adc9defb8c2b1599cae27bb268d58b2ddbWinson Chung if (!d.dragComplete) { 237a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung resetHoverColor(); 23861967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung } else { 23961967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung // Restore the hover color if we are deleting 24061967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung d.dragView.setColor(mHoverColor); 241aaa530adc9defb8c2b1599cae27bb268d58b2ddbWinson Chung } 2424c98d9235d164680186180974719f551cf935d08Winson Chung } 2434c98d9235d164680186180974719f551cf935d08Winson Chung 244ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen private void animateToTrashAndCompleteDrop(final DragObject d) { 2451e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka final DragLayer dragLayer = mLauncher.getDragLayer(); 2461e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka final Rect from = new Rect(); 247ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen dragLayer.getViewRectRelativeToSelf(d.dragView, from); 248fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen 249fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen int width = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicWidth(); 250fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen int height = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicHeight(); 2511e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(), 252fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen width, height); 2531e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka final float scale = (float) to.width() / from.width(); 254ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 255d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen mSearchDropTargetBar.deferOnDragEnd(); 2561e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka deferCompleteDropIfUninstalling(d); 2571e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka 258d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen Runnable onAnimationEndRunnable = new Runnable() { 259d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen @Override 260d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen public void run() { 2611e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka completeDrop(d); 262d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen mSearchDropTargetBar.onDragEnd(); 2638498eb40ee7b09a977251cac7e2a8df12289cbedSunny Goyal mLauncher.exitSpringLoadedDragModeDelayed(true, 0, null); 264d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen } 265d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen }; 26661967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f, 267d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen DELETE_ANIMATION_DURATION, new DecelerateInterpolator(2), 26861967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung new LinearInterpolator(), onAnimationEndRunnable, 269ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen DragLayer.ANIMATION_END_DISAPPEAR, null); 270d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen } 271d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen 2721e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka private void deferCompleteDropIfUninstalling(DragObject d) { 2731e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka mWaitingForUninstall = false; 2745e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka if (isUninstallFromWorkspace(d)) { 2751e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka if (d.dragSource instanceof Folder) { 2761e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka ((Folder) d.dragSource).deferCompleteDropAfterUninstallActivity(); 2771e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } else if (d.dragSource instanceof Workspace) { 2781e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka ((Workspace) d.dragSource).deferCompleteDropAfterUninstallActivity(); 2791e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } 2801e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka mWaitingForUninstall = true; 2811e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } 2821e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } 2831e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka 2845e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka private boolean isUninstallFromWorkspace(DragObject d) { 28516f3ea870aac47292cd6cbe1a4b4343173097aa9Nilesh Agrawal if (LauncherAppState.isDisableAllApps() && isWorkspaceOrFolderApplication(d)) { 2865e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka ShortcutInfo shortcut = (ShortcutInfo) d.dragInfo; 287dff0bfeb901e767ca9b57f9b8051c7fd077626e9Nilesh Agrawal // Only allow manifest shortcuts to initiate an un-install. 288dff0bfeb901e767ca9b57f9b8051c7fd077626e9Nilesh Agrawal return !InstallShortcutReceiver.isValidShortcutLaunchIntent(shortcut.intent); 2895e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka } 2905e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka return false; 2911e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } 2924c98d9235d164680186180974719f551cf935d08Winson Chung 293f3007589e346df224d357b389069adfeb266545eMichael Jurka private void completeDrop(DragObject d) { 2941e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka ItemInfo item = (ItemInfo) d.dragInfo; 2951e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka boolean wasWaitingForUninstall = mWaitingForUninstall; 2961e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka mWaitingForUninstall = false; 2974c98d9235d164680186180974719f551cf935d08Winson Chung if (isAllAppsApplication(d.dragSource, item)) { 2984c98d9235d164680186180974719f551cf935d08Winson Chung // Uninstall the application if it is being dragged from AppsCustomize 299eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka AppInfo appInfo = (AppInfo) item; 300d31df54073fbd80a9db9d277dde8c0e7421ffa14Kenny Guy mLauncher.startApplicationUninstallActivity(appInfo.componentName, appInfo.flags, 301d31df54073fbd80a9db9d277dde8c0e7421ffa14Kenny Guy appInfo.user); 3025e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka } else if (isUninstallFromWorkspace(d)) { 3031e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka ShortcutInfo shortcut = (ShortcutInfo) item; 304d31df54073fbd80a9db9d277dde8c0e7421ffa14Kenny Guy if (shortcut.intent != null && shortcut.intent.getComponent() != null) { 305f3007589e346df224d357b389069adfeb266545eMichael Jurka final ComponentName componentName = shortcut.intent.getComponent(); 306f3007589e346df224d357b389069adfeb266545eMichael Jurka final DragSource dragSource = d.dragSource; 307d31df54073fbd80a9db9d277dde8c0e7421ffa14Kenny Guy final UserHandleCompat user = shortcut.user; 308d31df54073fbd80a9db9d277dde8c0e7421ffa14Kenny Guy mWaitingForUninstall = mLauncher.startApplicationUninstallActivity( 309d31df54073fbd80a9db9d277dde8c0e7421ffa14Kenny Guy componentName, shortcut.flags, user); 310f3007589e346df224d357b389069adfeb266545eMichael Jurka if (mWaitingForUninstall) { 311f3007589e346df224d357b389069adfeb266545eMichael Jurka final Runnable checkIfUninstallWasSuccess = new Runnable() { 312f3007589e346df224d357b389069adfeb266545eMichael Jurka @Override 313f3007589e346df224d357b389069adfeb266545eMichael Jurka public void run() { 314f3007589e346df224d357b389069adfeb266545eMichael Jurka mWaitingForUninstall = false; 315f3007589e346df224d357b389069adfeb266545eMichael Jurka String packageName = componentName.getPackageName(); 316ed13187a745866483139e2878037e1f8427ce567Kenny Guy boolean uninstallSuccessful = !AllAppsList.packageHasActivities( 317d31df54073fbd80a9db9d277dde8c0e7421ffa14Kenny Guy getContext(), packageName, user); 318f3007589e346df224d357b389069adfeb266545eMichael Jurka if (dragSource instanceof Folder) { 319f3007589e346df224d357b389069adfeb266545eMichael Jurka ((Folder) dragSource). 320f3007589e346df224d357b389069adfeb266545eMichael Jurka onUninstallActivityReturned(uninstallSuccessful); 321f3007589e346df224d357b389069adfeb266545eMichael Jurka } else if (dragSource instanceof Workspace) { 322f3007589e346df224d357b389069adfeb266545eMichael Jurka ((Workspace) dragSource). 323f3007589e346df224d357b389069adfeb266545eMichael Jurka onUninstallActivityReturned(uninstallSuccessful); 324f3007589e346df224d357b389069adfeb266545eMichael Jurka } 325f3007589e346df224d357b389069adfeb266545eMichael Jurka } 326f3007589e346df224d357b389069adfeb266545eMichael Jurka }; 327f3007589e346df224d357b389069adfeb266545eMichael Jurka mLauncher.addOnResumeCallback(checkIfUninstallWasSuccess); 328f3007589e346df224d357b389069adfeb266545eMichael Jurka } 3291e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } 3300b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka } else if (isWorkspaceOrFolderApplication(d)) { 3314c98d9235d164680186180974719f551cf935d08Winson Chung LauncherModel.deleteItemFromDatabase(mLauncher, item); 3324c98d9235d164680186180974719f551cf935d08Winson Chung } else if (isWorkspaceFolder(d)) { 3334c98d9235d164680186180974719f551cf935d08Winson Chung // Remove the folder from the workspace and delete the contents from launcher model 3344c98d9235d164680186180974719f551cf935d08Winson Chung FolderInfo folderInfo = (FolderInfo) item; 3354c98d9235d164680186180974719f551cf935d08Winson Chung mLauncher.removeFolder(folderInfo); 3364c98d9235d164680186180974719f551cf935d08Winson Chung LauncherModel.deleteFolderContentsFromDatabase(mLauncher, folderInfo); 3370b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka } else if (isWorkspaceOrFolderWidget(d)) { 3384c98d9235d164680186180974719f551cf935d08Winson Chung // Remove the widget from the workspace 3394c98d9235d164680186180974719f551cf935d08Winson Chung mLauncher.removeAppWidget((LauncherAppWidgetInfo) item); 3404c98d9235d164680186180974719f551cf935d08Winson Chung LauncherModel.deleteItemFromDatabase(mLauncher, item); 3414c98d9235d164680186180974719f551cf935d08Winson Chung 3424c98d9235d164680186180974719f551cf935d08Winson Chung final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item; 3434c98d9235d164680186180974719f551cf935d08Winson Chung final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost(); 344651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal if ((appWidgetHost != null) && launcherAppWidgetInfo.isWidgetIdValid()) { 3454c98d9235d164680186180974719f551cf935d08Winson Chung // Deleting an app widget ID is a void call but writes to disk before returning 3464c98d9235d164680186180974719f551cf935d08Winson Chung // to the caller... 3474346746ef37413168a5cbec46bb6db8f96b0123aMichael Jurka new AsyncTask<Void, Void, Void>() { 3484346746ef37413168a5cbec46bb6db8f96b0123aMichael Jurka public Void doInBackground(Void ... args) { 3494c98d9235d164680186180974719f551cf935d08Winson Chung appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId); 3504346746ef37413168a5cbec46bb6db8f96b0123aMichael Jurka return null; 3514c98d9235d164680186180974719f551cf935d08Winson Chung } 3524346746ef37413168a5cbec46bb6db8f96b0123aMichael Jurka }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); 3534c98d9235d164680186180974719f551cf935d08Winson Chung } 3544c98d9235d164680186180974719f551cf935d08Winson Chung } 3551e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka if (wasWaitingForUninstall && !mWaitingForUninstall) { 3561e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka if (d.dragSource instanceof Folder) { 3571e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka ((Folder) d.dragSource).onUninstallActivityReturned(false); 3581e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } else if (d.dragSource instanceof Workspace) { 3591e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka ((Workspace) d.dragSource).onUninstallActivityReturned(false); 3601e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } 3611e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } 3624c98d9235d164680186180974719f551cf935d08Winson Chung } 363d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen 364d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen public void onDrop(DragObject d) { 365d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen animateToTrashAndCompleteDrop(d); 366d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen } 367043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 368043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung /** 369043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung * Creates an animation from the current drag view to the delete trash icon. 370043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung */ 371043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private AnimatorUpdateListener createFlingToTrashAnimatorListener(final DragLayer dragLayer, 372043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung DragObject d, PointF vel, ViewConfiguration config) { 373fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen 374fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen int width = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicWidth(); 375fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen int height = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicHeight(); 376043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(), 377fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen width, height); 378043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final Rect from = new Rect(); 379043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragLayer.getViewRectRelativeToSelf(d.dragView, from); 380043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 381043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Calculate how far along the velocity vector we should put the intermediate point on 382043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // the bezier curve 383043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float velocity = Math.abs(vel.length()); 384043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float vp = Math.min(1f, velocity / (config.getScaledMaximumFlingVelocity() / 2f)); 385043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung int offsetY = (int) (-from.top * vp); 386043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung int offsetX = (int) (offsetY / (vel.y / vel.x)); 387043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final float y2 = from.top + offsetY; // intermediate t/l 388043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final float x2 = from.left + offsetX; 389043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final float x1 = from.left; // drag view t/l 390043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final float y1 = from.top; 391043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final float x3 = to.left; // delete target t/l 392043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final float y3 = to.top; 393043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 394043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final TimeInterpolator scaleAlphaInterpolator = new TimeInterpolator() { 395043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung @Override 396043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public float getInterpolation(float t) { 397043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung return t * t * t * t * t * t * t * t; 398043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 399043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung }; 400043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung return new AnimatorUpdateListener() { 401043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung @Override 402043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public void onAnimationUpdate(ValueAnimator animation) { 403043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final DragView dragView = (DragView) dragLayer.getAnimatedView(); 404043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float t = ((Float) animation.getAnimatedValue()).floatValue(); 405043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float tp = scaleAlphaInterpolator.getInterpolation(t); 406043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float initialScale = dragView.getInitialScale(); 407043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float finalAlpha = 0.5f; 408043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float scale = dragView.getScaleX(); 409043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float x1o = ((1f - scale) * dragView.getMeasuredWidth()) / 2f; 410043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float y1o = ((1f - scale) * dragView.getMeasuredHeight()) / 2f; 411043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float x = (1f - t) * (1f - t) * (x1 - x1o) + 2 * (1f - t) * t * (x2 - x1o) + 412043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung (t * t) * x3; 413043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float y = (1f - t) * (1f - t) * (y1 - y1o) + 2 * (1f - t) * t * (y2 - x1o) + 414043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung (t * t) * y3; 415043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 416043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setTranslationX(x); 417043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setTranslationY(y); 418043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setScaleX(initialScale * (1f - tp)); 419043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setScaleY(initialScale * (1f - tp)); 420043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setAlpha(finalAlpha + (1f - finalAlpha) * (1f - tp)); 421043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 422043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung }; 423043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 424043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 425043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung /** 426043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung * Creates an animation from the current drag view along its current velocity vector. 427043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung * For this animation, the alpha runs for a fixed duration and we update the position 428043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung * progressively. 429043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung */ 430043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private static class FlingAlongVectorAnimatorUpdateListener implements AnimatorUpdateListener { 431043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private DragLayer mDragLayer; 432043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private PointF mVelocity; 433043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private Rect mFrom; 434043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private long mPrevTime; 435043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private boolean mHasOffsetForScale; 4366e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung private float mFriction; 437043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 4389658b1e65932f0149a596f451e0bd966e7ee4e74Winson Chung private final TimeInterpolator mAlphaInterpolator = new DecelerateInterpolator(0.75f); 439043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 440043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public FlingAlongVectorAnimatorUpdateListener(DragLayer dragLayer, PointF vel, Rect from, 4416e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung long startTime, float friction) { 442043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDragLayer = dragLayer; 443043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mVelocity = vel; 444043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFrom = from; 445043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mPrevTime = startTime; 4466e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung mFriction = 1f - (dragLayer.getResources().getDisplayMetrics().density * friction); 447043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 448043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 449043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung @Override 450043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public void onAnimationUpdate(ValueAnimator animation) { 451043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final DragView dragView = (DragView) mDragLayer.getAnimatedView(); 452043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float t = ((Float) animation.getAnimatedValue()).floatValue(); 453043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung long curTime = AnimationUtils.currentAnimationTimeMillis(); 454043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 455043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (!mHasOffsetForScale) { 456043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mHasOffsetForScale = true; 457043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float scale = dragView.getScaleX(); 458043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float xOffset = ((scale - 1f) * dragView.getMeasuredWidth()) / 2f; 459043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float yOffset = ((scale - 1f) * dragView.getMeasuredHeight()) / 2f; 460043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 461043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFrom.left += xOffset; 462043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFrom.top += yOffset; 463043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 464043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 465043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFrom.left += (mVelocity.x * (curTime - mPrevTime) / 1000f); 466043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFrom.top += (mVelocity.y * (curTime - mPrevTime) / 1000f); 467043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 468043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setTranslationX(mFrom.left); 469043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setTranslationY(mFrom.top); 470043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setAlpha(1f - mAlphaInterpolator.getInterpolation(t)); 471043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 4726e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung mVelocity.x *= mFriction; 4736e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung mVelocity.y *= mFriction; 474043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mPrevTime = curTime; 475043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 476043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung }; 477043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private AnimatorUpdateListener createFlingAlongVectorAnimatorListener(final DragLayer dragLayer, 478043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung DragObject d, PointF vel, final long startTime, final int duration, 479043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung ViewConfiguration config) { 480043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final Rect from = new Rect(); 481043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragLayer.getViewRectRelativeToSelf(d.dragView, from); 482043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 4836e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung return new FlingAlongVectorAnimatorUpdateListener(dragLayer, vel, from, startTime, 4846e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung FLING_TO_DELETE_FRICTION); 485043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 486043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 487043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public void onFlingToDelete(final DragObject d, int x, int y, PointF vel) { 488a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung final boolean isAllApps = d.dragSource instanceof AppsCustomizePagedView; 489a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung 490043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Don't highlight the icon as it's animating 491043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung d.dragView.setColor(0); 492043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung d.dragView.updateInitialScaleToCurrentScale(); 493a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung // Don't highlight the target if we are flinging from AllApps 494a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung if (isAllApps) { 495a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung resetHoverColor(); 496a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 497043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 498043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mFlingDeleteMode == MODE_FLING_DELETE_TO_TRASH) { 499043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Defer animating out the drop target if we are animating to it 500043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mSearchDropTargetBar.deferOnDragEnd(); 501043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mSearchDropTargetBar.finishAnimations(); 502043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 503043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 504043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final ViewConfiguration config = ViewConfiguration.get(mLauncher); 505043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final DragLayer dragLayer = mLauncher.getDragLayer(); 5066e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung final int duration = FLING_DELETE_ANIMATION_DURATION; 507043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final long startTime = AnimationUtils.currentAnimationTimeMillis(); 508043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 509043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // NOTE: Because it takes time for the first frame of animation to actually be 510043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // called and we expect the animation to be a continuation of the fling, we have 511043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // to account for the time that has elapsed since the fling finished. And since 512043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // we don't have a startDelay, we will always get call to update when we call 513043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // start() (which we want to ignore). 514043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final TimeInterpolator tInterpolator = new TimeInterpolator() { 515043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private int mCount = -1; 516043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private float mOffset = 0f; 517043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 518043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung @Override 519043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public float getInterpolation(float t) { 520043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mCount < 0) { 521043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mCount++; 522043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } else if (mCount == 0) { 523043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mOffset = Math.min(0.5f, (float) (AnimationUtils.currentAnimationTimeMillis() - 524043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung startTime) / duration); 525043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mCount++; 526043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 527043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung return Math.min(1f, mOffset + t); 528043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 529043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung }; 530043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung AnimatorUpdateListener updateCb = null; 531043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mFlingDeleteMode == MODE_FLING_DELETE_TO_TRASH) { 532043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung updateCb = createFlingToTrashAnimatorListener(dragLayer, d, vel, config); 533043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } else if (mFlingDeleteMode == MODE_FLING_DELETE_ALONG_VECTOR) { 534043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung updateCb = createFlingAlongVectorAnimatorListener(dragLayer, d, vel, startTime, 535043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung duration, config); 536043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 5371e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka deferCompleteDropIfUninstalling(d); 5381e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka 539043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung Runnable onAnimationEndRunnable = new Runnable() { 540043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung @Override 541043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public void run() { 542a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung // If we are dragging from AllApps, then we allow AppsCustomizePagedView to clean up 543a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung // itself, otherwise, complete the drop to initiate the deletion process 544a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung if (!isAllApps) { 545a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung mLauncher.exitSpringLoadedDragMode(); 546a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung completeDrop(d); 547a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 548a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung mLauncher.getDragController().onDeferredEndFling(d); 549043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 550043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung }; 551043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragLayer.animateView(d.dragView, updateCb, duration, tInterpolator, onAnimationEndRunnable, 552043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung DragLayer.ANIMATION_END_DISAPPEAR, null); 553043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 5544c98d9235d164680186180974719f551cf935d08Winson Chung} 555