131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/* 231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License. 631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at 731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and 1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License. 1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3; 1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 192801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohenimport android.animation.Animator; 202801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohenimport android.animation.AnimatorListenerAdapter; 212801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohenimport android.animation.ValueAnimator; 222801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohenimport android.animation.ValueAnimator.AnimatorUpdateListener; 2331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context; 2431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.res.Resources; 25a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohenimport android.graphics.Canvas; 26f4b08913677e18a8412930972237b91d5a946d95Adam Cohenimport android.graphics.Color; 27badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohenimport android.graphics.PorterDuff; 283e8f811f31a2275e778244427271f77f4116c08bAdam Cohenimport android.graphics.Rect; 2931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.drawable.Drawable; 3024ad0f0aad174b077e80b10d1f814ff9e9eb92e4Daniel Sandlerimport android.os.Looper; 31099f60d51f6310e1290687e83958e665b3324504Adam Cohenimport android.os.Parcelable; 3231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet; 3331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.LayoutInflater; 3488f334571fe41df620ba903ced9b2c69b0170d5cWinson Chungimport android.view.MotionEvent; 357c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohenimport android.view.View; 3602dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monkimport android.view.ViewConfiguration; 3731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.ViewGroup; 383e8f811f31a2275e778244427271f77f4116c08bAdam Cohenimport android.view.animation.AccelerateInterpolator; 393e8f811f31a2275e778244427271f77f4116c08bAdam Cohenimport android.view.animation.DecelerateInterpolator; 406e1c0d34bb31cacc24c57c89ab01deaa8985814fWinson Chungimport android.widget.FrameLayout; 4134c2e6cf7af328aba25c98158161dbad15ae986dMichael Jurkaimport android.widget.ImageView; 42a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohenimport android.widget.TextView; 4331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 44325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerimport com.android.launcher3.DropTarget.DragObject; 45325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerimport com.android.launcher3.FolderInfo.FolderListener; 46edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy 47c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohenimport java.util.ArrayList; 48c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen 4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/** 5031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * An icon that can appear on in the workspace representing an {@link UserFolder}. 5131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 526e1c0d34bb31cacc24c57c89ab01deaa8985814fWinson Chungpublic class FolderIcon extends FrameLayout implements FolderListener { 5331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private Launcher mLauncher; 54fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen private Folder mFolder; 55fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen private FolderInfo mInfo; 56099f60d51f6310e1290687e83958e665b3324504Adam Cohen private static boolean sStaticValuesDirty = true; 57a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 5888f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung private CheckLongPressHelper mLongPressHelper; 5988f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung 60badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen // The number of icons to display in the 6176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private static final int NUM_ITEMS_IN_PREVIEW = 3; 62f4b08913677e18a8412930972237b91d5a946d95Adam Cohen private static final int CONSUMPTION_ANIMATION_DURATION = 100; 63d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private static final int DROP_IN_ANIMATION_DURATION = 400; 648dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen private static final int INITIAL_ITEM_ANIMATION_DURATION = 350; 65fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen private static final int FINAL_ITEM_ANIMATION_DURATION = 200; 66badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen 67badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen // The degree to which the inner ring grows when accepting drop 6869ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen private static final float INNER_RING_GROWTH_FACTOR = 0.15f; 69badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen 70badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen // The degree to which the outer ring is scaled in its natural state 7169ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen private static final float OUTER_RING_GROWTH_FACTOR = 0.3f; 72badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen 73badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen // The amount of vertical spread between items in the stack [0...1] 7496bb79819ef9ddf2d1c0cb0b72c2c9f6db26b4fdAdam Cohen private static final float PERSPECTIVE_SHIFT_FACTOR = 0.18f; 758edd2001417443c34a930be79b8ee8438dcff246Adam Cohen 765108bc0fd9f7e30c87c223fbb75f024e271b2103Adam Cohen // Flag as to whether or not to draw an outer ring. Currently none is designed. 77b0e65f218ec7eb69fd527e5400f7c040742a1767Adam Cohen public static final boolean HAS_OUTER_RING = true; 785108bc0fd9f7e30c87c223fbb75f024e271b2103Adam Cohen 7955bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi // Flag whether the folder should open itself when an item is dragged over is enabled. 8055bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi public static final boolean SPRING_LOADING_ENABLED = true; 8155bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi 82badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen // The degree to which the item in the back of the stack is scaled [0...1] 83badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen // (0 means it's not scaled at all, 1 means it's scaled to nothing) 8476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private static final float PERSPECTIVE_SCALE_FACTOR = 0.35f; 8531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 8655bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi // Delay when drag enters until the folder opens, in miliseconds. 8755bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi private static final int ON_OPEN_DELAY = 800; 8855bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi 89c51934bfdfed6a5011c6d6c5b7b70f2d75613d41Adam Cohen public static Drawable sSharedFolderLeaveBehind = null; 90c51934bfdfed6a5011c6d6c5b7b70f2d75613d41Adam Cohen 9176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private ImageView mPreviewBackground; 9276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private BubbleTextView mFolderName; 93073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen 9419072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen FolderRingAnimator mFolderRingAnimator = null; 952801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 96d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen // These variables are all associated with the drawing of the preview; they are stored 97d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen // as member variables for shared usage and to avoid computation on each frame 98d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private int mIntrinsicIconSize; 99d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private float mBaselineIconScale; 100d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private int mBaselineIconSize; 101d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private int mAvailableSpaceInPreview; 102d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private int mTotalWidth = -1; 103d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private int mPreviewOffsetX; 104d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private int mPreviewOffsetY; 105d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private float mMaxPerspectiveShift; 106d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen boolean mAnimating = false; 107d4e53c882494f8cd7e4c0d44dbfc300d3610afcfWinson Chung private Rect mOldBounds = new Rect(); 108fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen 10902dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk private float mSlop; 11002dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk 111d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private PreviewItemDrawingParams mParams = new PreviewItemDrawingParams(0, 0, 0, 0); 112d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private PreviewItemDrawingParams mAnimParams = new PreviewItemDrawingParams(0, 0, 0, 0); 113fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen private ArrayList<ShortcutInfo> mHiddenItems = new ArrayList<ShortcutInfo>(); 114d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 11555bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi private Alarm mOpenAlarm = new Alarm(); 11655bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi private ItemInfo mDragInfo; 11755bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi 11831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public FolderIcon(Context context, AttributeSet attrs) { 11931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super(context, attrs); 12088f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung init(); 12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 12231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public FolderIcon(Context context) { 12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super(context); 12588f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung init(); 12688f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung } 12788f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung 12888f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung private void init() { 12988f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung mLongPressHelper = new CheckLongPressHelper(this); 13031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 1320280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka public boolean isDropEnabled() { 1337a1d16555d80135e61b90158ff3c1e3f963bd8b8Winson Chung final ViewGroup cellLayoutChildren = (ViewGroup) getParent(); 1347a1d16555d80135e61b90158ff3c1e3f963bd8b8Winson Chung final ViewGroup cellLayout = (ViewGroup) cellLayoutChildren.getParent(); 1357a1d16555d80135e61b90158ff3c1e3f963bd8b8Winson Chung final Workspace workspace = (Workspace) cellLayout.getParent(); 1366c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen return !workspace.workspaceInModalState(); 1370280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka } 1380280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka 13931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group, 140df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen FolderInfo folderInfo, IconCache iconCache) { 1413a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka @SuppressWarnings("all") // suppress dead code warning 1423a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka final boolean error = INITIAL_ITEM_ANIMATION_DURATION >= DROP_IN_ANIMATION_DURATION; 1433a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka if (error) { 144d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen throw new IllegalStateException("DROP_IN_ANIMATION_DURATION must be greater than " + 145d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen "INITIAL_ITEM_ANIMATION_DURATION, as sequencing of adding first two items " + 146d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen "is dependent on this"); 147d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 1486e1c0d34bb31cacc24c57c89ab01deaa8985814fWinson Chung LauncherAppState app = LauncherAppState.getInstance(); 1496e1c0d34bb31cacc24c57c89ab01deaa8985814fWinson Chung DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); 150d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 15131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false); 1525f8afe6280eae34620067696173e71943e1a30a3Winson Chung icon.setClipToPadding(false); 153d2eca6b66e654e71fb46ae718910af3ec6c2cf9cAdam Cohen icon.mFolderName = (BubbleTextView) icon.findViewById(R.id.folder_icon_name); 15476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen icon.mFolderName.setText(folderInfo.title); 1556e1c0d34bb31cacc24c57c89ab01deaa8985814fWinson Chung icon.mFolderName.setCompoundDrawablePadding(0); 1566e1c0d34bb31cacc24c57c89ab01deaa8985814fWinson Chung FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) icon.mFolderName.getLayoutParams(); 1576e1c0d34bb31cacc24c57c89ab01deaa8985814fWinson Chung lp.topMargin = grid.iconSizePx + grid.iconDrawablePaddingPx; 1586e1c0d34bb31cacc24c57c89ab01deaa8985814fWinson Chung 1595f8afe6280eae34620067696173e71943e1a30a3Winson Chung // Offset the preview background to center this view accordingly 1606e1c0d34bb31cacc24c57c89ab01deaa8985814fWinson Chung icon.mPreviewBackground = (ImageView) icon.findViewById(R.id.preview_background); 1616e1c0d34bb31cacc24c57c89ab01deaa8985814fWinson Chung lp = (FrameLayout.LayoutParams) icon.mPreviewBackground.getLayoutParams(); 1625f8afe6280eae34620067696173e71943e1a30a3Winson Chung lp.topMargin = grid.folderBackgroundOffset; 1635f8afe6280eae34620067696173e71943e1a30a3Winson Chung lp.width = grid.folderIconSizePx; 1645f8afe6280eae34620067696173e71943e1a30a3Winson Chung lp.height = grid.folderIconSizePx; 16576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 16631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project icon.setTag(folderInfo); 16731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project icon.setOnClickListener(launcher); 16831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project icon.mInfo = folderInfo; 16931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project icon.mLauncher = launcher; 1703371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen icon.setContentDescription(String.format(launcher.getString(R.string.folder_name_format), 1713371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen folderInfo.title)); 172a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen Folder folder = Folder.fromXml(launcher); 173a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen folder.setDragController(launcher.getDragController()); 1742801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen folder.setFolderIcon(icon); 175a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen folder.bind(folderInfo); 176a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen icon.mFolder = folder; 177099f60d51f6310e1290687e83958e665b3324504Adam Cohen 178099f60d51f6310e1290687e83958e665b3324504Adam Cohen icon.mFolderRingAnimator = new FolderRingAnimator(launcher, icon); 179099f60d51f6310e1290687e83958e665b3324504Adam Cohen folderInfo.addListener(icon); 180099f60d51f6310e1290687e83958e665b3324504Adam Cohen 181dcbcc86353e9ed52daac87f292aece667cd0ac71Sunny Goyal icon.setOnFocusChangeListener(launcher.mFocusHandler); 18219072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen return icon; 18319072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen } 18419072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen 185099f60d51f6310e1290687e83958e665b3324504Adam Cohen @Override 186099f60d51f6310e1290687e83958e665b3324504Adam Cohen protected Parcelable onSaveInstanceState() { 187099f60d51f6310e1290687e83958e665b3324504Adam Cohen sStaticValuesDirty = true; 188099f60d51f6310e1290687e83958e665b3324504Adam Cohen return super.onSaveInstanceState(); 189099f60d51f6310e1290687e83958e665b3324504Adam Cohen } 190099f60d51f6310e1290687e83958e665b3324504Adam Cohen 19119072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen public static class FolderRingAnimator { 19269ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen public int mCellX; 19369ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen public int mCellY; 19469ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen private CellLayout mCellLayout; 19576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public float mOuterRingSize; 19676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public float mInnerRingSize; 19719072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen public FolderIcon mFolderIcon = null; 198c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen public static Drawable sSharedOuterRingDrawable = null; 199c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen public static Drawable sSharedInnerRingDrawable = null; 20076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public static int sPreviewSize = -1; 20176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public static int sPreviewPadding = -1; 20276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 203c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen private ValueAnimator mAcceptAnimator; 204c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen private ValueAnimator mNeutralAnimator; 20519072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen 20619072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen public FolderRingAnimator(Launcher launcher, FolderIcon folderIcon) { 20719072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen mFolderIcon = folderIcon; 20876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen Resources res = launcher.getResources(); 20976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 210099f60d51f6310e1290687e83958e665b3324504Adam Cohen // We need to reload the static values when configuration changes in case they are 211099f60d51f6310e1290687e83958e665b3324504Adam Cohen // different in another configuration 212099f60d51f6310e1290687e83958e665b3324504Adam Cohen if (sStaticValuesDirty) { 21324ad0f0aad174b077e80b10d1f814ff9e9eb92e4Daniel Sandler if (Looper.myLooper() != Looper.getMainLooper()) { 21424ad0f0aad174b077e80b10d1f814ff9e9eb92e4Daniel Sandler throw new RuntimeException("FolderRingAnimator loading drawables on non-UI thread " 21524ad0f0aad174b077e80b10d1f814ff9e9eb92e4Daniel Sandler + Thread.currentThread()); 21624ad0f0aad174b077e80b10d1f814ff9e9eb92e4Daniel Sandler } 2175f8afe6280eae34620067696173e71943e1a30a3Winson Chung 2185f8afe6280eae34620067696173e71943e1a30a3Winson Chung LauncherAppState app = LauncherAppState.getInstance(); 2195f8afe6280eae34620067696173e71943e1a30a3Winson Chung DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); 2205f8afe6280eae34620067696173e71943e1a30a3Winson Chung sPreviewSize = grid.folderIconSizePx; 22176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen sPreviewPadding = res.getDimensionPixelSize(R.dimen.folder_preview_padding); 22276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen sSharedOuterRingDrawable = res.getDrawable(R.drawable.portal_ring_outer_holo); 2235108bc0fd9f7e30c87c223fbb75f024e271b2103Adam Cohen sSharedInnerRingDrawable = res.getDrawable(R.drawable.portal_ring_inner_nolip_holo); 224df6af5740da6ee9f78e846218d71941b02fc0283Adam Cohen sSharedFolderLeaveBehind = res.getDrawable(R.drawable.portal_ring_rest); 225099f60d51f6310e1290687e83958e665b3324504Adam Cohen sStaticValuesDirty = false; 22619072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen } 227073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen } 228a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 22919072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen public void animateToAcceptState() { 230c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen if (mNeutralAnimator != null) { 231c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen mNeutralAnimator.cancel(); 232c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen } 233f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka mAcceptAnimator = LauncherAnimUtils.ofFloat(mCellLayout, 0f, 1f); 234c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen mAcceptAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION); 235850d2e718560cb12ae73292e9d39f21a93d3c2c1Andrew Flynn 236850d2e718560cb12ae73292e9d39f21a93d3c2c1Andrew Flynn final int previewSize = sPreviewSize; 237c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen mAcceptAnimator.addUpdateListener(new AnimatorUpdateListener() { 23819072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen public void onAnimationUpdate(ValueAnimator animation) { 23919072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen final float percent = (Float) animation.getAnimatedValue(); 240850d2e718560cb12ae73292e9d39f21a93d3c2c1Andrew Flynn mOuterRingSize = (1 + percent * OUTER_RING_GROWTH_FACTOR) * previewSize; 241850d2e718560cb12ae73292e9d39f21a93d3c2c1Andrew Flynn mInnerRingSize = (1 + percent * INNER_RING_GROWTH_FACTOR) * previewSize; 24269ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen if (mCellLayout != null) { 24369ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen mCellLayout.invalidate(); 24419072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen } 24519072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen } 24619072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen }); 247c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen mAcceptAnimator.addListener(new AnimatorListenerAdapter() { 24819072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen @Override 249c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen public void onAnimationStart(Animator animation) { 25019072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen if (mFolderIcon != null) { 25176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mFolderIcon.mPreviewBackground.setVisibility(INVISIBLE); 25219072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen } 25319072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen } 25419072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen }); 255c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen mAcceptAnimator.start(); 25619072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen } 25719072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen 25819072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen public void animateToNaturalState() { 259c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen if (mAcceptAnimator != null) { 260c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen mAcceptAnimator.cancel(); 261c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen } 262f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka mNeutralAnimator = LauncherAnimUtils.ofFloat(mCellLayout, 0f, 1f); 263c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen mNeutralAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION); 264850d2e718560cb12ae73292e9d39f21a93d3c2c1Andrew Flynn 265850d2e718560cb12ae73292e9d39f21a93d3c2c1Andrew Flynn final int previewSize = sPreviewSize; 266c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen mNeutralAnimator.addUpdateListener(new AnimatorUpdateListener() { 26719072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen public void onAnimationUpdate(ValueAnimator animation) { 26819072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen final float percent = (Float) animation.getAnimatedValue(); 269850d2e718560cb12ae73292e9d39f21a93d3c2c1Andrew Flynn mOuterRingSize = (1 + (1 - percent) * OUTER_RING_GROWTH_FACTOR) * previewSize; 270850d2e718560cb12ae73292e9d39f21a93d3c2c1Andrew Flynn mInnerRingSize = (1 + (1 - percent) * INNER_RING_GROWTH_FACTOR) * previewSize; 27169ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen if (mCellLayout != null) { 27269ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen mCellLayout.invalidate(); 27319072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen } 27419072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen } 27519072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen }); 276c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen mNeutralAnimator.addListener(new AnimatorListenerAdapter() { 27719072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen @Override 27819072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen public void onAnimationEnd(Animator animation) { 27969ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen if (mCellLayout != null) { 28069ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen mCellLayout.hideFolderAccept(FolderRingAnimator.this); 28169ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen } 28219072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen if (mFolderIcon != null) { 28376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mFolderIcon.mPreviewBackground.setVisibility(VISIBLE); 28419072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen } 28519072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen } 28619072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen }); 287c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen mNeutralAnimator.start(); 28819072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen } 28919072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen 290c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen // Location is expressed in window coordinates 29169ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen public void getCell(int[] loc) { 29269ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen loc[0] = mCellX; 29369ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen loc[1] = mCellY; 29469ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen } 29569ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen 29669ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen // Location is expressed in window coordinates 29769ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen public void setCell(int x, int y) { 29869ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen mCellX = x; 29969ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen mCellY = y; 30069ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen } 30169ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen 30269ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen public void setCellLayout(CellLayout layout) { 30369ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen mCellLayout = layout; 30419072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen } 30519072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen 30676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public float getOuterRingSize() { 30776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return mOuterRingSize; 30819072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen } 30919072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen 31076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public float getInnerRingSize() { 31176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return mInnerRingSize; 312f4b08913677e18a8412930972237b91d5a946d95Adam Cohen } 31331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 31431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 315f05545fcc2df05518731f8d7ff048d797fe776d5Anjali Koppal public Folder getFolder() { 316fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen return mFolder; 317fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 318fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen 319fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen FolderInfo getFolderInfo() { 320fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen return mInfo; 321fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 322fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen 323073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen private boolean willAcceptItem(ItemInfo item) { 32431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int itemType = item.itemType; 3252801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION || 3262801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) && 327c51934bfdfed6a5011c6d6c5b7b70f2d75613d41Adam Cohen !mFolder.isFull() && item != mInfo && !mInfo.opened); 328073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen } 329073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen 330c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen public boolean acceptDrop(Object dragInfo) { 331c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen final ItemInfo item = (ItemInfo) dragInfo; 332fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen return !mFolder.isDestroyed() && willAcceptItem(item); 33331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 33431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 335df0353815c629fc678824b07a234b89a1ff94208Adam Cohen public void addItem(ShortcutInfo item) { 336df0353815c629fc678824b07a234b89a1ff94208Adam Cohen mInfo.add(item); 337df0353815c629fc678824b07a234b89a1ff94208Adam Cohen } 338df0353815c629fc678824b07a234b89a1ff94208Adam Cohen 339c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen public void onDragEnter(Object dragInfo) { 340fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen if (mFolder.isDestroyed() || !willAcceptItem((ItemInfo) dragInfo)) return; 34169ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams(); 34269ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen CellLayout layout = (CellLayout) getParent().getParent(); 34369ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen mFolderRingAnimator.setCell(lp.cellX, lp.cellY); 34469ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen mFolderRingAnimator.setCellLayout(layout); 34519072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen mFolderRingAnimator.animateToAcceptState(); 34669ce2e5beaa1a57c7b8fa14a2d6ff0b3abeb93c0Adam Cohen layout.showFolderAccept(mFolderRingAnimator); 34755bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi mOpenAlarm.setOnAlarmListener(mOnOpenListener); 348dedfca2aef7573624bdb421b1805ef5e04bee502Adam Cohen if (SPRING_LOADING_ENABLED && 349dedfca2aef7573624bdb421b1805ef5e04bee502Adam Cohen ((dragInfo instanceof AppInfo) || (dragInfo instanceof ShortcutInfo))) { 350dedfca2aef7573624bdb421b1805ef5e04bee502Adam Cohen // TODO: we currently don't support spring-loading for PendingAddShortcutInfos even 351dedfca2aef7573624bdb421b1805ef5e04bee502Adam Cohen // though widget-style shortcuts can be added to folders. The issue is that we need 352dedfca2aef7573624bdb421b1805ef5e04bee502Adam Cohen // to deal with configuration activities which are currently handled in 353dedfca2aef7573624bdb421b1805ef5e04bee502Adam Cohen // Workspace#onDropExternal. 35455bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi mOpenAlarm.setAlarm(ON_OPEN_DELAY); 35555bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi } 35655bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi mDragInfo = (ItemInfo) dragInfo; 357073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen } 358073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen 359c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen public void onDragOver(Object dragInfo) { 360073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen } 361073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen 36255bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi OnAlarmListener mOnOpenListener = new OnAlarmListener() { 36355bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi public void onAlarm(Alarm alarm) { 36455bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi ShortcutInfo item; 36555bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi if (mDragInfo instanceof AppInfo) { 36655bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi // Came from all apps -- make a copy. 36755bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi item = ((AppInfo) mDragInfo).makeShortcut(); 36855bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi item.spanX = 1; 36955bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi item.spanY = 1; 37055bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi } else { 371dedfca2aef7573624bdb421b1805ef5e04bee502Adam Cohen // ShortcutInfo 37255bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi item = (ShortcutInfo) mDragInfo; 37355bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi } 37455bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi mFolder.beginExternalDrag(item); 37555bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi mLauncher.openFolder(FolderIcon.this); 37655bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi } 37755bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi }; 37855bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi 379d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen public void performCreateAnimation(final ShortcutInfo destInfo, final View destView, 3807bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final ShortcutInfo srcInfo, final DragView srcView, Rect dstRect, 381ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen float scaleRelativeToDragLayer, Runnable postAnimationRunnable) { 382d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 383fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen // These correspond two the drawable and view that the icon was dropped _onto_ 38495abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal Drawable animateDrawable = getTopDrawable((TextView) destView); 385fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(), 386fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen destView.getMeasuredWidth()); 387fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen 388fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen // This will animate the first item from it's position as an icon into its 389fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen // position as the first item in the preview 390fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen animateFirstItem(animateDrawable, INITIAL_ITEM_ANIMATION_DURATION, false, null); 391fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen addItem(destInfo); 392ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen 393d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen // This will animate the dragView (srcView) into the new folder 3947bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, postAnimationRunnable, null); 395fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 396fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen 397fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen public void performDestroyAnimation(final View finalView, Runnable onCompleteRunnable) { 39895abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal Drawable animateDrawable = getTopDrawable((TextView) finalView); 39902dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(), 400fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen finalView.getMeasuredWidth()); 401d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 402d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen // This will animate the first item from it's position as an icon into its 403d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen // position as the first item in the preview 404fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen animateFirstItem(animateDrawable, FINAL_ITEM_ANIMATION_DURATION, true, 405fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen onCompleteRunnable); 406d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 407d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 408c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen public void onDragExit(Object dragInfo) { 409c6cc61d45836e4081920883cc4d448ccb0bb8417Adam Cohen onDragExit(); 410c6cc61d45836e4081920883cc4d448ccb0bb8417Adam Cohen } 411c6cc61d45836e4081920883cc4d448ccb0bb8417Adam Cohen 412c6cc61d45836e4081920883cc4d448ccb0bb8417Adam Cohen public void onDragExit() { 41319072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen mFolderRingAnimator.animateToNaturalState(); 41455bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi mOpenAlarm.cancelAlarm(); 415073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen } 416073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen 4177bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung private void onDrop(final ShortcutInfo item, DragView animateView, Rect finalRect, 4187bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float scaleRelativeToDragLayer, int index, Runnable postAnimationRunnable, 4197bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung DragObject d) { 420d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen item.cellX = -1; 421d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen item.cellY = -1; 422d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 423558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen // Typically, the animateView corresponds to the DragView; however, if this is being done 424558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen // after a configuration activity (ie. for a Shortcut being dragged from AllApps) we 425558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen // will not have a view to animate 426558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen if (animateView != null) { 427558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen DragLayer dragLayer = mLauncher.getDragLayer(); 428558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen Rect from = new Rect(); 429558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen dragLayer.getViewRectRelativeToSelf(animateView, from); 430558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen Rect to = finalRect; 431558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen if (to == null) { 432558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen to = new Rect(); 433558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen Workspace workspace = mLauncher.getWorkspace(); 434558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen // Set cellLayout and this to it's final state to compute final animation locations 435558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen workspace.setFinalTransitionTransform((CellLayout) getParent().getParent()); 436558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen float scaleX = getScaleX(); 437558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen float scaleY = getScaleY(); 438558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen setScaleX(1.0f); 439558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen setScaleY(1.0f); 440558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen scaleRelativeToDragLayer = dragLayer.getDescendantRectRelativeToSelf(this, to); 441558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen // Finished computing final animation locations, restore current state 442558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen setScaleX(scaleX); 443558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen setScaleY(scaleY); 444558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen workspace.resetTransitionTransform((CellLayout) getParent().getParent()); 445558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen } 446ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen 447558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen int[] center = new int[2]; 448558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen float scale = getLocalCenterForIndex(index, center); 449558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen center[0] = (int) Math.round(scaleRelativeToDragLayer * center[0]); 450558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen center[1] = (int) Math.round(scaleRelativeToDragLayer * center[1]); 451d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 452558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen to.offset(center[0] - animateView.getMeasuredWidth() / 2, 4535f8afe6280eae34620067696173e71943e1a30a3Winson Chung center[1] - animateView.getMeasuredHeight() / 2); 454d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 455558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen float finalAlpha = index < NUM_ITEMS_IN_PREVIEW ? 0.5f : 0f; 456558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen 457ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen float finalScale = scale * scaleRelativeToDragLayer; 458558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen dragLayer.animateView(animateView, from, to, finalAlpha, 459ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 1, 1, finalScale, finalScale, DROP_IN_ANIMATION_DURATION, 460558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen new DecelerateInterpolator(2), new AccelerateInterpolator(2), 461ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen postAnimationRunnable, DragLayer.ANIMATION_END_DISAPPEAR, null); 462fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen addItem(item); 463fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen mHiddenItems.add(item); 4647a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen mFolder.hideItem(item); 465558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen postDelayed(new Runnable() { 466558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen public void run() { 467fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen mHiddenItems.remove(item); 4687a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen mFolder.showItem(item); 469fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen invalidate(); 470558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen } 471558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen }, DROP_IN_ANIMATION_DURATION); 472558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen } else { 473558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen addItem(item); 474558baaf0a0b1c6a9062a6771088098533a35222bAdam Cohen } 475d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 476d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 4773e8f811f31a2275e778244427271f77f4116c08bAdam Cohen public void onDrop(DragObject d) { 478c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen ShortcutInfo item; 479eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka if (d.dragInfo instanceof AppInfo) { 480c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen // Came from all apps -- make a copy 481eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka item = ((AppInfo) d.dragInfo).makeShortcut(); 482c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen } else { 4833e8f811f31a2275e778244427271f77f4116c08bAdam Cohen item = (ShortcutInfo) d.dragInfo; 484c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen } 48567bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mFolder.notifyDrop(); 4867bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung onDrop(item, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable, d); 487c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen } 488c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen 489d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private void computePreviewDrawingParams(int drawableSize, int totalSize) { 490d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen if (mIntrinsicIconSize != drawableSize || mTotalWidth != totalSize) { 4915f8afe6280eae34620067696173e71943e1a30a3Winson Chung LauncherAppState app = LauncherAppState.getInstance(); 4925f8afe6280eae34620067696173e71943e1a30a3Winson Chung DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); 4935f8afe6280eae34620067696173e71943e1a30a3Winson Chung 494d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mIntrinsicIconSize = drawableSize; 495d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mTotalWidth = totalSize; 49676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 4975f8afe6280eae34620067696173e71943e1a30a3Winson Chung final int previewSize = mPreviewBackground.getLayoutParams().height; 498d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen final int previewPadding = FolderRingAnimator.sPreviewPadding; 499a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 500d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mAvailableSpaceInPreview = (previewSize - 2 * previewPadding); 501d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen // cos(45) = 0.707 + ~= 0.1) = 0.8f 502d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen int adjustedAvailableSpace = (int) ((mAvailableSpaceInPreview / 2) * (1 + 0.8f)); 503d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 504d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen int unscaledHeight = (int) (mIntrinsicIconSize * (1 + PERSPECTIVE_SHIFT_FACTOR)); 50596bb79819ef9ddf2d1c0cb0b72c2c9f6db26b4fdAdam Cohen 506d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mBaselineIconScale = (1.0f * adjustedAvailableSpace / unscaledHeight); 507a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 508d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mBaselineIconSize = (int) (mIntrinsicIconSize * mBaselineIconScale); 509d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mMaxPerspectiveShift = mBaselineIconSize * PERSPECTIVE_SHIFT_FACTOR; 510d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 511d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mPreviewOffsetX = (mTotalWidth - mAvailableSpaceInPreview) / 2; 5125f8afe6280eae34620067696173e71943e1a30a3Winson Chung mPreviewOffsetY = previewPadding + grid.folderBackgroundOffset; 513073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen } 514d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 51576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 516d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private void computePreviewDrawingParams(Drawable d) { 517d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen computePreviewDrawingParams(d.getIntrinsicWidth(), getMeasuredWidth()); 518d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 519073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen 520d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen class PreviewItemDrawingParams { 521d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen PreviewItemDrawingParams(float transX, float transY, float scale, int overlayAlpha) { 522d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen this.transX = transX; 523d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen this.transY = transY; 524d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen this.scale = scale; 525d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen this.overlayAlpha = overlayAlpha; 526d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 527d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen float transX; 528d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen float transY; 529d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen float scale; 530d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen int overlayAlpha; 531d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen Drawable drawable; 532d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 533badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen 534ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen private float getLocalCenterForIndex(int index, int[] center) { 535d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mParams = computePreviewItemDrawingParams(Math.min(NUM_ITEMS_IN_PREVIEW, index), mParams); 536a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 537d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mParams.transX += mPreviewOffsetX; 538d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mParams.transY += mPreviewOffsetY; 539ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen float offsetX = mParams.transX + (mParams.scale * mIntrinsicIconSize) / 2; 540ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen float offsetY = mParams.transY + (mParams.scale * mIntrinsicIconSize) / 2; 541badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen 542ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen center[0] = (int) Math.round(offsetX); 543ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen center[1] = (int) Math.round(offsetY); 544d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen return mParams.scale; 545d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 546badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen 547d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private PreviewItemDrawingParams computePreviewItemDrawingParams(int index, 548d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen PreviewItemDrawingParams params) { 549d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen index = NUM_ITEMS_IN_PREVIEW - index - 1; 550d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen float r = (index * 1.0f) / (NUM_ITEMS_IN_PREVIEW - 1); 551d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen float scale = (1 - PERSPECTIVE_SCALE_FACTOR * (1 - r)); 552d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 553d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen float offset = (1 - r) * mMaxPerspectiveShift; 554d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen float scaledSize = scale * mBaselineIconSize; 555d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen float scaleOffsetCorrection = (1 - scale) * mBaselineIconSize; 556d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 557d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen // We want to imagine our coordinates from the bottom left, growing up and to the 558d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen // right. This is natural for the x-axis, but for the y-axis, we have to invert things. 5595f8afe6280eae34620067696173e71943e1a30a3Winson Chung float transY = mAvailableSpaceInPreview - (offset + scaledSize + scaleOffsetCorrection) + getPaddingTop(); 56096bb79819ef9ddf2d1c0cb0b72c2c9f6db26b4fdAdam Cohen float transX = (mAvailableSpaceInPreview - scaledSize) / 2; 561d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen float totalScale = mBaselineIconScale * scale; 562d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen final int overlayAlpha = (int) (80 * (1 - r)); 563d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 564d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen if (params == null) { 565d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen params = new PreviewItemDrawingParams(transX, transY, totalScale, overlayAlpha); 566d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } else { 567d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen params.transX = transX; 568d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen params.transY = transY; 569d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen params.scale = totalScale; 570d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen params.overlayAlpha = overlayAlpha; 571d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 572d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen return params; 573d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 574badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen 575d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen private void drawPreviewItem(Canvas canvas, PreviewItemDrawingParams params) { 576d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen canvas.save(); 577d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen canvas.translate(params.transX + mPreviewOffsetX, params.transY + mPreviewOffsetY); 578d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen canvas.scale(params.scale, params.scale); 579d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen Drawable d = params.drawable; 580d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 581d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen if (d != null) { 582d4e53c882494f8cd7e4c0d44dbfc300d3610afcfWinson Chung mOldBounds.set(d.getBounds()); 583d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen d.setBounds(0, 0, mIntrinsicIconSize, mIntrinsicIconSize); 584c5c60ad3592f53549c9ffaa58e9a87b0480080e8Sunny Goyal if (d instanceof FastBitmapDrawable) { 585c5c60ad3592f53549c9ffaa58e9a87b0480080e8Sunny Goyal FastBitmapDrawable fd = (FastBitmapDrawable) d; 586508da15509224b46fcccabbe78f3e92fe69a67d8Sunny Goyal int oldBrightness = fd.getBrightness(); 587508da15509224b46fcccabbe78f3e92fe69a67d8Sunny Goyal fd.setBrightness(params.overlayAlpha); 588c5c60ad3592f53549c9ffaa58e9a87b0480080e8Sunny Goyal d.draw(canvas); 589508da15509224b46fcccabbe78f3e92fe69a67d8Sunny Goyal fd.setBrightness(oldBrightness); 590c5c60ad3592f53549c9ffaa58e9a87b0480080e8Sunny Goyal } else { 591c5c60ad3592f53549c9ffaa58e9a87b0480080e8Sunny Goyal d.setColorFilter(Color.argb(params.overlayAlpha, 255, 255, 255), 592c5c60ad3592f53549c9ffaa58e9a87b0480080e8Sunny Goyal PorterDuff.Mode.SRC_ATOP); 593c5c60ad3592f53549c9ffaa58e9a87b0480080e8Sunny Goyal d.draw(canvas); 594c5c60ad3592f53549c9ffaa58e9a87b0480080e8Sunny Goyal d.clearColorFilter(); 595c5c60ad3592f53549c9ffaa58e9a87b0480080e8Sunny Goyal } 596d4e53c882494f8cd7e4c0d44dbfc300d3610afcfWinson Chung d.setBounds(mOldBounds); 597d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 598d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen canvas.restore(); 599d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 60076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 601d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen @Override 602d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen protected void dispatchDraw(Canvas canvas) { 603d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen super.dispatchDraw(canvas); 604badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen 605d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen if (mFolder == null) return; 606d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen if (mFolder.getItemCount() == 0 && !mAnimating) return; 607d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 6087a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen ArrayList<View> items = mFolder.getItemsInReadingOrder(); 609d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen Drawable d; 610d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen TextView v; 611d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 612d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen // Update our drawing parameters if necessary 613d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen if (mAnimating) { 614d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen computePreviewDrawingParams(mAnimParams.drawable); 615d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } else { 616d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen v = (TextView) items.get(0); 6173484638cad97e255a412b0489a63873fb3ca4218Sunny Goyal d = getTopDrawable(v); 618d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen computePreviewDrawingParams(d); 619d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 620a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 621d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen int nItemsInPreview = Math.min(items.size(), NUM_ITEMS_IN_PREVIEW); 622d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen if (!mAnimating) { 623d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen for (int i = nItemsInPreview - 1; i >= 0; i--) { 624d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen v = (TextView) items.get(i); 625fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen if (!mHiddenItems.contains(v.getTag())) { 6263484638cad97e255a412b0489a63873fb3ca4218Sunny Goyal d = getTopDrawable(v); 627fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen mParams = computePreviewItemDrawingParams(i, mParams); 628fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen mParams.drawable = d; 629fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen drawPreviewItem(canvas, mParams); 630fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 631a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen } 632d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } else { 633d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen drawPreviewItem(canvas, mAnimParams); 634a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen } 635d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 636d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 6373484638cad97e255a412b0489a63873fb3ca4218Sunny Goyal private Drawable getTopDrawable(TextView v) { 6383484638cad97e255a412b0489a63873fb3ca4218Sunny Goyal Drawable d = v.getCompoundDrawables()[1]; 6393484638cad97e255a412b0489a63873fb3ca4218Sunny Goyal return (d instanceof PreloadIconDrawable) ? ((PreloadIconDrawable) d).mIcon : d; 6403484638cad97e255a412b0489a63873fb3ca4218Sunny Goyal } 6413484638cad97e255a412b0489a63873fb3ca4218Sunny Goyal 642fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen private void animateFirstItem(final Drawable d, int duration, final boolean reverse, 643fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen final Runnable onCompleteRunnable) { 644d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen final PreviewItemDrawingParams finalParams = computePreviewItemDrawingParams(0, null); 645d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 646d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen final float scale0 = 1.0f; 6471d4ee4e46218fb98a43cf584d8d4e3e569850f78Adam Cohen final float transX0 = (mAvailableSpaceInPreview - d.getIntrinsicWidth()) / 2; 6485f8afe6280eae34620067696173e71943e1a30a3Winson Chung final float transY0 = (mAvailableSpaceInPreview - d.getIntrinsicHeight()) / 2 + getPaddingTop(); 649d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mAnimParams.drawable = d; 650d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 651f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka ValueAnimator va = LauncherAnimUtils.ofFloat(this, 0f, 1.0f); 652d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen va.addUpdateListener(new AnimatorUpdateListener(){ 653d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen public void onAnimationUpdate(ValueAnimator animation) { 654d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen float progress = (Float) animation.getAnimatedValue(); 655fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen if (reverse) { 656fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen progress = 1 - progress; 657fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen mPreviewBackground.setAlpha(progress); 658fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 659d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen 660d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mAnimParams.transX = transX0 + progress * (finalParams.transX - transX0); 661d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mAnimParams.transY = transY0 + progress * (finalParams.transY - transY0); 662d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mAnimParams.scale = scale0 + progress * (finalParams.scale - scale0); 663d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen invalidate(); 664d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 665d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen }); 666d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen va.addListener(new AnimatorListenerAdapter() { 667d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen @Override 668d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen public void onAnimationStart(Animator animation) { 669d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mAnimating = true; 670d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 671d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen @Override 672d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen public void onAnimationEnd(Animator animation) { 673d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen mAnimating = false; 674fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen if (onCompleteRunnable != null) { 675fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen onCompleteRunnable.run(); 676fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 677d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen } 678d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen }); 679d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen va.setDuration(duration); 680d044526d82e7938cf35b296978d9d5302f98b4afAdam Cohen va.start(); 681a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen } 682a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 683099f60d51f6310e1290687e83958e665b3324504Adam Cohen public void setTextVisible(boolean visible) { 684099f60d51f6310e1290687e83958e665b3324504Adam Cohen if (visible) { 685099f60d51f6310e1290687e83958e665b3324504Adam Cohen mFolderName.setVisibility(VISIBLE); 686099f60d51f6310e1290687e83958e665b3324504Adam Cohen } else { 687099f60d51f6310e1290687e83958e665b3324504Adam Cohen mFolderName.setVisibility(INVISIBLE); 688099f60d51f6310e1290687e83958e665b3324504Adam Cohen } 689099f60d51f6310e1290687e83958e665b3324504Adam Cohen } 690099f60d51f6310e1290687e83958e665b3324504Adam Cohen 691099f60d51f6310e1290687e83958e665b3324504Adam Cohen public boolean getTextVisible() { 692099f60d51f6310e1290687e83958e665b3324504Adam Cohen return mFolderName.getVisibility() == VISIBLE; 693099f60d51f6310e1290687e83958e665b3324504Adam Cohen } 694099f60d51f6310e1290687e83958e665b3324504Adam Cohen 69576078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen public void onItemsChanged() { 69676078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen invalidate(); 69776078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen requestLayout(); 69876078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen } 69976078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen 700a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen public void onAdd(ShortcutInfo item) { 701a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen invalidate(); 702a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen requestLayout(); 703a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen } 704a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 705a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen public void onRemove(ShortcutInfo item) { 706a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen invalidate(); 707a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen requestLayout(); 708a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen } 70976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 71076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void onTitleChanged(CharSequence title) { 711d63cfa96814fa1a51490950b8df9853eef305cbbAdam Cohen mFolderName.setText(title.toString()); 7128b805b17158886035b38261eb611d8641701ae43Michael Jurka setContentDescription(String.format(getContext().getString(R.string.folder_name_format), 7133371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen title)); 71476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 71588f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung 71688f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung @Override 71788f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung public boolean onTouchEvent(MotionEvent event) { 71888f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung // Call the superclass onTouchEvent first, because sometimes it changes the state to 71988f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung // isPressed() on an ACTION_UP 72088f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung boolean result = super.onTouchEvent(event); 72188f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung 72288f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung switch (event.getAction()) { 72388f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung case MotionEvent.ACTION_DOWN: 72488f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung mLongPressHelper.postCheckForLongPress(); 72588f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung break; 72688f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung case MotionEvent.ACTION_CANCEL: 72788f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung case MotionEvent.ACTION_UP: 72888f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung mLongPressHelper.cancelLongPress(); 72988f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung break; 73002dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk case MotionEvent.ACTION_MOVE: 73102dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk if (!Utilities.pointInView(this, event.getX(), event.getY(), mSlop)) { 73202dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk mLongPressHelper.cancelLongPress(); 73302dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk } 73402dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk break; 73588f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung } 73688f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung return result; 73788f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung } 73888f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung 73988f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung @Override 74002dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk protected void onAttachedToWindow() { 74102dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk super.onAttachedToWindow(); 74202dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); 74302dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk } 74402dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk 74502dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk @Override 74688f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung public void cancelLongPress() { 74788f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung super.cancelLongPress(); 74888f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung 74988f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung mLongPressHelper.cancelLongPress(); 75088f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung } 75131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project} 752