summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/folder/Folder.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3/folder/Folder.java')
-rw-r--r--src/com/android/launcher3/folder/Folder.java285
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);
+ }
}