Fixing crash when dragging tasks to docked state.
- Also tweaking animation when a task is first picked up. Change-Id: Idf99c88fdb216823637e2436e54b392b661b9849
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user