summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJorim Jaggi <jjaggi@google.com>2014-01-16 15:30:42 -0800
committerJorim Jaggi <jjaggi@google.com>2014-02-12 22:16:51 +0100
commit55bd9725d5c0373b89f7b9bbd9547550ea3bbc63 (patch)
treed42a4d3a6fc5e53fbe36d0a8d705e92ed7d4988d
parentf180497bc303af666d2672fc268730f4ec1c771b (diff)
downloadandroid_packages_apps_Trebuchet-55bd9725d5c0373b89f7b9bbd9547550ea3bbc63.tar.gz
android_packages_apps_Trebuchet-55bd9725d5c0373b89f7b9bbd9547550ea3bbc63.tar.bz2
android_packages_apps_Trebuchet-55bd9725d5c0373b89f7b9bbd9547550ea3bbc63.zip
Implement spring-loading of folders when dragging over.
Bug: 8912132 Change-Id: Id81889a133e56461df2e20599c4b40020818ba18
-rw-r--r--src/com/android/launcher3/AppsCustomizePagedView.java2
-rw-r--r--src/com/android/launcher3/DragLayer.java35
-rw-r--r--src/com/android/launcher3/Folder.java139
-rw-r--r--src/com/android/launcher3/FolderIcon.java31
-rw-r--r--src/com/android/launcher3/Launcher.java1
5 files changed, 147 insertions, 61 deletions
diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java
index 49b12b1b1..251ae2108 100644
--- a/src/com/android/launcher3/AppsCustomizePagedView.java
+++ b/src/com/android/launcher3/AppsCustomizePagedView.java
@@ -817,7 +817,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
*/
private void endDragging(View target, boolean isFlingToDelete, boolean success) {
if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() &&
- !(target instanceof DeleteDropTarget))) {
+ !(target instanceof DeleteDropTarget) && !(target instanceof Folder))) {
// Exit spring loaded mode if we have not successfully dropped or have not handled the
// drop in Workspace
mLauncher.getWorkspace().removeExtraEmptyScreen(true, new Runnable() {
diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java
index ab0469d53..862ceca28 100644
--- a/src/com/android/launcher3/DragLayer.java
+++ b/src/com/android/launcher3/DragLayer.java
@@ -65,8 +65,6 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
private boolean mHoverPointClosesFolder = false;
private Rect mHitRect = new Rect();
- private int mWorkspaceIndex = -1;
- private int mQsbIndex = -1;
public static final int ANIMATION_END_DISAPPEAR = 0;
public static final int ANIMATION_END_FADE_OUT = 1;
public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
@@ -75,6 +73,8 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
private final Rect mInsets = new Rect();
+ private int mDragViewIndex;
+
/**
* Used to create a new DragLayer from XML.
*
@@ -771,31 +771,26 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
}
private void updateChildIndices() {
- if (mLauncher != null) {
- mWorkspaceIndex = indexOfChild(mLauncher.getWorkspace());
- mQsbIndex = indexOfChild(mLauncher.getSearchBar());
+ mDragViewIndex = -1;
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ if (getChildAt(i) instanceof DragView) {
+ mDragViewIndex = i;
+ }
}
}
@Override
protected int getChildDrawingOrder(int childCount, int i) {
- // TODO: We have turned off this custom drawing order because it now effects touch
- // dispatch order. We need to sort that issue out and then decide how to go about this.
- if (true || LauncherAppState.isScreenLandscape(getContext()) ||
- mWorkspaceIndex == -1 || mQsbIndex == -1 ||
- mLauncher.getWorkspace().isDrawingBackgroundGradient()) {
+ if (mDragViewIndex == -1) {
return i;
- }
-
- // This ensures that the workspace is drawn above the hotseat and qsb,
- // except when the workspace is drawing a background gradient, in which
- // case we want the workspace to stay behind these elements.
- if (i == mQsbIndex) {
- return mWorkspaceIndex;
- } else if (i == mWorkspaceIndex) {
- return mQsbIndex;
- } else {
+ } else if (i == mDragViewIndex) {
+ return getChildCount()-1;
+ } else if (i < mDragViewIndex) {
return i;
+ } else {
+ // i > mDragViewIndex
+ return i-1;
}
}
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index a9134e105..b4c399266 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -24,7 +24,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.PointF;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
import android.os.SystemClock;
import android.support.v4.widget.AutoScrollHelper;
import android.text.InputType;
@@ -70,6 +69,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
static final int STATE_ANIMATING = 1;
static final int STATE_OPEN = 2;
+ private static final int CLOSE_FOLDER_DELAY_MS = 150;
+
private int mExpandDuration;
protected CellLayout mContent;
private ScrollView mScrollView;
@@ -85,10 +86,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
private int mMaxCountY;
private int mMaxNumItems;
private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
- private Drawable mIconDrawable;
boolean mItemsInvalidated = false;
private ShortcutInfo mCurrentDragInfo;
private View mCurrentDragView;
+ private boolean mIsExternalDrag;
boolean mSuppressOnAdd = false;
private int[] mTargetCell = new int[2];
private int[] mPreviousTargetCell = new int[2];
@@ -242,7 +243,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mLauncher.getWorkspace().onDragStartedWithItem(v);
mLauncher.getWorkspace().beginDragShared(v, this);
- mIconDrawable = ((TextView) v).getCompoundDrawables()[1];
mCurrentDragInfo = item;
mEmptyCell[0] = item.cellX;
@@ -303,10 +303,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
return mFolderName;
}
- public Drawable getDragDrawable() {
- return mIconDrawable;
- }
-
/**
* We need to handle touch events to prevent them from falling through to the workspace below.
*/
@@ -381,7 +377,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
int count = 0;
for (int i = 0; i < children.size(); i++) {
ShortcutInfo child = (ShortcutInfo) children.get(i);
- if (!createAndAddShortcut(child)) {
+ if (createAndAddShortcut(child) == null) {
overflow.add(child);
} else {
count++;
@@ -466,11 +462,15 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
public void onAnimationEnd(Animator animation) {
mState = STATE_OPEN;
setLayerType(LAYER_TYPE_NONE, null);
- Cling cling = mLauncher.getLauncherClings().showFoldersCling();
- if (cling != null) {
- cling.bringScrimToFront();
- bringToFront();
- cling.bringToFront();
+
+ // Only show cling if we are not in the middle of a drag - this would be quite jarring.
+ if (!mDragController.isDragging()) {
+ Cling cling = mLauncher.getLauncherClings().showFoldersCling();
+ if (cling != null) {
+ cling.bringScrimToFront();
+ bringToFront();
+ cling.bringToFront();
+ }
}
setFocusOnFirstChild();
}
@@ -478,6 +478,23 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
oa.setDuration(mExpandDuration);
setLayerType(LAYER_TYPE_HARDWARE, null);
oa.start();
+
+ // Make sure the folder picks up the last drag move even if the finger doesn't move.
+ if (mDragController.isDragging()) {
+ mDragController.forceTouchMove();
+ }
+ }
+
+ public void beginExternalDrag(ShortcutInfo item) {
+ setupContentForNumItems(getItemCount() + 1);
+ findAndSetEmptyCells(item);
+
+ mCurrentDragInfo = item;
+ mEmptyCell[0] = item.cellX;
+ mEmptyCell[1] = item.cellY;
+ mIsExternalDrag = true;
+
+ mDragInProgress = true;
}
private void sendCustomAccessibilityEvent(int type, String text) {
@@ -544,7 +561,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
}
- protected boolean createAndAddShortcut(ShortcutInfo item) {
+ protected View createAndAddShortcut(ShortcutInfo item) {
final BubbleTextView textView =
(BubbleTextView) mInflater.inflate(R.layout.application, this, false);
textView.setCompoundDrawables(null,
@@ -565,7 +582,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
// This shouldn't happen, log it.
Log.e(TAG, "Folder order not properly persisted during bind");
if (!findAndSetEmptyCells(item)) {
- return false;
+ return null;
}
}
@@ -574,7 +591,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
boolean insert = false;
textView.setOnKeyListener(new FolderKeyEventListener());
mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
- return true;
+ return textView;
}
public void onDragEnter(DragObject d) {
@@ -723,6 +740,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mCurrentDragView = null;
mSuppressOnAdd = false;
mRearrangeOnClose = true;
+ mIsExternalDrag = false;
}
public void onDragExit(DragObject d) {
@@ -756,7 +774,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
success && (!beingCalledAfterUninstall || mUninstallSuccessful);
if (successfulDrop) {
- if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon) {
+ if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon && target != this) {
replaceFolderWithFinalItem();
}
} else {
@@ -1152,34 +1170,75 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
public void onDrop(DragObject d) {
- ShortcutInfo item;
- if (d.dragInfo instanceof AppInfo) {
- // Came from all apps -- make a copy
- item = ((AppInfo) d.dragInfo).makeShortcut();
- item.spanX = 1;
- item.spanY = 1;
- } else {
- item = (ShortcutInfo) d.dragInfo;
+ Runnable cleanUpRunnable = null;
+
+ // If we are coming from All Apps space, we need to remove the extra empty screen (which is
+ // normally done in Workspace#onDropExternal, as well zoom back in and close the folder.
+ if (d.dragSource != mLauncher.getWorkspace() && !(d.dragSource instanceof Folder)) {
+ cleanUpRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mLauncher.getWorkspace().removeExtraEmptyScreen(false, new Runnable() {
+ @Override
+ public void run() {
+ mLauncher.closeFolder();
+ mLauncher.exitSpringLoadedDragModeDelayed(true,
+ Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT_FOLDER_CLOSE,
+ null);
+ }
+ }, CLOSE_FOLDER_DELAY_MS, false);
+ }
+ };
}
- // Dragged from self onto self, currently this is the only path possible, however
- // we keep this as a distinct code path.
- if (item == mCurrentDragInfo) {
- ShortcutInfo si = (ShortcutInfo) mCurrentDragView.getTag();
- CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mCurrentDragView.getLayoutParams();
+
+ View currentDragView;
+ ShortcutInfo si = mCurrentDragInfo;
+ if (mIsExternalDrag) {
+ si.cellX = mEmptyCell[0];
+ si.cellY = mEmptyCell[1];
+ currentDragView = createAndAddShortcut(si);
+ } else {
+ currentDragView = mCurrentDragView;
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) currentDragView.getLayoutParams();
si.cellX = lp.cellX = mEmptyCell[0];
si.cellX = lp.cellY = mEmptyCell[1];
- mContent.addViewToCellLayout(mCurrentDragView, -1, (int)item.id, lp, true);
- if (d.dragView.hasDrawn()) {
- mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, mCurrentDragView);
- } else {
- d.deferDragViewCleanupPostAnimation = false;
- mCurrentDragView.setVisibility(VISIBLE);
+ mContent.addViewToCellLayout(currentDragView, -1, (int) si.id, lp, true);
+ }
+
+ if (d.dragView.hasDrawn()) {
+
+ // Temporarily reset the scale such that the animation target gets calculated correctly.
+ float scaleX = getScaleX();
+ float scaleY = getScaleY();
+ setScaleX(1.0f);
+ setScaleY(1.0f);
+ mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, currentDragView,
+ cleanUpRunnable, null);
+ setScaleX(scaleX);
+ setScaleY(scaleY);
+ } else {
+ d.deferDragViewCleanupPostAnimation = false;
+ currentDragView.setVisibility(VISIBLE);
+ }
+ mItemsInvalidated = true;
+ setupContentDimensions(getItemCount());
+
+ // Actually move the item in the database if it was an external drag.
+ if (mIsExternalDrag) {
+ LauncherModel.addOrMoveItemInDatabase(
+ mLauncher, si, mInfo.id, 0, si.cellX, si.cellY);
+
+ // We only need to update the locations if it doesn't get handled in #onDropCompleted.
+ if (d.dragSource != this) {
+ updateItemLocationsInDatabaseBatch();
}
- mItemsInvalidated = true;
- setupContentDimensions(getItemCount());
- mSuppressOnAdd = true;
+ mIsExternalDrag = false;
}
- mInfo.add(item);
+
+ // Temporarily suppress the listener, as we did all the work already here.
+ mSuppressOnAdd = true;
+ mInfo.add(si);
+ mSuppressOnAdd = false;
}
// This is used so the item doesn't immediately appear in the folder when added. In one case
diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java
index 644db47ac..78026f162 100644
--- a/src/com/android/launcher3/FolderIcon.java
+++ b/src/com/android/launcher3/FolderIcon.java
@@ -75,10 +75,16 @@ public class FolderIcon extends FrameLayout implements FolderListener {
// Flag as to whether or not to draw an outer ring. Currently none is designed.
public static final boolean HAS_OUTER_RING = true;
+ // Flag whether the folder should open itself when an item is dragged over is enabled.
+ public static final boolean SPRING_LOADING_ENABLED = true;
+
// The degree to which the item in the back of the stack is scaled [0...1]
// (0 means it's not scaled at all, 1 means it's scaled to nothing)
private static final float PERSPECTIVE_SCALE_FACTOR = 0.35f;
+ // Delay when drag enters until the folder opens, in miliseconds.
+ private static final int ON_OPEN_DELAY = 800;
+
public static Drawable sSharedFolderLeaveBehind = null;
private ImageView mPreviewBackground;
@@ -103,6 +109,9 @@ public class FolderIcon extends FrameLayout implements FolderListener {
private PreviewItemDrawingParams mAnimParams = new PreviewItemDrawingParams(0, 0, 0, 0);
private ArrayList<ShortcutInfo> mHiddenItems = new ArrayList<ShortcutInfo>();
+ private Alarm mOpenAlarm = new Alarm();
+ private ItemInfo mDragInfo;
+
public FolderIcon(Context context, AttributeSet attrs) {
super(context, attrs);
init();
@@ -331,11 +340,32 @@ public class FolderIcon extends FrameLayout implements FolderListener {
mFolderRingAnimator.setCellLayout(layout);
mFolderRingAnimator.animateToAcceptState();
layout.showFolderAccept(mFolderRingAnimator);
+ mOpenAlarm.setOnAlarmListener(mOnOpenListener);
+ if (SPRING_LOADING_ENABLED) {
+ mOpenAlarm.setAlarm(ON_OPEN_DELAY);
+ }
+ mDragInfo = (ItemInfo) dragInfo;
}
public void onDragOver(Object dragInfo) {
}
+ OnAlarmListener mOnOpenListener = new OnAlarmListener() {
+ public void onAlarm(Alarm alarm) {
+ ShortcutInfo item;
+ if (mDragInfo instanceof AppInfo) {
+ // Came from all apps -- make a copy.
+ item = ((AppInfo) mDragInfo).makeShortcut();
+ item.spanX = 1;
+ item.spanY = 1;
+ } else {
+ item = (ShortcutInfo) mDragInfo;
+ }
+ mFolder.beginExternalDrag(item);
+ mLauncher.openFolder(FolderIcon.this);
+ }
+ };
+
public void performCreateAnimation(final ShortcutInfo destInfo, final View destView,
final ShortcutInfo srcInfo, final DragView srcView, Rect dstRect,
float scaleRelativeToDragLayer, Runnable postAnimationRunnable) {
@@ -371,6 +401,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
public void onDragExit() {
mFolderRingAnimator.animateToNaturalState();
+ mOpenAlarm.cancelAlarm();
}
private void onDrop(final ShortcutInfo item, DragView animateView, Rect finalRect,
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index c57d32e31..c87f9e2f0 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -210,6 +210,7 @@ public class Launcher extends Activity
static final int APPWIDGET_HOST_ID = 1024;
public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300;
+ public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT_FOLDER_CLOSE = 400;
private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500;
private static final Object sLock = new Object();