diff options
Diffstat (limited to 'src/com/android/launcher3/folder/Folder.java')
-rw-r--r-- | src/com/android/launcher3/folder/Folder.java | 285 |
1 files changed, 158 insertions, 127 deletions
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 698e5aa04..2952196fa 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -46,9 +46,9 @@ import android.view.animation.AccelerateInterpolator; import android.view.animation.AnimationUtils; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; -import android.widget.LinearLayout; import android.widget.TextView; +import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Alarm; import com.android.launcher3.AppInfo; import com.android.launcher3.BubbleTextView; @@ -71,8 +71,9 @@ import com.android.launcher3.ShortcutInfo; import com.android.launcher3.UninstallDropTarget.DropTargetSource; import com.android.launcher3.Utilities; import com.android.launcher3.Workspace.ItemOperator; -import com.android.launcher3.accessibility.AccessibileDragListenerAdapter; +import com.android.launcher3.accessibility.AccessibleDragListenerAdapter; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.config.ProviderConfig; import com.android.launcher3.dragndrop.DragController; import com.android.launcher3.dragndrop.DragController.DragListener; import com.android.launcher3.dragndrop.DragLayer; @@ -91,9 +92,10 @@ import java.util.Comparator; /** * Represents a set of icons chosen by the user or generated by the system. */ -public class Folder extends LinearLayout implements DragSource, View.OnClickListener, +public class Folder extends AbstractFloatingView implements DragSource, View.OnClickListener, View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener, - View.OnFocusChangeListener, DragListener, DropTargetSource { + View.OnFocusChangeListener, DragListener, DropTargetSource, + ExtendedEditText.OnBackKeyListener { private static final String TAG = "Launcher.Folder"; /** @@ -227,14 +229,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mPageIndicator = (PageIndicatorDots) findViewById(R.id.folder_page_indicator); mFolderName = (ExtendedEditText) findViewById(R.id.folder_name); - mFolderName.setOnBackKeyListener(new ExtendedEditText.OnBackKeyListener() { - @Override - public boolean onBackKey() { - // Close the activity on back key press - doneEditingFolderName(true); - return false; - } - }); + mFolderName.setOnBackKeyListener(this); mFolderName.setOnFocusChangeListener(this); if (!Utilities.ATLEAST_MARSHMALLOW) { @@ -281,17 +276,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList public boolean onLongClick(View v) { // Return if global dragging is not enabled if (!mLauncher.isDraggingEnabled()) return true; - DragOptions dragOptions = new DragOptions(); - if (v instanceof BubbleTextView) { - BubbleTextView icon = (BubbleTextView) v; - if (icon.hasDeepShortcuts()) { - DeepShortcutsContainer dsc = DeepShortcutsContainer.showForIcon(icon); - if (dsc != null) { - dragOptions.deferDragCondition = dsc.createDeferDragCondition(null); - } - } - } - return startDrag(v, dragOptions); + return startDrag(v, new DragOptions()); } public boolean startDrag(View v, DragOptions options) { @@ -307,7 +292,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mDragController.addDragListener(this); if (options.isAccessibleDrag) { - mDragController.addDragListener(new AccessibileDragListenerAdapter( + mDragController.addDragListener(new AccessibleDragListenerAdapter( mContent, CellLayout.FOLDER_ACCESSIBILITY_DRAG) { @Override @@ -367,12 +352,9 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList }); } - public void dismissEditingName() { - mInputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); - doneEditingFolderName(true); - } - public void doneEditingFolderName(boolean commit) { + @Override + public boolean onBackKey() { mFolderName.setHint(sHintText); // Convert to a string here to ensure that no other state associated with the text field // gets saved. @@ -380,30 +362,30 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mInfo.setTitle(newTitle); LauncherModel.updateItemInDatabase(mLauncher, mInfo); - if (commit) { - Utilities.sendCustomAccessibilityEvent( - this, AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, - getContext().getString(R.string.folder_renamed, newTitle)); - } + Utilities.sendCustomAccessibilityEvent( + this, AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, + getContext().getString(R.string.folder_renamed, newTitle)); // This ensures that focus is gained every time the field is clicked, which selects all // the text and brings up the soft keyboard if necessary. mFolderName.clearFocus(); - Selection.setSelection((Spannable) mFolderName.getText(), 0, 0); + Selection.setSelection(mFolderName.getText(), 0, 0); mIsEditingName = false; + return true; } public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE) { - dismissEditingName(); + mFolderName.dispatchBackKey(); return true; } return false; } - public View getEditTextRegion() { - return mFolderName; + @Override + public ExtendedEditText getActiveTextView() { + return isEditingName() ? mFolderName : null; } /** @@ -528,8 +510,33 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mState = STATE_SMALL; } + /** + * Opens the user folder described by the specified tag. The opening of the folder + * is animated relative to the specified View. If the View is null, no animation + * is played. + */ public void animateOpen() { - if (!(getParent() instanceof DragLayer)) return; + Folder openFolder = getOpen(mLauncher); + if (openFolder != null && openFolder != this) { + // Close any open folder before opening a folder. + openFolder.close(true); + } + + DragLayer dragLayer = mLauncher.getDragLayer(); + // Just verify that the folder hasn't already been added to the DragLayer. + // There was a one-off crash where the folder had a parent already. + if (getParent() == null) { + dragLayer.addView(this); + mDragController.addDropTarget(this); + } else { + if (ProviderConfig.IS_DOGFOOD_BUILD) { + Log.e(TAG, "Opening folder (" + this + ") which already has a parent:" + + getParent()); + } + } + + mIsOpen = true; + mFolderIcon.growAndFadeOut(); mContent.completePendingPageChanges(); if (!mDragInProgress) { @@ -542,83 +549,63 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList // dropping. One resulting issue is that replaceFolderWithFinalItem() can be called twice. mDeleteFolderOnDropCompleted = false; - Animator openFolderAnim = null; final Runnable onCompleteRunnable; - if (!Utilities.ATLEAST_LOLLIPOP) { - positionAndSizeAsIcon(); - centerAboutIcon(); + prepareReveal(); + centerAboutIcon(); - final ObjectAnimator oa = LauncherAnimUtils.ofViewAlphaAndScale(this, 1, 1, 1); - oa.setDuration(mExpandDuration); - openFolderAnim = oa; + AnimatorSet anim = LauncherAnimUtils.createAnimatorSet(); + int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); + int height = getFolderHeight(); - setLayerType(LAYER_TYPE_HARDWARE, null); - onCompleteRunnable = new Runnable() { - @Override - public void run() { - setLayerType(LAYER_TYPE_NONE, null); - } - }; - } else { - prepareReveal(); - centerAboutIcon(); - - AnimatorSet anim = LauncherAnimUtils.createAnimatorSet(); - int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); - int height = getFolderHeight(); - - float transX = - 0.075f * (width / 2 - getPivotX()); - float transY = - 0.075f * (height / 2 - getPivotY()); - setTranslationX(transX); - setTranslationY(transY); - PropertyValuesHolder tx = PropertyValuesHolder.ofFloat(TRANSLATION_X, transX, 0); - PropertyValuesHolder ty = PropertyValuesHolder.ofFloat(TRANSLATION_Y, transY, 0); - - Animator drift = ObjectAnimator.ofPropertyValuesHolder(this, tx, ty); - drift.setDuration(mMaterialExpandDuration); - drift.setStartDelay(mMaterialExpandStagger); - drift.setInterpolator(new LogDecelerateInterpolator(100, 0)); - - int rx = (int) Math.max(Math.max(width - getPivotX(), 0), getPivotX()); - int ry = (int) Math.max(Math.max(height - getPivotY(), 0), getPivotY()); - float radius = (float) Math.hypot(rx, ry); - - Animator reveal = new CircleRevealOutlineProvider((int) getPivotX(), - (int) getPivotY(), 0, radius).createRevealAnimator(this); - reveal.setDuration(mMaterialExpandDuration); - reveal.setInterpolator(new LogDecelerateInterpolator(100, 0)); - - mContent.setAlpha(0f); - Animator iconsAlpha = ObjectAnimator.ofFloat(mContent, "alpha", 0f, 1f); - iconsAlpha.setDuration(mMaterialExpandDuration); - iconsAlpha.setStartDelay(mMaterialExpandStagger); - iconsAlpha.setInterpolator(new AccelerateInterpolator(1.5f)); - - mFooter.setAlpha(0f); - Animator textAlpha = ObjectAnimator.ofFloat(mFooter, "alpha", 0f, 1f); - textAlpha.setDuration(mMaterialExpandDuration); - textAlpha.setStartDelay(mMaterialExpandStagger); - textAlpha.setInterpolator(new AccelerateInterpolator(1.5f)); - - anim.play(drift); - anim.play(iconsAlpha); - anim.play(textAlpha); - anim.play(reveal); - - openFolderAnim = anim; - - mContent.setLayerType(LAYER_TYPE_HARDWARE, null); - mFooter.setLayerType(LAYER_TYPE_HARDWARE, null); - onCompleteRunnable = new Runnable() { - @Override - public void run() { - mContent.setLayerType(LAYER_TYPE_NONE, null); - mFooter.setLayerType(LAYER_TYPE_NONE, null); - mLauncher.getUserEventDispatcher().resetElapsedContainerMillis(); - } - }; - } - openFolderAnim.addListener(new AnimatorListenerAdapter() { + float transX = - 0.075f * (width / 2 - getPivotX()); + float transY = - 0.075f * (height / 2 - getPivotY()); + setTranslationX(transX); + setTranslationY(transY); + PropertyValuesHolder tx = PropertyValuesHolder.ofFloat(TRANSLATION_X, transX, 0); + PropertyValuesHolder ty = PropertyValuesHolder.ofFloat(TRANSLATION_Y, transY, 0); + + Animator drift = ObjectAnimator.ofPropertyValuesHolder(this, tx, ty); + drift.setDuration(mMaterialExpandDuration); + drift.setStartDelay(mMaterialExpandStagger); + drift.setInterpolator(new LogDecelerateInterpolator(100, 0)); + + int rx = (int) Math.max(Math.max(width - getPivotX(), 0), getPivotX()); + int ry = (int) Math.max(Math.max(height - getPivotY(), 0), getPivotY()); + float radius = (float) Math.hypot(rx, ry); + + Animator reveal = new CircleRevealOutlineProvider((int) getPivotX(), + (int) getPivotY(), 0, radius).createRevealAnimator(this); + reveal.setDuration(mMaterialExpandDuration); + reveal.setInterpolator(new LogDecelerateInterpolator(100, 0)); + + mContent.setAlpha(0f); + Animator iconsAlpha = ObjectAnimator.ofFloat(mContent, "alpha", 0f, 1f); + iconsAlpha.setDuration(mMaterialExpandDuration); + iconsAlpha.setStartDelay(mMaterialExpandStagger); + iconsAlpha.setInterpolator(new AccelerateInterpolator(1.5f)); + + mFooter.setAlpha(0f); + Animator textAlpha = ObjectAnimator.ofFloat(mFooter, "alpha", 0f, 1f); + textAlpha.setDuration(mMaterialExpandDuration); + textAlpha.setStartDelay(mMaterialExpandStagger); + textAlpha.setInterpolator(new AccelerateInterpolator(1.5f)); + + anim.play(drift); + anim.play(iconsAlpha); + anim.play(textAlpha); + anim.play(reveal); + + mContent.setLayerType(LAYER_TYPE_HARDWARE, null); + mFooter.setLayerType(LAYER_TYPE_HARDWARE, null); + onCompleteRunnable = new Runnable() { + @Override + public void run() { + mContent.setLayerType(LAYER_TYPE_NONE, null); + mFooter.setLayerType(LAYER_TYPE_NONE, null); + mLauncher.getUserEventDispatcher().resetElapsedContainerMillis(); + } + }; + anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { Utilities.sendCustomAccessibilityEvent( @@ -649,7 +636,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList // Do not update the flag if we are in drag mode. The flag will be updated, when we // actually drop the icon. final boolean updateAnimationFlag = !mDragInProgress; - openFolderAnim.addListener(new AnimatorListenerAdapter() { + anim.addListener(new AnimatorListenerAdapter() { @SuppressLint("InlinedApi") @Override @@ -672,7 +659,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } mPageIndicator.stopAllAnimations(); - openFolderAnim.start(); + anim.start(); // Make sure the folder picks up the last drag move even if the finger doesn't move. if (mDragController.isDragging()) { @@ -680,6 +667,11 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } mContent.verifyVisibleHighResIcons(mContent.getNextPage()); + + // Notify the accessibility manager that this folder "window" has appeared and occluded + // the workspace items + sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + dragLayer.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); } public void beginExternalDrag() { @@ -692,14 +684,44 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mDragController.addDragListener(this); } - public void animateClosed() { + @Override + protected boolean isOfType(int type) { + return (type & TYPE_FOLDER) != 0; + } + + @Override + protected void handleClose(boolean animate) { + mIsOpen = false; + + if (isEditingName()) { + mFolderName.dispatchBackKey(); + } + + if (mFolderIcon != null) { + mFolderIcon.shrinkAndFadeIn(animate); + } + if (!(getParent() instanceof DragLayer)) return; + DragLayer parent = (DragLayer) getParent(); + + if (animate) { + animateClosed(); + } else { + closeComplete(false); + } + + // Notify the accessibility manager that this folder "window" has disappeared and no + // longer occludes the workspace items + parent.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + } + + private void animateClosed() { final ObjectAnimator oa = LauncherAnimUtils.ofViewAlphaAndScale(this, 0, 0.9f, 0.9f); oa.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { setLayerType(LAYER_TYPE_NONE, null); - close(true); + closeComplete(true); } @Override public void onAnimationStart(Animator animation) { @@ -715,7 +737,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList oa.start(); } - public void close(boolean wasAnimated) { + private void closeComplete(boolean wasAnimated) { // TODO: Clear all active animations. DragLayer parent = (DragLayer) getParent(); if (parent != null) { @@ -850,8 +872,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList }; public void completeDragExit() { - if (mInfo.opened) { - mLauncher.closeFolder(); + if (mIsOpen) { + close(true); mRearrangeOnClose = true; } else if (mState == STATE_ANIMATING) { mRearrangeOnClose = true; @@ -916,7 +938,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon && target != this) { replaceFolderWithFinalItem(); } - } else if (!mDragController.isDeferringDrag()) { + } else { // The drag failed, we need to return the item to the folder ShortcutInfo info = (ShortcutInfo) d.dragInfo; View icon = (mCurrentDragView != null && mCurrentDragView.getTag() == info) @@ -1309,7 +1331,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mIsExternalDrag = false; } else { currentDragView = mCurrentDragView; - if (!mDragController.isDeferringDrag()) { + // The view was never removed from this folder if we are still in the pre-drag. + if (!mDragController.isInPreDrag()) { mContent.addViewForRank(currentDragView, si, mEmptyCellRank); } } @@ -1332,7 +1355,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mItemsInvalidated = true; rearrangeChildren(); - if (!mDragController.isDeferringDrag()) { + // The ShortcutInfo was never removed if we are still in the pre-drag. + if (!mDragController.isInPreDrag()) { // Temporarily suppress the listener, as we did all the work already here. try (SuppressInfoChanges s = new SuppressInfoChanges()) { mInfo.add(si, false); @@ -1382,8 +1406,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList rearrangeChildren(); } if (getItemCount() <= 1) { - if (mInfo.opened) { - mLauncher.closeFolder(this, true); + if (mIsOpen) { + close(true); } else { replaceFolderWithFinalItem(); } @@ -1429,7 +1453,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList if (hasFocus) { startEditingFolderName(); } else { - dismissEditingName(); + mFolderName.dispatchBackKey(); } } } @@ -1442,7 +1466,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } @Override - public void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent) { + public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) { target.gridX = info.cellX; target.gridY = info.cellY; target.pageIndex = mContent.getCurrentPage(); @@ -1528,4 +1552,11 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList updateTextViewFocus(); } } + + /** + * Returns a folder which is already open or null + */ + public static Folder getOpen(Launcher launcher) { + return getOpenView(launcher, TYPE_FOLDER); + } } |