diff options
26 files changed, 223 insertions, 14 deletions
diff --git a/res/drawable-hdpi/page_hover_left.9.png b/res/drawable-hdpi/page_hover_left.9.png Binary files differnew file mode 100644 index 000000000..3f11d0b33 --- /dev/null +++ b/res/drawable-hdpi/page_hover_left.9.png diff --git a/res/drawable-hdpi/page_hover_left_active.9.png b/res/drawable-hdpi/page_hover_left_active.9.png Binary files differnew file mode 100644 index 000000000..abe4c31a9 --- /dev/null +++ b/res/drawable-hdpi/page_hover_left_active.9.png diff --git a/res/drawable-hdpi/page_hover_right.9.png b/res/drawable-hdpi/page_hover_right.9.png Binary files differnew file mode 100644 index 000000000..3bcf19195 --- /dev/null +++ b/res/drawable-hdpi/page_hover_right.9.png diff --git a/res/drawable-hdpi/page_hover_right_active.9.png b/res/drawable-hdpi/page_hover_right_active.9.png Binary files differnew file mode 100644 index 000000000..101e4dc0f --- /dev/null +++ b/res/drawable-hdpi/page_hover_right_active.9.png diff --git a/res/drawable-mdpi/page_hover_left.9.png b/res/drawable-mdpi/page_hover_left.9.png Binary files differnew file mode 100644 index 000000000..2b6094cf6 --- /dev/null +++ b/res/drawable-mdpi/page_hover_left.9.png diff --git a/res/drawable-mdpi/page_hover_left_active.9.png b/res/drawable-mdpi/page_hover_left_active.9.png Binary files differnew file mode 100644 index 000000000..9eb00a282 --- /dev/null +++ b/res/drawable-mdpi/page_hover_left_active.9.png diff --git a/res/drawable-mdpi/page_hover_right.9.png b/res/drawable-mdpi/page_hover_right.9.png Binary files differnew file mode 100644 index 000000000..c2e598351 --- /dev/null +++ b/res/drawable-mdpi/page_hover_right.9.png diff --git a/res/drawable-mdpi/page_hover_right_active.9.png b/res/drawable-mdpi/page_hover_right_active.9.png Binary files differnew file mode 100644 index 000000000..d2771a1a5 --- /dev/null +++ b/res/drawable-mdpi/page_hover_right_active.9.png diff --git a/res/drawable-xhdpi/page_hover_left.9.png b/res/drawable-xhdpi/page_hover_left.9.png Binary files differnew file mode 100644 index 000000000..dbcc0abd2 --- /dev/null +++ b/res/drawable-xhdpi/page_hover_left.9.png diff --git a/res/drawable-xhdpi/page_hover_left_active.9.png b/res/drawable-xhdpi/page_hover_left_active.9.png Binary files differnew file mode 100644 index 000000000..3233efe28 --- /dev/null +++ b/res/drawable-xhdpi/page_hover_left_active.9.png diff --git a/res/drawable-xhdpi/page_hover_right.9.png b/res/drawable-xhdpi/page_hover_right.9.png Binary files differnew file mode 100644 index 000000000..d82f809bf --- /dev/null +++ b/res/drawable-xhdpi/page_hover_right.9.png diff --git a/res/drawable-xhdpi/page_hover_right_active.9.png b/res/drawable-xhdpi/page_hover_right_active.9.png Binary files differnew file mode 100644 index 000000000..819ea195c --- /dev/null +++ b/res/drawable-xhdpi/page_hover_right_active.9.png diff --git a/res/drawable-xxhdpi/page_hover_left.9.png b/res/drawable-xxhdpi/page_hover_left.9.png Binary files differnew file mode 100644 index 000000000..c81f86c02 --- /dev/null +++ b/res/drawable-xxhdpi/page_hover_left.9.png diff --git a/res/drawable-xxhdpi/page_hover_left_active.9.png b/res/drawable-xxhdpi/page_hover_left_active.9.png Binary files differnew file mode 100644 index 000000000..858a3b2ab --- /dev/null +++ b/res/drawable-xxhdpi/page_hover_left_active.9.png diff --git a/res/drawable-xxhdpi/page_hover_right.9.png b/res/drawable-xxhdpi/page_hover_right.9.png Binary files differnew file mode 100644 index 000000000..c5297703e --- /dev/null +++ b/res/drawable-xxhdpi/page_hover_right.9.png diff --git a/res/drawable-xxhdpi/page_hover_right_active.9.png b/res/drawable-xxhdpi/page_hover_right_active.9.png Binary files differnew file mode 100644 index 000000000..99005536b --- /dev/null +++ b/res/drawable-xxhdpi/page_hover_right_active.9.png diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml new file mode 100644 index 000000000..514980fe0 --- /dev/null +++ b/res/values-sw720dp-land/dimens.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> + <!-- the area at the edge of the screen that makes the workspace go left + or right while you're dragging. --> + <dimen name="scroll_zone">100dip</dimen> +</resources> diff --git a/res/values-sw720dp-port/dimens.xml b/res/values-sw720dp-port/dimens.xml new file mode 100644 index 000000000..6f594d518 --- /dev/null +++ b/res/values-sw720dp-port/dimens.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> +<!-- Workspace --> + <!-- the area at the edge of the screen that makes the workspace go left + or right while you're dragging. --> + <dimen name="scroll_zone">40dp</dimen> +</resources> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 90083c09c..041b82bf8 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -104,6 +104,10 @@ <dimen name="drop_target_drag_padding">14dp</dimen> <dimen name="drop_target_text_size">14sp</dimen> + <!-- the area at the edge of the screen that makes the workspace go left + or right while you're dragging. --> + <dimen name="scroll_zone">20dp</dimen> + <!-- When dragging an item, how much bigger (fixed dps) the dragged view should be. If 0, it will not be scaled at all. --> <dimen name="dragViewScale">12dp</dimen> diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index 3d3d57dbd..b09723de5 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -399,6 +399,10 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { mIsDragTarget = false; } + public boolean isDragTarget() { + return mIsDragTarget; + } + void setIsDragOverlapping(boolean isDragOverlapping) { if (mIsDragOverlapping != isDragOverlapping) { mIsDragOverlapping = isDragOverlapping; @@ -441,6 +445,10 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { (ParcelableSparseArray) parcelable : new ParcelableSparseArray(); } + public boolean getIsDragOverlapping() { + return mIsDragOverlapping; + } + @Override protected void onDraw(Canvas canvas) { if (!mIsDragTarget) { diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java index 1df12084c..ee9e4f211 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -42,7 +42,6 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.animation.AccelerateInterpolator; @@ -950,7 +949,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList @Override public boolean supportsAppInfoDropTarget() { - return true; + return Workspace.IS_SPRING_LOADED; } @Override diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 1eda66df2..1af2c4fbe 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1384,6 +1384,7 @@ public class Launcher extends Activity // Setup the drag controller (drop targets have to be added in reverse order in priority) dragController.setDragScoller(mWorkspace); + dragController.setScrollView(mDragLayer); dragController.setMoveTarget(mWorkspace); dragController.addDropTarget(mWorkspace); if (mSearchDropTargetBar != null) { @@ -3488,8 +3489,10 @@ public class Launcher extends Activity mState = State.APPS_SPRING_LOADED; } else if (isWidgetsViewVisible()) { mState = State.WIDGETS_SPRING_LOADED; - } else { + } else if (Workspace.IS_SPRING_LOADED) { mState = State.WORKSPACE_SPRING_LOADED; + } else { + mState = State.WORKSPACE; } } diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 0d5bbc11d..e86758a9e 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -46,13 +46,10 @@ import android.os.Parcelable; import android.util.AttributeSet; import android.util.Log; import android.util.SparseArray; -import android.view.Choreographer; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityManager; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; import android.widget.TextView; import com.android.launcher3.FolderIcon.FolderRingAnimator; @@ -93,6 +90,7 @@ public class Workspace extends PagedView Insettable, UninstallSource, AccessibilityDragSource, Stats.LaunchSourceProvider { private static final String TAG = "Launcher.Workspace"; + public static final boolean IS_SPRING_LOADED = true; private static boolean ENFORCE_DRAG_EVENT_ORDER = false; private static final int SNAP_OFF_EMPTY_SCREEN_DURATION = 400; @@ -404,8 +402,9 @@ public class Workspace extends PagedView mLauncher.onInteractionEnd(); } - public float getSpringLoadedShrinkFactor() { - return mSpringLoadedShrinkFactor; + /** Returns a scale factor to apply to workspace icons when dragging them from the workspace. */ + public float getDragShrinkFactor() { + return IS_SPRING_LOADED ? mSpringLoadedShrinkFactor : 1f; } /** @@ -2146,7 +2145,9 @@ public class Workspace extends PagedView b.recycle(); - mLauncher.enterSpringLoadedDragMode(); + if (IS_SPRING_LOADED) { + mLauncher.enterSpringLoadedDragMode(); + } } public void beginExternalDragShared(View child, DragSource source) { @@ -2196,7 +2197,9 @@ public class Workspace extends PagedView // Recycle temporary bitmaps tmpB.recycle(); - mLauncher.enterSpringLoadedDragMode(); + if (IS_SPRING_LOADED) { + mLauncher.enterSpringLoadedDragMode(); + } } public boolean transitionStateShouldAllowDrop() { @@ -2635,6 +2638,10 @@ public class Workspace extends PagedView CellLayout layout = getCurrentDropLayout(); setCurrentDropLayout(layout); setCurrentDragOverlappingLayout(layout); + + if (!workspaceInModalState() && !IS_SPRING_LOADED) { + mLauncher.getDragLayer().showPageHints(); + } } @Override @@ -2669,6 +2676,8 @@ public class Workspace extends PagedView setCurrentDragOverlappingLayout(null); mSpringLoadedDragController.cancel(); + + mLauncher.getDragLayer().hidePageHints(); } private void enfoceDragParity(String event, int update, int expectedValue) { @@ -3552,7 +3561,7 @@ public class Workspace extends PagedView @Override public boolean supportsAppInfoDropTarget() { - return true; + return IS_SPRING_LOADED; } @Override diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 13f83a743..84807cb39 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -494,6 +494,8 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc // Start the drag mLauncher.getWorkspace().beginDragShared(v, mIconLastTouchPos, this, false); + // Enter spring loaded mode + mLauncher.enterSpringLoadedDragMode(); return false; } diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java index d61117c0d..07775b615 100644 --- a/src/com/android/launcher3/dragndrop/DragController.java +++ b/src/com/android/launcher3/dragndrop/DragController.java @@ -35,7 +35,6 @@ import android.view.View; import android.view.ViewConfiguration; import android.view.inputmethod.InputMethodManager; -import com.android.launcher3.DeleteDropTarget; import com.android.launcher3.DragSource; import com.android.launcher3.DropTarget; import com.android.launcher3.ItemInfo; @@ -43,6 +42,7 @@ import com.android.launcher3.Launcher; import com.android.launcher3.PagedView; import com.android.launcher3.R; import com.android.launcher3.ShortcutInfo; +import com.android.launcher3.Utilities; import com.android.launcher3.accessibility.DragViewStateAnnouncer; import com.android.launcher3.util.Thunk; @@ -81,6 +81,7 @@ public class DragController implements DragDriver.EventListener { // temporaries to avoid gc thrash private Rect mRectTemp = new Rect(); private final int[] mCoordinatesTemp = new int[2]; + private final boolean mIsRtl; /** * Drag driver for the current drag/drop operation, or null if there is no active DND operation. @@ -97,6 +98,11 @@ public class DragController implements DragDriver.EventListener { /** Y coordinate of the down event. */ private int mMotionDownY; + /** the area at the edge of the screen that makes the workspace go left + * or right while you're dragging. + */ + private final int mScrollZone; + private DropTarget.DragObject mDragObject; /** Who can receive drop events */ @@ -107,6 +113,9 @@ public class DragController implements DragDriver.EventListener { /** The window token used as the parent for the DragView. */ private IBinder mWindowToken; + /** The view that will be scrolled when dragging to the left and right edges of the screen. */ + private View mScrollView; + private View mMoveTarget; @Thunk DragScroller mDragScroller; @@ -119,6 +128,7 @@ public class DragController implements DragDriver.EventListener { @Thunk int mLastTouch[] = new int[2]; @Thunk long mLastTouchUpTime = -1; + @Thunk int mDistanceSinceScroll = 0; private int mTmpPoint[] = new int[2]; private Rect mDragLayerRect = new Rect(); @@ -148,15 +158,19 @@ public class DragController implements DragDriver.EventListener { /** * Used to create a new DragLayer from XML. + * + * @param context The application's context. */ public DragController(Launcher launcher) { Resources r = launcher.getResources(); mLauncher = launcher; mHandler = new Handler(); + mScrollZone = r.getDimensionPixelSize(R.dimen.scroll_zone); mVelocityTracker = VelocityTracker.obtain(); mFlingToDeleteThresholdVelocity = r.getDimensionPixelSize(R.dimen.drag_flingToDeleteMinVelocity); + mIsRtl = Utilities.isRtl(r); } /** @@ -231,7 +245,7 @@ public class DragController implements DragDriver.EventListener { mDragObject = new DropTarget.DragObject(); - float finalDragViewScale = mLauncher.getWorkspace().getSpringLoadedShrinkFactor(); + float finalDragViewScale = mLauncher.getWorkspace().getDragShrinkFactor(); final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX, registrationY, 0, 0, b.getWidth(), b.getHeight(), initialDragViewScale, finalDragViewScale); @@ -502,6 +516,7 @@ public class DragController implements DragDriver.EventListener { mScrollState = SCROLL_OUTSIDE_ZONE; mScrollRunnable.setDirection(SCROLL_RIGHT); mDragScroller.onExitScrollArea(); + mLauncher.getDragLayer().onExitScrollArea(); } } @@ -515,8 +530,11 @@ public class DragController implements DragDriver.EventListener { mDragObject.y = coordinates[1]; checkTouchMove(dropTarget); + // Check if we are hovering over the scroll areas + mDistanceSinceScroll += Math.hypot(mLastTouch[0] - x, mLastTouch[1] - y); mLastTouch[0] = x; mLastTouch[1] = y; + checkScrollState(x, y); } public void forceTouchMove() { @@ -544,6 +562,36 @@ public class DragController implements DragDriver.EventListener { mLastDropTarget = dropTarget; } + @Thunk void checkScrollState(int x, int y) { + final int slop = ViewConfiguration.get(mLauncher).getScaledWindowTouchSlop(); + final int delay = mDistanceSinceScroll < slop ? RESCROLL_DELAY : SCROLL_DELAY; + final DragLayer dragLayer = mLauncher.getDragLayer(); + final int forwardDirection = mIsRtl ? SCROLL_RIGHT : SCROLL_LEFT; + final int backwardsDirection = mIsRtl ? SCROLL_LEFT : SCROLL_RIGHT; + + if (x < mScrollZone) { + if (mScrollState == SCROLL_OUTSIDE_ZONE) { + mScrollState = SCROLL_WAITING_IN_ZONE; + if (mDragScroller.onEnterScrollArea(x, y, forwardDirection)) { + dragLayer.onEnterScrollArea(forwardDirection); + mScrollRunnable.setDirection(forwardDirection); + mHandler.postDelayed(mScrollRunnable, delay); + } + } + } else if (x > mScrollView.getWidth() - mScrollZone) { + if (mScrollState == SCROLL_OUTSIDE_ZONE) { + mScrollState = SCROLL_WAITING_IN_ZONE; + if (mDragScroller.onEnterScrollArea(x, y, backwardsDirection)) { + dragLayer.onEnterScrollArea(backwardsDirection); + mScrollRunnable.setDirection(backwardsDirection); + mHandler.postDelayed(mScrollRunnable, delay); + } + } + } else { + clearScrollRunnable(); + } + } + /** * Call this from a drag source view. */ @@ -565,6 +613,13 @@ public class DragController implements DragDriver.EventListener { // Remember where the motion event started mMotionDownX = dragLayerX; mMotionDownY = dragLayerY; + + if ((dragLayerX < mScrollZone) || (dragLayerX > mScrollView.getWidth() - mScrollZone)) { + mScrollState = SCROLL_WAITING_IN_ZONE; + mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY); + } else { + mScrollState = SCROLL_OUTSIDE_ZONE; + } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: @@ -757,6 +812,13 @@ public class DragController implements DragDriver.EventListener { } } + /** + * Set which view scrolls for touch events near the edge of the screen. + */ + public void setScrollView(View v) { + mScrollView = v; + } + private class ScrollRunnable implements Runnable { private int mDirection; @@ -771,7 +833,14 @@ public class DragController implements DragDriver.EventListener { mDragScroller.scrollRight(); } mScrollState = SCROLL_OUTSIDE_ZONE; + mDistanceSinceScroll = 0; mDragScroller.onExitScrollArea(); + mLauncher.getDragLayer().onExitScrollArea(); + + if (isDragging()) { + // Check the scroll again so that we can requeue the scroller if necessary + checkScrollState(mLastTouch[0], mLastTouch[1]); + } } } diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java index 1fcb5234e..ded7fae37 100644 --- a/src/com/android/launcher3/dragndrop/DragLayer.java +++ b/src/com/android/launcher3/dragndrop/DragLayer.java @@ -102,6 +102,15 @@ public class DragLayer extends InsettableFrameLayout { // Darkening scrim private float mBackgroundAlpha = 0; + // Related to adjacent page hints + private final Rect mScrollChildPosition = new Rect(); + private boolean mInScrollArea; + private boolean mShowPageHints; + private Drawable mLeftHoverDrawable; + private Drawable mRightHoverDrawable; + private Drawable mLeftHoverDrawableActive; + private Drawable mRightHoverDrawableActive; + private boolean mBlockTouches = false; /** @@ -117,7 +126,12 @@ public class DragLayer extends InsettableFrameLayout { setMotionEventSplittingEnabled(false); setChildrenDrawingOrderEnabled(true); - mIsRtl = Utilities.isRtl(getResources()); + final Resources res = getResources(); + mLeftHoverDrawable = res.getDrawable(R.drawable.page_hover_left); + mRightHoverDrawable = res.getDrawable(R.drawable.page_hover_right); + mLeftHoverDrawableActive = res.getDrawable(R.drawable.page_hover_left_active); + mRightHoverDrawableActive = res.getDrawable(R.drawable.page_hover_right_active); + mIsRtl = Utilities.isRtl(res); } public void setup(Launcher launcher, DragController controller) { @@ -883,6 +897,29 @@ public class DragLayer extends InsettableFrameLayout { } } + void onEnterScrollArea(int direction) { + mInScrollArea = true; + invalidate(); + } + + void onExitScrollArea() { + mInScrollArea = false; + invalidate(); + } + + public void showPageHints() { + mShowPageHints = true; + Workspace workspace = mLauncher.getWorkspace(); + getDescendantRectRelativeToSelf(workspace.getChildAt(workspace.numCustomPages()), + mScrollChildPosition); + invalidate(); + } + + public void hidePageHints() { + mShowPageHints = false; + invalidate(); + } + @Override protected void dispatchDraw(Canvas canvas) { // Draw the background below children. @@ -894,6 +931,41 @@ public class DragLayer extends InsettableFrameLayout { super.dispatchDraw(canvas); } + private void drawPageHints(Canvas canvas) { + if (mShowPageHints) { + Workspace workspace = mLauncher.getWorkspace(); + int width = getMeasuredWidth(); + int page = workspace.getNextPage(); + CellLayout leftPage = (CellLayout) workspace.getChildAt(mIsRtl ? page + 1 : page - 1); + CellLayout rightPage = (CellLayout) workspace.getChildAt(mIsRtl ? page - 1 : page + 1); + + if (leftPage != null && leftPage.isDragTarget()) { + Drawable left = mInScrollArea && leftPage.getIsDragOverlapping() ? + mLeftHoverDrawableActive : mLeftHoverDrawable; + left.setBounds(0, mScrollChildPosition.top, + left.getIntrinsicWidth(), mScrollChildPosition.bottom); + left.draw(canvas); + } + if (rightPage != null && rightPage.isDragTarget()) { + Drawable right = mInScrollArea && rightPage.getIsDragOverlapping() ? + mRightHoverDrawableActive : mRightHoverDrawable; + right.setBounds(width - right.getIntrinsicWidth(), + mScrollChildPosition.top, width, mScrollChildPosition.bottom); + right.draw(canvas); + } + } + } + + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + boolean ret = super.drawChild(canvas, child, drawingTime); + + // We want to draw the page hints above the workspace, but below the drag view. + if (child instanceof Workspace) { + drawPageHints(canvas); + } + return ret; + } + public void setBackgroundAlpha(float alpha) { if (alpha != mBackgroundAlpha) { mBackgroundAlpha = alpha; |