From 4165d336b6cd69715eda7fbdfd272a878097170e Mon Sep 17 00:00:00 2001 From: Winson Date: Sat, 10 Oct 2015 14:40:35 -0700 Subject: [PATCH] Fixing crash when dragging tasks to docked state. - Also tweaking animation when a task is first picked up. Change-Id: Idf99c88fdb216823637e2436e54b392b661b9849 --- .../systemui/recents/model/TaskStack.java | 32 +++-- .../systemui/recents/views/RecentsView.java | 62 ++++++--- .../views/RecentsViewTouchHandler.java | 130 ++++++++++-------- .../systemui/recents/views/TaskView.java | 7 +- 4 files changed, 141 insertions(+), 90 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java index 57a81985b36b4..48a12ed5a0255 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java @@ -183,16 +183,18 @@ public class TaskStack { public enum DockState { - LEFT(DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, - new RectF(0, 0, 0.25f, 1), new RectF(0, 0, 0.35f, 1), new RectF(0.65f, 0, 1, 1)), - TOP(DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, - new RectF(0, 0, 1, 0.25f), new RectF(0, 0, 1, 0.35f), new RectF(0, 0.65f, 1, 1)), - RIGHT(DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, - new RectF(0.75f, 0, 1, 1), new RectF(0.65f, 0, 1, 1), new RectF(0, 0, 0.35f, 1)), - BOTTOM(DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, - new RectF(0, 0.75f, 1, 1), new RectF(0, 0.65f, 1, 1), new RectF(0, 0, 1, 0.35f)); + NONE(-1, 96, null, null, null), + LEFT(DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, 192, + new RectF(0, 0, 0.3f, 1), new RectF(0, 0, 0.3f, 1), new RectF(0.7f, 0, 1, 1)), + TOP(DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, 192, + new RectF(0, 0, 1, 0.3f), new RectF(0, 0, 1, 0.3f), new RectF(0, 0.7f, 1, 1)), + RIGHT(DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, 192, + new RectF(0.7f, 0, 1, 1), new RectF(0.7f, 0, 1, 1), new RectF(0, 0, 0.3f, 1)), + BOTTOM(DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, 192, + new RectF(0, 0.7f, 1, 1), new RectF(0, 0.7f, 1, 1), new RectF(0, 0, 1, 0.3f)); public final int createMode; + public final int dockAreaAlpha; private final RectF touchArea; private final RectF dockArea; private final RectF stackArea; @@ -202,8 +204,10 @@ public class TaskStack { * @param touchArea the area in which touch will initiate this dock state * @param stackArea the area for the stack if a task is docked */ - DockState(int createMode, RectF touchArea, RectF dockArea, RectF stackArea) { + DockState(int createMode, int dockAreaAlpha, RectF touchArea, RectF dockArea, + RectF stackArea) { this.createMode = createMode; + this.dockAreaAlpha = dockAreaAlpha; this.touchArea = touchArea; this.dockArea = dockArea; this.stackArea = stackArea; @@ -232,9 +236,13 @@ public class TaskStack { /** * Returns the stack bounds with the given {@param width} and {@param height}. */ - public Rect getStackBounds(int width, int height) { - return new Rect((int) (stackArea.left * width), (int) (stackArea.top * height), - (int) (stackArea.right * width), (int) (stackArea.bottom * height)); + public Rect getStackBounds(Rect stackRect) { + int width = stackRect.width(); + int height = stackRect.height(); + return new Rect((int) (stackRect.left + stackArea.left * width), + (int) (stackRect.top + stackArea.top * height), + (int) (stackRect.left + (stackArea.right - stackArea.left) * width), + (int) (stackRect.top + (stackArea.bottom - stackArea.top) * height)); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index 15bd2326b95c7..f12042178f139 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -16,6 +16,8 @@ package com.android.systemui.recents.views; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.app.ActivityManager; import android.app.ActivityOptions; import android.content.Context; @@ -23,6 +25,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.IRemoteCallback; import android.os.RemoteException; @@ -89,6 +92,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV RecentsViewTouchHandler mTouchHandler; DragView mDragView; ColorDrawable mDockRegionOverlay; + ObjectAnimator mDockRegionOverlayAnimator; Interpolator mFastOutSlowInInterpolator; @@ -114,8 +118,9 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, com.android.internal.R.interpolator.fast_out_slow_in); mTouchHandler = new RecentsViewTouchHandler(this); - mDockRegionOverlay = new ColorDrawable(0x66000000); + mDockRegionOverlay = new ColorDrawable(0xFFffffff); mDockRegionOverlay.setAlpha(0); + mDockRegionOverlay.setCallback(this); } /** Sets the callbacks */ @@ -383,6 +388,11 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV } } + @Override + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mDockRegionOverlay; + } + /** Notifies each task view of the user interaction. */ public void onUserInteraction() { // Get the first stack view @@ -764,19 +774,12 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV // Add the drag view mDragView = event.dragView; addView(mDragView); + + updateDockRegion(TaskStack.DockState.NONE); } public final void onBusEvent(DragDockStateChangedEvent event) { - // Update the task stack positions, and then - if (event.dockState != null) { - // Draw an overlay on the bounds of the dock task - mDockRegionOverlay.setBounds( - event.dockState.getDockedBounds(getMeasuredWidth(), getMeasuredHeight())); - mDockRegionOverlay.setAlpha(255); - } else { - mDockRegionOverlay.setAlpha(0); - } - invalidate(); + updateDockRegion(event.dockState); } public final void onBusEvent(final DragEndEvent event) { @@ -791,7 +794,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV invalidate(); // Dock the new task if we are hovering over a valid dock state - if (event.dockState != null) { + if (event.dockState != TaskStack.DockState.NONE) { SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy(); ssp.setTaskResizeable(event.task.key.id); ssp.dockTask(event.task.key.id, event.dockState.createMode); @@ -799,22 +802,49 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV } } }); - if (event.dockState == null) { + if (event.dockState == TaskStack.DockState.NONE) { // Animate the alpha back to what it was before Rect taskBounds = mTaskStackView.getStackAlgorithm().getUntransformedTaskViewBounds(); int left = taskBounds.left + (int) ((1f - event.taskView.getScaleX()) * taskBounds.width()) / 2; int top = taskBounds.top + (int) ((1f - event.taskView.getScaleY()) * taskBounds.height()) / 2; event.dragView.animate() - .alpha(1f) + .scaleX(1f) + .scaleY(1f) .translationX(left + event.taskView.getTranslationX()) .translationY(top + event.taskView.getTranslationY()) .setDuration(175) - .setInterpolator(new AccelerateInterpolator(1.5f)) + .setInterpolator(mFastOutSlowInInterpolator) .withEndAction(event.postAnimationTrigger.decrementAsRunnable()) - .withLayer() .start(); + + // Animate the overlay alpha back to 0 + updateDockRegionAlpha(0); } else { event.postAnimationTrigger.decrement(); } } + + /** + * Updates the dock region to match the specified dock state. + */ + private void updateDockRegion(TaskStack.DockState dockState) { + TaskStack.DockState boundsDockState = dockState; + if (dockState == TaskStack.DockState.NONE) { + // If the dock state is null, then use the bounds of the preferred dock state for this + // orientation + boundsDockState = mTouchHandler.getPreferredDockStateForCurrentOrientation(); + } + mDockRegionOverlay.setBounds( + boundsDockState.getDockedBounds(getMeasuredWidth(), getMeasuredHeight())); + updateDockRegionAlpha(dockState.dockAreaAlpha); + } + + private void updateDockRegionAlpha(int alpha) { + if (mDockRegionOverlayAnimator != null) { + mDockRegionOverlayAnimator.cancel(); + } + mDockRegionOverlayAnimator = ObjectAnimator.ofInt(mDockRegionOverlay, "alpha", alpha); + mDockRegionOverlayAnimator.setDuration(150); + mDockRegionOverlayAnimator.start(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java index 8dea0cd1ab381..f0b6cbda1954d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java @@ -36,7 +36,8 @@ class DockRegion { TaskStack.DockState.LEFT, TaskStack.DockState.RIGHT }; public static TaskStack.DockState[] PORTRAIT = { - TaskStack.DockState.TOP, TaskStack.DockState.BOTTOM + // We only allow docking to the top for now + TaskStack.DockState.TOP }; } @@ -53,75 +54,30 @@ class RecentsViewTouchHandler { private Point mDownPos = new Point(); private boolean mDragging; - private TaskStack.DockState mLastDockState; + private TaskStack.DockState mLastDockState = TaskStack.DockState.NONE; public RecentsViewTouchHandler(RecentsView rv) { mRv = rv; } + public TaskStack.DockState getPreferredDockStateForCurrentOrientation() { + boolean isLandscape = mRv.getResources().getConfiguration().orientation == + Configuration.ORIENTATION_LANDSCAPE; + TaskStack.DockState[] dockStates = isLandscape ? + DockRegion.LANDSCAPE : DockRegion.PORTRAIT; + return dockStates[0]; + } + /** Touch preprocessing for handling below */ public boolean onInterceptTouchEvent(MotionEvent ev) { - int action = ev.getAction(); - switch (action & MotionEvent.ACTION_MASK) { - case MotionEvent.ACTION_DOWN: - mDownPos.set((int) ev.getX(), (int) ev.getY()); - break; - } + handleTouchEvent(ev); return mDragging; } /** Handles touch events once we have intercepted them */ public boolean onTouchEvent(MotionEvent ev) { - if (!mDragging) return false; - - boolean isLandscape = mRv.getResources().getConfiguration().orientation == - Configuration.ORIENTATION_LANDSCAPE; - int action = ev.getAction(); - switch (action & MotionEvent.ACTION_MASK) { - case MotionEvent.ACTION_DOWN: - mDownPos.set((int) ev.getX(), (int) ev.getY()); - break; - case MotionEvent.ACTION_MOVE: { - int width = mRv.getMeasuredWidth(); - int height = mRv.getMeasuredHeight(); - float evX = ev.getX(); - float evY = ev.getY(); - float x = evX - mDragView.getTopLeftOffset().x; - float y = evY - mDragView.getTopLeftOffset().y; - - // Update the dock state - TaskStack.DockState[] dockStates = isLandscape ? - DockRegion.LANDSCAPE : DockRegion.PORTRAIT; - TaskStack.DockState foundDockState = null; - for (int i = 0; i < dockStates.length; i++) { - TaskStack.DockState state = dockStates[i]; - if (state.touchAreaContainsPoint(width, height, evX, evY)) { - foundDockState = state; - break; - } - } - if (mLastDockState != foundDockState) { - mLastDockState = foundDockState; - EventBus.getDefault().send(new DragDockStateChangedEvent(mDragTask, - foundDockState)); - } - - mDragView.setTranslationX(x); - mDragView.setTranslationY(y); - break; - } - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: { - ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger( - mRv.getContext(), null, null, null); - postAnimationTrigger.increment(); - EventBus.getDefault().send(new DragEndEvent(mDragTask, mTaskView, mDragView, - mLastDockState, postAnimationTrigger)); - postAnimationTrigger.decrement(); - break; - } - } - return true; + handleTouchEvent(ev); + return mDragging; } /**** Events ****/ @@ -144,6 +100,62 @@ class RecentsViewTouchHandler { mDragTask = null; mTaskView = null; mDragView = null; - mLastDockState = null; + mLastDockState = TaskStack.DockState.NONE; + } + + /** + * Handles dragging touch events + * @param ev + */ + private void handleTouchEvent(MotionEvent ev) { + boolean isLandscape = mRv.getResources().getConfiguration().orientation == + Configuration.ORIENTATION_LANDSCAPE; + int action = ev.getAction(); + switch (action & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: + mDownPos.set((int) ev.getX(), (int) ev.getY()); + break; + case MotionEvent.ACTION_MOVE: { + if (mDragging) { + int width = mRv.getMeasuredWidth(); + int height = mRv.getMeasuredHeight(); + float evX = ev.getX(); + float evY = ev.getY(); + float x = evX - mDragView.getTopLeftOffset().x; + float y = evY - mDragView.getTopLeftOffset().y; + + // Update the dock state + TaskStack.DockState[] dockStates = isLandscape ? + DockRegion.LANDSCAPE : DockRegion.PORTRAIT; + TaskStack.DockState foundDockState = TaskStack.DockState.NONE; + for (int i = 0; i < dockStates.length; i++) { + TaskStack.DockState state = dockStates[i]; + if (state.touchAreaContainsPoint(width, height, evX, evY)) { + foundDockState = state; + break; + } + } + if (mLastDockState != foundDockState) { + mLastDockState = foundDockState; + EventBus.getDefault().send(new DragDockStateChangedEvent(mDragTask, + foundDockState)); + } + + mDragView.setTranslationX(x); + mDragView.setTranslationY(y); + } + break; + } + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: { + ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger( + mRv.getContext(), null, null, null); + postAnimationTrigger.increment(); + EventBus.getDefault().send(new DragEndEvent(mDragTask, mTaskView, mDragView, + mLastDockState, postAnimationTrigger)); + postAnimationTrigger.decrement(); + break; + } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java index 9d08ee907626f..d2003bf331acf 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -807,15 +807,16 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, dragView.setElevation(getElevation()); dragView.setTranslationZ(getTranslationZ()); dragView.animate() - .alpha(0.75f) + .scaleX(1.05f) + .scaleY(1.05f) .setDuration(175) - .setInterpolator(new AccelerateInterpolator(1.5f)) - .withLayer() + .setInterpolator(mFastOutSlowInInterpolator) .start(); } @Override public void onViewDetachedFromWindow(View v) { + // Do nothing } }); EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);