151889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham/* 251889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham * Copyright (C) 2017 The Android Open Source Project 351889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham * 451889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham * Licensed under the Apache License, Version 2.0 (the "License"); 551889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham * you may not use this file except in compliance with the License. 651889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham * You may obtain a copy of the License at 751889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham * 851889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham * http://www.apache.org/licenses/LICENSE-2.0 951889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham * 1051889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham * Unless required by applicable law or agreed to in writing, software 1151889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham * distributed under the License is distributed on an "AS IS" BASIS, 1251889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1351889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham * See the License for the specific language governing permissions and 1451889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham * limitations under the License. 1551889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham */ 1651889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 1751889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhampackage com.android.launcher3.shortcuts; 1851889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 19887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTonyimport android.animation.Animator; 20887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTonyimport android.animation.AnimatorSet; 21887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTonyimport android.animation.ObjectAnimator; 2251889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport android.content.Context; 2351889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport android.graphics.Point; 24887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTonyimport android.graphics.Rect; 2551889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport android.util.AttributeSet; 265a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickhamimport android.util.Log; 2751889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport android.view.MotionEvent; 2851889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport android.view.View; 2951889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport android.widget.LinearLayout; 3051889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 3151889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport com.android.launcher3.AbstractFloatingView; 32a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickhamimport com.android.launcher3.BubbleTextView; 3351889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport com.android.launcher3.ItemInfo; 3451889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport com.android.launcher3.Launcher; 35887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTonyimport com.android.launcher3.LauncherAnimUtils; 3651889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport com.android.launcher3.R; 37aa2272f81cc4a62f847db777efda7959cc2b9979Tony Wickhamimport com.android.launcher3.anim.PropertyListBuilder; 38887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTonyimport com.android.launcher3.anim.RoundedRectRevealOutlineProvider; 3951889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport com.android.launcher3.dragndrop.DragOptions; 4051889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport com.android.launcher3.dragndrop.DragView; 4151889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport com.android.launcher3.logging.UserEventDispatcher.LogContainerProvider; 4251889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport com.android.launcher3.popup.PopupContainerWithArrow; 4351889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport com.android.launcher3.popup.PopupItemView; 4426b1746593851e239bfff65ae7a69b809ad87b99Tony Wickhamimport com.android.launcher3.popup.PopupPopulator; 4526b1746593851e239bfff65ae7a69b809ad87b99Tony Wickhamimport com.android.launcher3.popup.SystemShortcut; 4651889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport com.android.launcher3.userevent.nano.LauncherLogProto; 4751889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 4851889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport java.util.ArrayList; 4926b1746593851e239bfff65ae7a69b809ad87b99Tony Wickhamimport java.util.Collections; 5051889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhamimport java.util.List; 5151889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 5251889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham/** 5326b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham * A {@link PopupItemView} that contains all of the {@link DeepShortcutView}s for an app, 5426b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham * as well as the system shortcuts such as Widgets and App Info. 5551889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham */ 5651889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickhampublic class ShortcutsItemView extends PopupItemView implements View.OnLongClickListener, 5751889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham View.OnTouchListener, LogContainerProvider { 5851889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 595a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham private static final String TAG = "ShortcutsItem"; 605a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham 6151889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham private Launcher mLauncher; 62887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony private LinearLayout mContent; 6326b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham private LinearLayout mShortcutsLayout; 6426b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham private LinearLayout mSystemShortcutIcons; 6551889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham private final Point mIconShift = new Point(); 6651889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham private final Point mIconLastTouchPos = new Point(); 6726b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham private final List<DeepShortcutView> mDeepShortcutViews = new ArrayList<>(); 6826b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham private final List<View> mSystemShortcutViews = new ArrayList<>(); 6951889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 70887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony private int mHiddenShortcutsHeight; 71887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony 7251889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham public ShortcutsItemView(Context context) { 7351889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham this(context, null, 0); 7451889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 7551889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 7651889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham public ShortcutsItemView(Context context, AttributeSet attrs) { 7751889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham this(context, attrs, 0); 7851889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 7951889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 8051889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham public ShortcutsItemView(Context context, AttributeSet attrs, int defStyle) { 8151889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham super(context, attrs, defStyle); 8251889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 8351889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham mLauncher = Launcher.getLauncher(context); 8451889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 8551889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 8651889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham @Override 8751889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham protected void onFinishInflate() { 8851889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham super.onFinishInflate(); 89887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony mContent = findViewById(R.id.content); 90887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony mShortcutsLayout = findViewById(R.id.shortcuts); 9151889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 9251889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 9351889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham @Override 9451889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham public boolean onTouch(View v, MotionEvent ev) { 9551889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham // Touched a shortcut, update where it was touched so we can drag from there on long click. 9651889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham switch (ev.getAction()) { 9751889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham case MotionEvent.ACTION_DOWN: 9851889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham case MotionEvent.ACTION_MOVE: 9951889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham mIconLastTouchPos.set((int) ev.getX(), (int) ev.getY()); 10051889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham break; 10151889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 10251889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham return false; 10351889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 10451889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 10551889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham @Override 10651889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham public boolean onLongClick(View v) { 107cd04c89f89dd092d34d149dad107efd7ae00fb2aMario Bertschler // Return early if not the correct view 108cd04c89f89dd092d34d149dad107efd7ae00fb2aMario Bertschler if (!(v.getParent() instanceof DeepShortcutView)) return false; 10951889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham // Return early if global dragging is not enabled 11051889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham if (!mLauncher.isDraggingEnabled()) return false; 11151889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham // Return early if an item is already being dragged (e.g. when long-pressing two shortcuts) 11251889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham if (mLauncher.getDragController().isDragging()) return false; 11351889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 11451889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham // Long clicked on a shortcut. 11551889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham DeepShortcutView sv = (DeepShortcutView) v.getParent(); 11651889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham sv.setWillDrawIcon(false); 11751889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 11851889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham // Move the icon to align with the center-top of the touch point 11951889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham mIconShift.x = mIconLastTouchPos.x - sv.getIconCenter().x; 12051889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham mIconShift.y = mIconLastTouchPos.y - mLauncher.getDeviceProfile().iconSizePx; 12151889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 122aa6f66aad29171bda85e0633c93530beefdac307Jon Miranda DragView dv = mLauncher.getWorkspace().beginDragShared(sv.getIconView(), 12351889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham (PopupContainerWithArrow) getParent(), sv.getFinalInfo(), 12451889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham new ShortcutDragPreviewProvider(sv.getIconView(), mIconShift), new DragOptions()); 12551889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham dv.animateShift(-mIconShift.x, -mIconShift.y); 12651889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 12751889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham // TODO: support dragging from within folder without having to close it 12851889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham AbstractFloatingView.closeOpenContainer(mLauncher, AbstractFloatingView.TYPE_FOLDER); 12951889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham return false; 13051889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 13151889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 132ce44516dd869dff1d6a744e26625a662d9567a10Tony Wickham public void addShortcutView(View shortcutView, PopupPopulator.Item shortcutType) { 133a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham addShortcutView(shortcutView, shortcutType, -1); 134a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham } 135a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham 136a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham private void addShortcutView(View shortcutView, PopupPopulator.Item shortcutType, int index) { 13726b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham if (shortcutType == PopupPopulator.Item.SHORTCUT) { 13826b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham mDeepShortcutViews.add((DeepShortcutView) shortcutView); 13926b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham } else { 14026b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham mSystemShortcutViews.add(shortcutView); 14126b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham } 14226b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham if (shortcutType == PopupPopulator.Item.SYSTEM_SHORTCUT_ICON) { 14326b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham // System shortcut icons are added to a header that is separate from the full shortcuts. 14426b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham if (mSystemShortcutIcons == null) { 14526b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham mSystemShortcutIcons = (LinearLayout) mLauncher.getLayoutInflater().inflate( 146887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony R.layout.system_shortcut_icons, mContent, false); 147887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony boolean iconsAreBelowShortcuts = mShortcutsLayout.getChildCount() > 0; 14845cdfa78d4f39db1d18514c4cab0e0e8442b5202Tony mContent.addView(mSystemShortcutIcons, iconsAreBelowShortcuts ? -1 : 0); 14926b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham } 150a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham mSystemShortcutIcons.addView(shortcutView, index); 15126b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham } else { 15226b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham if (mShortcutsLayout.getChildCount() > 0) { 15326b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham View prevChild = mShortcutsLayout.getChildAt(mShortcutsLayout.getChildCount() - 1); 15426b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham if (prevChild instanceof DeepShortcutView) { 15526b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham prevChild.findViewById(R.id.divider).setVisibility(VISIBLE); 15626b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham } 15726b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham } 158a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham mShortcutsLayout.addView(shortcutView, index); 15951889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 16051889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 16151889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 16226b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham public List<DeepShortcutView> getDeepShortcutViews(boolean reverseOrder) { 16326b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham if (reverseOrder) { 16426b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham Collections.reverse(mDeepShortcutViews); 16526b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham } 16626b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham return mDeepShortcutViews; 16751889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 16851889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 16926b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham public List<View> getSystemShortcutViews(boolean reverseOrder) { 170ee82b035dbaf0cba73ffd856ddc97d092728dc34Tony Wickham // Always reverse system shortcut icons (in the header) 171ee82b035dbaf0cba73ffd856ddc97d092728dc34Tony Wickham // so they are in priority order from right to left. 172ee82b035dbaf0cba73ffd856ddc97d092728dc34Tony Wickham if (reverseOrder || mSystemShortcutIcons != null) { 17326b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham Collections.reverse(mSystemShortcutViews); 17426b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham } 17526b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham return mSystemShortcutViews; 17651889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 17751889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 17826b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham /** 1795a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham * Hides shortcuts until only {@param maxShortcuts} are showing. Also sets 1805a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham * {@link #mHiddenShortcutsHeight} to be the amount of extra space that shortcuts will 1815a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham * require when {@link #showAllShortcuts(boolean)} is called. 182887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony */ 183887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony public void hideShortcuts(boolean hideFromTop, int maxShortcuts) { 1845a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham // When shortcuts are shown, they get more space allocated to them. 1855a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham final int oldHeight = mShortcutsLayout.getChildAt(0).getLayoutParams().height; 1865a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham final int newHeight = getResources().getDimensionPixelSize(R.dimen.bg_popup_item_height); 1875a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham mHiddenShortcutsHeight = (newHeight - oldHeight) * mShortcutsLayout.getChildCount(); 1885a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham 189887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony int numToHide = mShortcutsLayout.getChildCount() - maxShortcuts; 190887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony if (numToHide <= 0) { 191887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony return; 192887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony } 193887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony final int numShortcuts = mShortcutsLayout.getChildCount(); 194887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony final int dir = hideFromTop ? 1 : -1; 195887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony for (int i = hideFromTop ? 0 : numShortcuts - 1; 0 <= i && i < numShortcuts; i += dir) { 196887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony View child = mShortcutsLayout.getChildAt(i); 197887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony if (child instanceof DeepShortcutView) { 198887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony mHiddenShortcutsHeight += child.getLayoutParams().height; 199887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony child.setVisibility(GONE); 200887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony int prev = i + dir; 201887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony if (!hideFromTop && 0 <= prev && prev < numShortcuts) { 202887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony // When hiding views from the bottom, make sure to hide the last divider. 203887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony mShortcutsLayout.getChildAt(prev).findViewById(R.id.divider).setVisibility(GONE); 204887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony } 205887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony numToHide--; 206887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony if (numToHide == 0) { 207887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony break; 208887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony } 209887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony } 210887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony } 211887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony } 212887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony 213887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony public int getHiddenShortcutsHeight() { 214887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony return mHiddenShortcutsHeight; 215887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony } 216887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony 217887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony /** 218887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony * Sets all shortcuts in {@link #mShortcutsLayout} to VISIBLE, then creates an 219887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony * animation to reveal the newly shown shortcuts. 220887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony * 221887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony * @see #hideShortcuts(boolean, int) 222887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony */ 223887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony public Animator showAllShortcuts(boolean showFromTop) { 224887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony // First set all the shortcuts to VISIBLE. 225887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony final int numShortcuts = mShortcutsLayout.getChildCount(); 2265a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham if (numShortcuts == 0) { 2275a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham Log.w(TAG, "Tried to show all shortcuts but there were no shortcuts to show"); 2285a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham return null; 2295a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham } 2305a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham final int oldHeight = mShortcutsLayout.getChildAt(0).getLayoutParams().height; 2315a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham final int newHeight = getResources().getDimensionPixelSize(R.dimen.bg_popup_item_height); 232887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony for (int i = 0; i < numShortcuts; i++) { 233887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony DeepShortcutView view = (DeepShortcutView) mShortcutsLayout.getChildAt(i); 2345a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham view.getLayoutParams().height = newHeight; 2355a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham view.requestLayout(); 236887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony view.setVisibility(VISIBLE); 237887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony if (i < numShortcuts - 1) { 238887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony view.findViewById(R.id.divider).setVisibility(VISIBLE); 239887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony } 240887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony } 241887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony 242887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony // Now reveal the newly shown shortcuts. 243887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony AnimatorSet animation = LauncherAnimUtils.createAnimatorSet(); 244887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony 245887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony if (showFromTop) { 246887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony // The new shortcuts pushed the original shortcuts down, but we want to animate them 247887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony // to that position. So we revert the translation and animate to the new. 2485a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham animation.play(translateYFrom(mShortcutsLayout, -mHiddenShortcutsHeight)); 249887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony } else if (mSystemShortcutIcons != null) { 250887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony // When adding the shortcuts from the bottom, things are a little trickier, since 251887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony // that means they push the icons header down. To account for this, we do the same 252887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony // translation trick as above, but on the header. Since this means leaving behind 253887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony // a blank area where the header was, we also need to clip the background. 2545a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham animation.play(translateYFrom(mSystemShortcutIcons, -mHiddenShortcutsHeight)); 255887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony // mPillRect is the bounds of this view before the new shortcuts were shown. 256887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony Rect backgroundStartRect = new Rect(mPillRect); 257887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony Rect backgroundEndRect = new Rect(mPillRect); 258887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony backgroundEndRect.bottom += mHiddenShortcutsHeight; 259887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony animation.play(new RoundedRectRevealOutlineProvider(getBackgroundRadius(), 260887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony getBackgroundRadius(), backgroundStartRect, backgroundEndRect, mRoundedCorners) 261887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony .createRevealAnimator(this, false)); 262887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony } 2635a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham for (int i = 0; i < numShortcuts; i++) { 2645a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham // Animate each shortcut to its new height. 2655a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham DeepShortcutView shortcut = (DeepShortcutView) mShortcutsLayout.getChildAt(i); 2665a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham int heightDiff = newHeight - oldHeight; 2675a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham int heightAdjustmentIndex = showFromTop ? numShortcuts - i - 1 : i; 2685a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham int fromDir = showFromTop ? 1 : -1; 2695a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham animation.play(translateYFrom(shortcut, heightDiff * heightAdjustmentIndex * fromDir)); 2705a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham // Make sure the text and icon stay centered in the shortcut. 2715a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham animation.play(translateYFrom(shortcut.getBubbleText(), heightDiff / 2 * fromDir)); 2725a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham animation.play(translateYFrom(shortcut.getIconView(), heightDiff / 2 * fromDir)); 273aa2272f81cc4a62f847db777efda7959cc2b9979Tony Wickham // Scale icons back up to full size. 274aa2272f81cc4a62f847db777efda7959cc2b9979Tony Wickham animation.play(LauncherAnimUtils.ofPropertyValuesHolder(shortcut.getIconView(), 275aa2272f81cc4a62f847db777efda7959cc2b9979Tony Wickham new PropertyListBuilder().scale(1f).build())); 2765a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham } 277887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony return animation; 278887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony } 279887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony 280887bd1fe1af9a37aad78ad51f5b38b265aa09c3aTony /** 2815a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham * Animates the translationY of the view from the given offset to the view's current translation 2825a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham * @return an Animator, which should be started by the caller. 2835a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham */ 2845a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham private Animator translateYFrom(View v, int diff) { 2855a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham float finalY = v.getTranslationY(); 2865a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham return ObjectAnimator.ofFloat(v, TRANSLATION_Y, finalY + diff, finalY); 2875a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham } 2885a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham 2895a1ca5756ecea6784743f5cd1540844c1a83b36fTony Wickham /** 290a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham * Adds a {@link SystemShortcut.Widgets} item if there are widgets for the given ItemInfo. 29126b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham */ 292a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham public void enableWidgetsIfExist(final BubbleTextView originalIcon) { 293a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham ItemInfo itemInfo = (ItemInfo) originalIcon.getTag(); 294a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham SystemShortcut widgetInfo = new SystemShortcut.Widgets(); 295a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham View.OnClickListener onClickListener = widgetInfo.getOnClickListener(mLauncher, itemInfo); 296a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham View widgetsView = null; 297a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham for (View systemShortcutView : mSystemShortcutViews) { 298a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham if (systemShortcutView.getTag() instanceof SystemShortcut.Widgets) { 299a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham widgetsView = systemShortcutView; 300a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham break; 301a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham } 302a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham } 303a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham final PopupPopulator.Item widgetsItem = mSystemShortcutIcons == null 304a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham ? PopupPopulator.Item.SYSTEM_SHORTCUT 305a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham : PopupPopulator.Item.SYSTEM_SHORTCUT_ICON; 306a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham if (onClickListener != null && widgetsView == null) { 307a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham // We didn't have any widgets cached but now there are some, so enable the shortcut. 308a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham widgetsView = mLauncher.getLayoutInflater().inflate(widgetsItem.layoutId, this, false); 309a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham PopupPopulator.initializeSystemShortcut(getContext(), widgetsView, widgetInfo); 310a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham widgetsView.setOnClickListener(onClickListener); 311a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham if (widgetsItem == PopupPopulator.Item.SYSTEM_SHORTCUT_ICON) { 312a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham addShortcutView(widgetsView, widgetsItem, 0); 313a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham } else { 314a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham // If using the expanded system shortcut (as opposed to just the icon), we need to 315a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham // reopen the container to ensure measurements etc. all work out. While this could 316a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham // be quite janky, in practice the user would typically see a small flicker as the 317a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham // animation restarts partway through, and this is a very rare edge case anyway. 318a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham ((PopupContainerWithArrow) getParent()).close(false); 319a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham PopupContainerWithArrow.showForIcon(originalIcon); 320a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham } 321a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham } else if (onClickListener == null && widgetsView != null) { 322a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham // No widgets exist, but we previously added the shortcut so remove it. 323a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham if (widgetsItem == PopupPopulator.Item.SYSTEM_SHORTCUT_ICON) { 324a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham mSystemShortcutViews.remove(widgetsView); 325a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham mSystemShortcutIcons.removeView(widgetsView); 326a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham } else { 327a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham ((PopupContainerWithArrow) getParent()).close(false); 328a7e1c1c08854930ddb4366698d5bf079ae0536f3Tony Wickham PopupContainerWithArrow.showForIcon(originalIcon); 32951889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 33051889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 33151889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 33251889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham 33351889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham @Override 33451889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham public void fillInLogContainerData(View v, ItemInfo info, LauncherLogProto.Target target, 33551889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham LauncherLogProto.Target targetParent) { 33651889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham target.itemType = LauncherLogProto.ItemType.DEEPSHORTCUT; 33751889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham target.rank = info.rank; 33851889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham targetParent.containerType = LauncherLogProto.ContainerType.DEEPSHORTCUTS; 33951889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham } 34051889b0be83dc34c9752fc066d0d6e75ab4f5e26Tony Wickham} 341