Improving drag and drop animations.
- Expanding drop targets to indicate the size of the to-be docked window
- Fixing animation when dropping task
- Fixing drag view z order
- Fixes issue where the dock divider position in WM is not exact
- Requiring user to move the slop distance before accepting drops
Change-Id: I2f6eab504db7126c19e0c680629e89a39e7512e3
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 67135d5..61780f8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -139,7 +139,7 @@
} else {
// In portrait, the search bar appears on the top (which already has the inset)
int top = searchBarBounds.isEmpty() ? topInset : 0;
- taskStackBounds.set(windowBounds.left, searchBarBounds.bottom + top,
+ taskStackBounds.set(windowBounds.left, windowBounds.top + searchBarBounds.bottom + top,
windowBounds.right - rightInset, windowBounds.bottom);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java
index 21321f2..b85ddac 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java
@@ -25,6 +25,7 @@
*/
public class DragDropTargetChangedEvent extends EventBus.Event {
+ // The task that is currently being dragged
public final Task task;
public final DropTarget dropTarget;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index f9e825a..e05a6f8f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -307,11 +307,12 @@
}
/** Docks a task to the side of the screen and starts it. */
- public void startTaskInDockedMode(int taskId, int createMode) {
+ public void startTaskInDockedMode(Context context, int taskId, int createMode) {
if (mIam == null) return;
try {
- final ActivityOptions options = ActivityOptions.makeBasic();
+ // TODO: Determine what animation we want for the incoming task
+ final ActivityOptions options = ActivityOptions.makeCustomAnimation(context, 0, 0);
options.setDockCreateMode(createMode);
options.setLaunchStackId(DOCKED_STACK_ID);
mIam.startActivityFromRecents(taskId, options.toBundle());
@@ -917,6 +918,18 @@
}
}
+ /**
+ * Calculates the size of the dock divider in the current orientation.
+ */
+ public int getDockedDividerSize(Context context) {
+ Resources res = context.getResources();
+ int dividerWindowWidth = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_divider_thickness);
+ int dividerInsets = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_divider_insets);
+ return dividerWindowWidth - 2 * dividerInsets;
+ }
+
public void requestKeyboardShortcuts(Context context, KeyboardShortcutsReceiver receiver) {
mWm.requestAppKeyboardShortcuts(receiver);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
index 2bf2ccb..33f116b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -18,13 +18,43 @@
import android.animation.Animator;
import android.graphics.Color;
+import android.graphics.Rect;
import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.util.IntProperty;
+import android.util.Property;
import android.view.View;
import android.view.ViewParent;
/* Common code */
public class Utilities {
+ public static final Property<Drawable, Integer> DRAWABLE_ALPHA =
+ new IntProperty<Drawable>("drawableAlpha") {
+ @Override
+ public void setValue(Drawable object, int alpha) {
+ object.setAlpha(alpha);
+ }
+
+ @Override
+ public Integer get(Drawable object) {
+ return object.getAlpha();
+ }
+ };
+
+ public static final Property<Drawable, Rect> DRAWABLE_RECT =
+ new Property<Drawable, Rect>(Rect.class, "drawableBounds") {
+ @Override
+ public void set(Drawable object, Rect bounds) {
+ object.setBounds(bounds);
+ }
+
+ @Override
+ public Rect get(Drawable object) {
+ return object.getBounds();
+ }
+ };
+
/**
* @return the first parent walking up the view hierarchy that has the given class type.
*
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 856200d..e97188b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -16,16 +16,25 @@
package com.android.systemui.recents.model;
+import android.animation.Animator;
+import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.RectEvaluator;
import android.content.ComponentName;
import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.util.SparseArray;
+import android.view.animation.Interpolator;
+import com.android.internal.policy.DockedDividerUtils;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.misc.NamedCounter;
import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -44,6 +53,11 @@
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.view.WindowManager.DOCKED_LEFT;
+import static android.view.WindowManager.DOCKED_RIGHT;
+import static android.view.WindowManager.DOCKED_TOP;
+import static android.view.WindowManager.DOCKED_BOTTOM;
+import static android.view.WindowManager.DOCKED_INVALID;
/**
@@ -229,30 +243,36 @@
public static class DockState implements DropTarget {
private static final int DOCK_AREA_ALPHA = 192;
- public static final DockState NONE = new DockState(-1, 96, null, null);
- public static final DockState LEFT = new DockState(
+ public static final DockState NONE = new DockState(DOCKED_INVALID, -1, 80, null, null, null);
+ public static final DockState LEFT = new DockState(DOCKED_LEFT,
DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA,
- new RectF(0, 0, 0.15f, 1), new RectF(0, 0, 0.15f, 1));
- public static final DockState TOP = new DockState(
+ new RectF(0, 0, 0.125f, 1), new RectF(0, 0, 0.125f, 1),
+ new RectF(0, 0, 0.5f, 1));
+ public static final DockState TOP = new DockState(DOCKED_TOP,
DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA,
- new RectF(0, 0, 1, 0.15f), new RectF(0, 0, 1, 0.15f));
- public static final DockState RIGHT = new DockState(
+ new RectF(0, 0, 1, 0.125f), new RectF(0, 0, 1, 0.125f),
+ new RectF(0, 0, 1, 0.5f));
+ public static final DockState RIGHT = new DockState(DOCKED_RIGHT,
DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA,
- new RectF(0.85f, 0, 1, 1), new RectF(0.85f, 0, 1, 1));
- public static final DockState BOTTOM = new DockState(
+ new RectF(0.875f, 0, 1, 1), new RectF(0.875f, 0, 1, 1),
+ new RectF(0.5f, 0, 1, 1));
+ public static final DockState BOTTOM = new DockState(DOCKED_BOTTOM,
DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA,
- new RectF(0, 0.85f, 1, 1), new RectF(0, 0.85f, 1, 1));
+ new RectF(0, 0.875f, 1, 1), new RectF(0, 0.875f, 1, 1),
+ new RectF(0, 0.5f, 1, 1));
@Override
- public boolean acceptsDrop(int x, int y, int width, int height) {
- return touchAreaContainsPoint(width, height, x, y);
+ public boolean acceptsDrop(int x, int y, int width, int height, boolean isCurrentTarget) {
+ return isCurrentTarget
+ ? areaContainsPoint(expandedTouchDockArea, width, height, x, y)
+ : areaContainsPoint(touchArea, width, height, x, y);
}
// Represents the view state of this dock state
public class ViewState {
public final int dockAreaAlpha;
public final ColorDrawable dockAreaOverlay;
- private ObjectAnimator dockAreaOverlayAnimator;
+ private AnimatorSet dockAreaOverlayAnimator;
private ViewState(int alpha) {
dockAreaAlpha = alpha;
@@ -261,56 +281,130 @@
}
/**
- * Creates a new alpha animation.
+ * Creates a new bounds and alpha animation.
*/
- public void startAlphaAnimation(int alpha, int duration) {
+ public void startAnimation(Rect bounds, int alpha, int duration,
+ Interpolator interpolator, boolean animateAlpha, boolean animateBounds) {
+ if (dockAreaOverlayAnimator != null) {
+ dockAreaOverlayAnimator.cancel();
+ }
+
+ ArrayList<Animator> animators = new ArrayList<>();
if (dockAreaOverlay.getAlpha() != alpha) {
- if (dockAreaOverlayAnimator != null) {
- dockAreaOverlayAnimator.cancel();
+ if (animateAlpha) {
+ animators.add(ObjectAnimator.ofInt(dockAreaOverlay,
+ Utilities.DRAWABLE_ALPHA, dockAreaOverlay.getAlpha(), alpha));
+ } else {
+ dockAreaOverlay.setAlpha(alpha);
}
- dockAreaOverlayAnimator = ObjectAnimator.ofInt(dockAreaOverlay, "alpha", alpha);
+ }
+ if (bounds != null && !dockAreaOverlay.getBounds().equals(bounds)) {
+ if (animateBounds) {
+ PropertyValuesHolder prop = PropertyValuesHolder.ofObject(
+ Utilities.DRAWABLE_RECT, new RectEvaluator(new Rect()),
+ dockAreaOverlay.getBounds(), bounds);
+ animators.add(ObjectAnimator.ofPropertyValuesHolder(dockAreaOverlay, prop));
+ } else {
+ dockAreaOverlay.setBounds(bounds);
+ }
+ }
+ if (!animators.isEmpty()) {
+ dockAreaOverlayAnimator = new AnimatorSet();
+ dockAreaOverlayAnimator.playTogether(animators);
dockAreaOverlayAnimator.setDuration(duration);
+ dockAreaOverlayAnimator.setInterpolator(interpolator);
dockAreaOverlayAnimator.start();
}
}
}
+ public final int dockSide;
public final int createMode;
public final ViewState viewState;
- private final RectF dockArea;
private final RectF touchArea;
+ private final RectF dockArea;
+ private final RectF expandedTouchDockArea;
/**
* @param createMode used to pass to ActivityManager to dock the task
* @param touchArea the area in which touch will initiate this dock state
* @param dockArea the visible dock area
+ * @param expandedTouchDockArea the areain which touch will continue to dock after entering
+ * the initial touch area. This is also the new dock area to
+ * draw.
*/
- DockState(int createMode, int dockAreaAlpha, RectF touchArea, RectF dockArea) {
+ DockState(int dockSide, int createMode, int dockAreaAlpha, RectF touchArea, RectF dockArea,
+ RectF expandedTouchDockArea) {
+ this.dockSide = dockSide;
this.createMode = createMode;
this.viewState = new ViewState(dockAreaAlpha);
this.dockArea = dockArea;
this.touchArea = touchArea;
+ this.expandedTouchDockArea = expandedTouchDockArea;
}
/**
- * Returns whether {@param x} and {@param y} are contained in the touch area scaled to the
+ * Returns whether {@param x} and {@param y} are contained in the area scaled to the
* given {@param width} and {@param height}.
*/
- public boolean touchAreaContainsPoint(int width, int height, float x, float y) {
- int left = (int) (touchArea.left * width);
- int top = (int) (touchArea.top * height);
- int right = (int) (touchArea.right * width);
- int bottom = (int) (touchArea.bottom * height);
+ public boolean areaContainsPoint(RectF area, int width, int height, float x, float y) {
+ int left = (int) (area.left * width);
+ int top = (int) (area.top * height);
+ int right = (int) (area.right * width);
+ int bottom = (int) (area.bottom * height);
return x >= left && y >= top && x <= right && y <= bottom;
}
/**
* Returns the docked task bounds with the given {@param width} and {@param height}.
*/
- public Rect getDockedBounds(int width, int height) {
+ public Rect getPreDockedBounds(int width, int height) {
return new Rect((int) (dockArea.left * width), (int) (dockArea.top * height),
(int) (dockArea.right * width), (int) (dockArea.bottom * height));
}
+
+ /**
+ * Returns the expanded docked task bounds with the given {@param width} and
+ * {@param height}.
+ */
+ public Rect getDockedBounds(int width, int height, int dividerSize, Rect insets,
+ Resources res) {
+ // Calculate the docked task bounds
+ boolean isHorizontalDivision =
+ res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
+ int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision,
+ insets, width, height, dividerSize);
+ Rect newWindowBounds = new Rect();
+ DockedDividerUtils.calculateBoundsForPosition(position, dockSide, newWindowBounds,
+ width, height, dividerSize);
+ return newWindowBounds;
+ }
+
+ /**
+ * Returns the task stack bounds with the given {@param width} and
+ * {@param height}.
+ */
+ public Rect getDockedTaskStackBounds(int width, int height, int dividerSize, Rect insets,
+ Resources res) {
+ RecentsConfiguration config = Recents.getConfiguration();
+
+ // Calculate the inverse docked task bounds
+ boolean isHorizontalDivision =
+ res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
+ int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision,
+ insets, width, height, dividerSize);
+ Rect newWindowBounds = new Rect();
+ DockedDividerUtils.calculateBoundsForPosition(position,
+ DockedDividerUtils.invertDockSide(dockSide), newWindowBounds, width, height,
+ dividerSize);
+
+ // Calculate the task stack bounds from the new window bounds
+ Rect searchBarSpaceBounds = new Rect();
+ Rect taskStackBounds = new Rect();
+ config.getTaskStackBounds(newWindowBounds, insets.top, insets.right,
+ searchBarSpaceBounds, taskStackBounds);
+ return taskStackBounds;
+ }
}
// A comparator that sorts tasks by their last active time
@@ -446,6 +540,7 @@
mCb.onHistoryTaskRemoved(this, t);
}
}
+ mRawTaskList.remove(t);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/DropTarget.java b/packages/SystemUI/src/com/android/systemui/recents/views/DropTarget.java
index 8ae00a7..3ad368c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/DropTarget.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/DropTarget.java
@@ -25,5 +25,5 @@
* Returns whether this target can accept this drop. The x,y are relative to the top level
* RecentsView, and the width/height are of the RecentsView.
*/
- boolean acceptsDrop(int x, int y, int width, int height);
+ boolean acceptsDrop(int x, int y, int width, int height, boolean isCurrentTarget);
}
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 e28e2b3..d71bdbe 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -19,6 +19,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -63,6 +64,7 @@
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.stackdivider.WindowManagerProxy;
import com.android.systemui.statusbar.FlingAnimationUtils;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
import java.util.ArrayList;
import java.util.Collections;
@@ -76,8 +78,7 @@
*/
public class RecentsView extends FrameLayout {
- private static final String TAG = "RecentsView";
- private static final boolean DEBUG = false;
+ private static final int DOCK_AREA_OVERLAY_TRANSITION_DURATION = 135;
private final Handler mHandler;
@@ -89,6 +90,7 @@
private boolean mAwaitingFirstLayout = true;
private boolean mLastTaskLaunchedWasFreeform;
private Rect mSystemInsets = new Rect();
+ private int mDividerSize;
private RecentsTransitionHelper mTransitionHelper;
private RecentsViewTouchHandler mTouchHandler;
@@ -118,12 +120,15 @@
public RecentsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setWillNotDraw(false);
+
+ SystemServicesProxy ssp = Recents.getSystemServices();
mHandler = new Handler();
mTransitionHelper = new RecentsTransitionHelper(getContext(), mHandler);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_linear_in);
+ mDividerSize = ssp.getDockedDividerSize(context);
mTouchHandler = new RecentsViewTouchHandler(this);
mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f);
@@ -470,52 +475,77 @@
public final void onBusEvent(DragStartEvent event) {
updateVisibleDockRegions(mTouchHandler.getDockStatesForCurrentOrientation(),
- TaskStack.DockState.NONE.viewState.dockAreaAlpha);
+ true /* isDefaultDockState */, TaskStack.DockState.NONE.viewState.dockAreaAlpha,
+ true /* animateAlpha */, false /* animateBounds */);
}
public final void onBusEvent(DragDropTargetChangedEvent event) {
if (event.dropTarget == null || !(event.dropTarget instanceof TaskStack.DockState)) {
updateVisibleDockRegions(mTouchHandler.getDockStatesForCurrentOrientation(),
- TaskStack.DockState.NONE.viewState.dockAreaAlpha);
+ true /* isDefaultDockState */, TaskStack.DockState.NONE.viewState.dockAreaAlpha,
+ true /* animateAlpha */, true /* animateBounds */);
} else {
final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget;
- updateVisibleDockRegions(new TaskStack.DockState[] {dockState}, -1);
+ updateVisibleDockRegions(new TaskStack.DockState[] {dockState},
+ false /* isDefaultDockState */, -1, true /* animateAlpha */,
+ true /* animateBounds */);
}
}
public final void onBusEvent(final DragEndEvent event) {
- // Animate the overlay alpha back to 0
- updateVisibleDockRegions(null, -1);
-
// Handle the case where we drop onto a dock region
if (event.dropTarget instanceof TaskStack.DockState) {
- TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget;
+ final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget;
+
+ // Hide the dock region
+ updateVisibleDockRegions(null, false /* isDefaultDockState */, -1,
+ false /* animateAlpha */, false /* animateBounds */);
+
TaskStackLayoutAlgorithm stackLayout = mTaskStackView.getStackAlgorithm();
TaskStackViewScroller stackScroller = mTaskStackView.getScroller();
TaskViewTransform tmpTransform = new TaskViewTransform();
+ // We translated the view but we need to animate it back from the current layout-space
+ // rect to its final layout-space rect
+ int x = (int) event.taskView.getTranslationX();
+ int y = (int) event.taskView.getTranslationY();
+ Rect taskViewRect = new Rect(event.taskView.getLeft(), event.taskView.getTop(),
+ event.taskView.getRight(), event.taskView.getBottom());
+ taskViewRect.offset(x, y);
+ event.taskView.setTranslationX(0);
+ event.taskView.setTranslationY(0);
+ event.taskView.setLeftTopRightBottom(taskViewRect.left, taskViewRect.top,
+ taskViewRect.right, taskViewRect.bottom);
+
// Remove the task view after it is docked
+ mTaskStackView.updateLayout(false /* boundScroll */);
stackLayout.getStackTransform(event.task, stackScroller.getStackScroll(), tmpTransform,
null);
- tmpTransform.scale = event.taskView.getScaleX();
- tmpTransform.rect.offset(event.taskView.getTranslationX(),
- event.taskView.getTranslationY());
+ tmpTransform.alpha = 0;
+ tmpTransform.scale = 1f;
+ tmpTransform.rect.set(taskViewRect);
mTaskStackView.updateTaskViewToTransform(event.taskView, tmpTransform,
- new TaskViewAnimation(150, mFastOutLinearInInterpolator,
+ new TaskViewAnimation(125, PhoneStatusBar.ALPHA_OUT,
new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
+ // Dock the task and launch it
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ ssp.startTaskInDockedMode(getContext(), event.task.key.id,
+ dockState.createMode);
+ launchTask(event.task, null, INVALID_STACK_ID);
+
mTaskStackView.getStack().removeTask(event.task);
}
}));
- // Dock the task and launch it
- SystemServicesProxy ssp = Recents.getSystemServices();
- ssp.startTaskInDockedMode(event.task.key.id, dockState.createMode);
- launchTask(event.task, null, INVALID_STACK_ID);
MetricsLogger.action(mContext,
MetricsLogger.ACTION_WINDOW_DOCK_DRAG_DROP);
+ } else {
+ // Animate the overlay alpha back to 0
+ updateVisibleDockRegions(null, true /* isDefaultDockState */, -1,
+ true /* animateAlpha */, false /* animateBounds */);
}
}
@@ -638,7 +668,9 @@
/**
* Updates the dock region to match the specified dock state.
*/
- private void updateVisibleDockRegions(TaskStack.DockState[] newDockStates, int overrideAlpha) {
+ private void updateVisibleDockRegions(TaskStack.DockState[] newDockStates,
+ boolean isDefaultDockState, int overrideAlpha, boolean animateAlpha,
+ boolean animateBounds) {
ArraySet<TaskStack.DockState> newDockStatesSet = new ArraySet<>();
if (newDockStates != null) {
Collections.addAll(newDockStatesSet, newDockStates);
@@ -647,14 +679,21 @@
TaskStack.DockState.ViewState viewState = dockState.viewState;
if (newDockStates == null || !newDockStatesSet.contains(dockState)) {
// This is no longer visible, so hide it
- viewState.startAlphaAnimation(0, 150);
+ viewState.startAnimation(null, 0, DOCK_AREA_OVERLAY_TRANSITION_DURATION,
+ PhoneStatusBar.ALPHA_OUT, animateAlpha, animateBounds);
} else {
// This state is now visible, update the bounds and show it
int alpha = (overrideAlpha != -1 ? overrideAlpha : viewState.dockAreaAlpha);
- viewState.dockAreaOverlay.setBounds(
- dockState.getDockedBounds(getMeasuredWidth(), getMeasuredHeight()));
- viewState.dockAreaOverlay.setCallback(this);
- viewState.startAlphaAnimation(alpha, 150);
+ Rect bounds = isDefaultDockState
+ ? dockState.getPreDockedBounds(getMeasuredWidth(), getMeasuredHeight())
+ : dockState.getDockedBounds(getMeasuredWidth(), getMeasuredHeight(),
+ mDividerSize, mSystemInsets, getResources());
+ if (viewState.dockAreaOverlay.getCallback() != this) {
+ viewState.dockAreaOverlay.setCallback(this);
+ viewState.dockAreaOverlay.setBounds(bounds);
+ }
+ viewState.startAnimation(bounds, alpha, DOCK_AREA_OVERLAY_TRANSITION_DURATION,
+ PhoneStatusBar.ALPHA_IN, animateAlpha, animateBounds);
}
}
}
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 473334b..0ca46a0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -19,6 +19,7 @@
import android.content.res.Configuration;
import android.graphics.Point;
import android.view.MotionEvent;
+import android.view.ViewConfiguration;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.events.EventBus;
@@ -64,13 +65,16 @@
private Point mTaskViewOffset = new Point();
private Point mDownPos = new Point();
- private boolean mDragging;
+ private boolean mDragRequested;
+ private boolean mIsDragging;
+ private float mDragSlop;
private DropTarget mLastDropTarget;
private ArrayList<DropTarget> mDropTargets = new ArrayList<>();
public RecentsViewTouchHandler(RecentsView rv) {
mRv = rv;
+ mDragSlop = ViewConfiguration.get(rv.getContext()).getScaledTouchSlop();
}
/**
@@ -96,13 +100,13 @@
/** Touch preprocessing for handling below */
public boolean onInterceptTouchEvent(MotionEvent ev) {
handleTouchEvent(ev);
- return mDragging;
+ return mDragRequested;
}
/** Handles touch events once we have intercepted them */
public boolean onTouchEvent(MotionEvent ev) {
handleTouchEvent(ev);
- return mDragging;
+ return mDragRequested;
}
/**** Events ****/
@@ -110,7 +114,9 @@
public final void onBusEvent(DragStartEvent event) {
SystemServicesProxy ssp = Recents.getSystemServices();
mRv.getParent().requestDisallowInterceptTouchEvent(true);
- mDragging = true;
+ mDragRequested = true;
+ // We defer starting the actual drag handling until the user moves past the drag slop
+ mIsDragging = false;
mDragTask = event.task;
mTaskView = event.taskView;
mDropTargets.clear();
@@ -137,7 +143,7 @@
}
public final void onBusEvent(DragEndEvent event) {
- mDragging = false;
+ mDragRequested = false;
mDragTask = null;
mTaskView = null;
mLastDropTarget = null;
@@ -153,25 +159,45 @@
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 - mTaskViewOffset.x;
- float y = evY - mTaskViewOffset.y;
+ float evX = ev.getX();
+ float evY = ev.getY();
+ float x = evX - mTaskViewOffset.x;
+ float y = evY - mTaskViewOffset.y;
- DropTarget currentDropTarget = null;
- for (DropTarget target : mDropTargets) {
- if (target.acceptsDrop((int) evX, (int) evY, width, height)) {
- currentDropTarget = target;
- break;
- }
+ if (mDragRequested) {
+ if (!mIsDragging) {
+ mIsDragging = Math.hypot(evX - mDownPos.x, evY - mDownPos.y) > mDragSlop;
}
- if (mLastDropTarget != currentDropTarget) {
- mLastDropTarget = currentDropTarget;
- EventBus.getDefault().send(new DragDropTargetChangedEvent(mDragTask,
- currentDropTarget));
+ if (mIsDragging) {
+ int width = mRv.getMeasuredWidth();
+ int height = mRv.getMeasuredHeight();
+
+ DropTarget currentDropTarget = null;
+
+ // Give priority to the current drop target to retain the touch handling
+ if (mLastDropTarget != null) {
+ if (mLastDropTarget.acceptsDrop((int) evX, (int) evY, width, height,
+ true /* isCurrentTarget */)) {
+ currentDropTarget = mLastDropTarget;
+ }
+ }
+
+ // Otherwise, find the next target to handle this event
+ if (currentDropTarget == null) {
+ for (DropTarget target : mDropTargets) {
+ if (target.acceptsDrop((int) evX, (int) evY, width, height,
+ false /* isCurrentTarget */)) {
+ currentDropTarget = target;
+ break;
+ }
+ }
+ }
+ if (mLastDropTarget != currentDropTarget) {
+ mLastDropTarget = currentDropTarget;
+ EventBus.getDefault().send(new DragDropTargetChangedEvent(mDragTask,
+ currentDropTarget));
+ }
+
}
mTaskView.setTranslationX(x);
@@ -181,7 +207,7 @@
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
- if (mDragging) {
+ if (mDragRequested) {
EventBus.getDefault().send(new DragEndEvent(mDragTask, mTaskView,
mLastDropTarget));
break;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index c2bb745..e908e53 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -37,7 +37,9 @@
import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
/**
* Used to describe a visible range that can be normalized to [0, 1].
@@ -373,7 +375,7 @@
* Computes the minimum and maximum scroll progress values and the progress values for each task
* in the stack.
*/
- void update(TaskStack stack) {
+ void update(TaskStack stack, HashSet<Task> ignoreTasksSet) {
SystemServicesProxy ssp = Recents.getSystemServices();
// Clear the progress map
@@ -393,6 +395,9 @@
ArrayList<Task> stackTasks = new ArrayList<>();
for (int i = 0; i < tasks.size(); i++) {
Task task = tasks.get(i);
+ if (ignoreTasksSet.contains(task)) {
+ continue;
+ }
if (task.isFreeformTask()) {
freeformTasks.add(task);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index ceab9c7..582698c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -28,8 +28,6 @@
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.Settings;
-import android.util.IntProperty;
-import android.util.Property;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -77,6 +75,7 @@
import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -105,19 +104,6 @@
private static final int DRAG_SCALE_DURATION = 175;
private static final float DRAG_SCALE_FACTOR = 1.05f;
- public static final Property<Drawable, Integer> DRAWABLE_ALPHA =
- new IntProperty<Drawable>("drawableAlpha") {
- @Override
- public void setValue(Drawable object, int alpha) {
- object.setAlpha(alpha);
- }
-
- @Override
- public Integer get(Drawable object) {
- return object.getAlpha();
- }
- };
-
TaskStack mStack;
TaskStackLayoutAlgorithm mLayoutAlgorithm;
TaskStackViewScroller mStackScroller;
@@ -136,6 +122,7 @@
Task mFocusedTask;
int mTaskCornerRadiusPx;
+ private int mDividerSize;
boolean mTaskViewsClipDirty = true;
boolean mAwaitingFirstLayout = true;
@@ -143,10 +130,14 @@
boolean mTouchExplorationEnabled;
boolean mScreenPinningEnabled;
- Rect mTaskStackBounds = new Rect();
+ // The stable stack bounds are the full bounds that we were measured with from RecentsView
+ Rect mStableStackBounds = new Rect();
+ // The current stack bounds are dynamic and may change as the user drags and drops
+ Rect mStackBounds = new Rect();
int[] mTmpVisibleRange = new int[2];
Rect mTmpRect = new Rect();
HashMap<Task, TaskView> mTmpTaskViewMap = new HashMap<>();
+ HashSet<Task> mTmpTaskSet = new HashSet<>();
List<TaskView> mTmpTaskViews = new ArrayList<>();
TaskViewTransform mTmpTransform = new TaskViewTransform();
LayoutInflater mInflater;
@@ -166,15 +157,25 @@
// The drop targets for a task drag
private DropTarget mFreeformWorkspaceDropTarget = new DropTarget() {
@Override
- public boolean acceptsDrop(int x, int y, int width, int height) {
- return mLayoutAlgorithm.mFreeformRect.contains(x, y);
+ public boolean acceptsDrop(int x, int y, int width, int height, boolean isCurrentTarget) {
+ // This drop target has a fixed bounds and should be checked last, so just fall through
+ // if it is the current target
+ if (!isCurrentTarget) {
+ return mLayoutAlgorithm.mFreeformRect.contains(x, y);
+ }
+ return false;
}
};
private DropTarget mStackDropTarget = new DropTarget() {
@Override
- public boolean acceptsDrop(int x, int y, int width, int height) {
- return mLayoutAlgorithm.mStackRect.contains(x, y);
+ public boolean acceptsDrop(int x, int y, int width, int height, boolean isCurrentTarget) {
+ // This drop target has a fixed bounds and should be checked last, so just fall through
+ // if it is the current target
+ if (!isCurrentTarget) {
+ return mLayoutAlgorithm.mStackRect.contains(x, y);
+ }
+ return false;
}
};
@@ -196,6 +197,7 @@
com.android.internal.R.interpolator.fast_out_slow_in);
mTaskCornerRadiusPx = res.getDimensionPixelSize(
R.dimen.recents_task_view_rounded_corners_radius);
+ mDividerSize = ssp.getDockedDividerSize(context);
int taskBarDismissDozeDelaySeconds = getResources().getInteger(
R.integer.recents_task_bar_dismiss_delay_seconds);
@@ -347,9 +349,8 @@
* This call ignores freeform tasks.
*/
private boolean updateStackTransforms(ArrayList<TaskViewTransform> taskTransforms,
- ArrayList<Task> tasks,
- float stackScroll,
- int[] visibleRangeOut) {
+ ArrayList<Task> tasks, float stackScroll,
+ int[] visibleRangeOut, HashSet<Task> ignoreTasksSet) {
int taskTransformCount = taskTransforms.size();
int taskCount = tasks.size();
int frontMostVisibleIndex = -1;
@@ -370,6 +371,10 @@
TaskViewTransform frontTransform = null;
for (int i = taskCount - 1; i >= 0; i--) {
Task task = tasks.get(i);
+ if (ignoreTasksSet.contains(task)) {
+ continue;
+ }
+
TaskViewTransform transform = mLayoutAlgorithm.getStackTransform(task, stackScroll,
taskTransforms.get(i), frontTransform);
@@ -410,14 +415,14 @@
* they are initially picked up from the pool, when they will be placed in a suitable initial
* position.
*/
- private void bindTaskViewsWithStack() {
+ private void bindTaskViewsWithStack(HashSet<Task> ignoreTasksSet) {
final float stackScroll = mStackScroller.getStackScroll();
final int[] visibleStackRange = mTmpVisibleRange;
// Get all the task transforms
final ArrayList<Task> tasks = mStack.getStackTasks();
- final boolean isValidVisibleStackRange = updateStackTransforms(mCurrentTaskTransforms, tasks,
- stackScroll, visibleStackRange);
+ final boolean isValidVisibleStackRange = updateStackTransforms(mCurrentTaskTransforms,
+ tasks, stackScroll, visibleStackRange, ignoreTasksSet);
// Return all the invisible children to the pool
mTmpTaskViewMap.clear();
@@ -429,6 +434,11 @@
final Task task = tv.getTask();
final int taskIndex = mStack.indexOfStackTask(task);
+ // Skip ignored tasks
+ if (ignoreTasksSet.contains(task)) {
+ continue;
+ }
+
if (task.isFreeformTask() ||
visibleStackRange[1] <= taskIndex && taskIndex <= visibleStackRange[0]) {
mTmpTaskViewMap.put(task, tv);
@@ -447,6 +457,11 @@
final Task task = tasks.get(i);
final TaskViewTransform transform = mCurrentTaskTransforms.get(i);
+ // Skip ignored tasks
+ if (ignoreTasksSet.contains(task)) {
+ continue;
+ }
+
// Skip the invisible non-freeform stack tasks
if (i > visibleStackRange[0] && !task.isFreeformTask()) {
continue;
@@ -496,8 +511,15 @@
/**
* Cancels any existing {@link TaskView} animations, and updates each {@link TaskView} to its
* current position as defined by the {@link TaskStackLayoutAlgorithm}.
+ *
+ * @param ignoreTasks the set of tasks to ignore in the relayout
*/
- private void updateTaskViewsToLayout(TaskViewAnimation animation) {
+ private void updateTaskViewsToLayout(TaskViewAnimation animation, Task... ignoreTasks) {
+ // Keep track of the ignore tasks
+ HashSet<Task> ignoreTasksSet = mTmpTaskSet;
+ ignoreTasksSet.clear();
+ Collections.addAll(ignoreTasksSet, ignoreTasks);
+
// If we had a deferred animation, cancel that
mDeferredTaskViewUpdateAnimation = null;
@@ -505,7 +527,7 @@
cancelAllTaskViewAnimations();
// Fetch the current set of TaskViews
- bindTaskViewsWithStack();
+ bindTaskViewsWithStack(ignoreTasksSet);
// Animate them to their final transforms with the given animation
List<TaskView> taskViews = getTaskViews();
@@ -515,6 +537,10 @@
final int taskIndex = mStack.indexOfStackTask(tv.getTask());
final TaskViewTransform transform = mCurrentTaskTransforms.get(taskIndex);
+ if (ignoreTasksSet.contains(tv.getTask())) {
+ continue;
+ }
+
updateTaskViewToTransform(tv, transform, animation);
}
}
@@ -542,8 +568,7 @@
*/
private void cancelAllTaskViewAnimations() {
List<TaskView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
+ for (int i = taskViews.size() - 1; i >= 0; i--) {
final TaskView tv = taskViews.get(i);
tv.cancelTransformAnimation();
}
@@ -594,10 +619,19 @@
mTaskViewsClipDirty = false;
}
- /** Updates the min and max virtual scroll bounds */
- void updateLayout(boolean boundScrollToNewMinMax) {
+ /**
+ * Updates the min and max virtual scroll bounds.
+ *
+ * @param ignoreTasks the set of tasks to ignore in the relayout
+ */
+ void updateLayout(boolean boundScrollToNewMinMax, Task... ignoreTasks) {
+ // Keep track of the ingore tasks
+ HashSet<Task> ignoreTasksSet = mTmpTaskSet;
+ ignoreTasksSet.clear();
+ Collections.addAll(ignoreTasksSet, ignoreTasks);
+
// Compute the min and max scroll values
- mLayoutAlgorithm.update(mStack);
+ mLayoutAlgorithm.update(mStack, ignoreTasksSet);
// Update the freeform workspace
SystemServicesProxy ssp = Recents.getSystemServices();
@@ -918,14 +952,18 @@
}
}
- /** Computes the stack and task rects */
- public void computeRects(Rect taskStackBounds) {
+ /**
+ * Computes the stack and task rects.
+ *
+ * @param ignoreTasks the set of tasks to ignore in the relayout
+ */
+ public void computeRects(Rect taskStackBounds, boolean boundScroll, Task... ignoreTasks) {
// Compute the rects in the stack algorithm
mLayoutAlgorithm.initialize(taskStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
// Update the scroll bounds
- updateLayout(false);
+ updateLayout(boundScroll, ignoreTasks);
}
/**
@@ -945,9 +983,19 @@
return mLayoutAlgorithm.computeStackVisibilityReport(mStack.getStackTasks());
}
+ /**
+ * Updates the expected task stack bounds for this stack view.
+ */
public void setTaskStackBounds(Rect taskStackBounds, Rect systemInsets) {
- mTaskStackBounds.set(taskStackBounds);
+ // We can get spurious measure passes with the old bounds when docking, and since we are
+ // using the current stack bounds during drag and drop, don't overwrite them until we
+ // actually get new bounds
+ if (!taskStackBounds.equals(mStableStackBounds)) {
+ mStableStackBounds.set(taskStackBounds);
+ mStackBounds.set(taskStackBounds);
+ }
mLayoutAlgorithm.setSystemInsets(systemInsets);
+ requestLayout();
}
/**
@@ -960,14 +1008,15 @@
int height = MeasureSpec.getSize(heightMeasureSpec);
// Compute our stack/task rects
- computeRects(mTaskStackBounds);
+ computeRects(mStackBounds, false);
// If this is the first layout, then scroll to the front of the stack, then update the
// TaskViews with the stack so that we can lay them out
if (mAwaitingFirstLayout) {
mStackScroller.setStackScrollToInitialState();
}
- bindTaskViewsWithStack();
+ mTmpTaskSet.clear();
+ bindTaskViewsWithStack(mTmpTaskSet);
// Measure each of the TaskViews
mTmpTaskViews.clear();
@@ -1407,6 +1456,7 @@
mLayoutAlgorithm.getStackTransform(event.task, getScroller().getStackScroll(),
mTmpTransform, null);
mTmpTransform.scale = finalScale;
+ mTmpTransform.translationZ = mLayoutAlgorithm.mMaxTranslationZ + 1;
updateTaskViewToTransform(event.taskView, mTmpTransform,
new TaskViewAnimation(DRAG_SCALE_DURATION, mFastOutSlowInInterpolator));
}
@@ -1420,7 +1470,23 @@
}
public final void onBusEvent(DragDropTargetChangedEvent event) {
- // TODO: Animate the freeform workspace background etc.
+ if (event.dropTarget instanceof TaskStack.DockState) {
+ // Calculate the new task stack bounds that matches the window size that Recents will
+ // have after the drop
+ final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget;
+ mStackBounds.set(dockState.getDockedTaskStackBounds(getMeasuredWidth(),
+ getMeasuredHeight(), mDividerSize, mLayoutAlgorithm.mSystemInsets,
+ getResources()));
+ computeRects(mStackBounds, true /* boundScroll */, event.task /* ignoreTask */);
+ updateTaskViewsToLayout(new TaskViewAnimation(250, mFastOutSlowInInterpolator),
+ event.task /* ignoreTask */);
+ } else {
+ // Restore the pre-drag task stack bounds
+ mStackBounds.set(mStableStackBounds);
+ computeRects(mStackBounds, true /* boundScroll */);
+ updateTaskViewsToLayout(new TaskViewAnimation(250, mFastOutSlowInInterpolator),
+ event.task /* ignoreTask */);
+ }
}
public final void onBusEvent(final DragEndEvent event) {
@@ -1564,7 +1630,7 @@
Utilities.cancelAnimationWithoutCallbacks(mFreeformWorkspaceBackgroundAnimator);
mFreeformWorkspaceBackgroundAnimator = ObjectAnimator.ofInt(mFreeformWorkspaceBackground,
- DRAWABLE_ALPHA, mFreeformWorkspaceBackground.getAlpha(), targetAlpha);
+ Utilities.DRAWABLE_ALPHA, mFreeformWorkspaceBackground.getAlpha(), targetAlpha);
mFreeformWorkspaceBackgroundAnimator.setDuration(duration);
mFreeformWorkspaceBackgroundAnimator.setInterpolator(interpolator);
mFreeformWorkspaceBackgroundAnimator.start();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 00d64fe..96dadff 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -136,6 +136,10 @@
float mDimAlpha;
Drawable mLightDismissDrawable;
Drawable mDarkDismissDrawable;
+ Drawable mLightFreeformIcon;
+ Drawable mDarkFreeformIcon;
+ Drawable mLightFullscreenIcon;
+ Drawable mDarkFullscreenIcon;
int mTaskBarViewLightTextColor;
int mTaskBarViewDarkTextColor;
String mDismissContentDescription;
@@ -179,6 +183,11 @@
mHighlightHeight = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight);
mTaskBarViewLightTextColor = context.getColor(R.color.recents_task_bar_light_text_color);
mTaskBarViewDarkTextColor = context.getColor(R.color.recents_task_bar_dark_text_color);
+ mLightFreeformIcon = context.getDrawable(R.drawable.recents_move_task_freeform_light);
+ mDarkFreeformIcon = context.getDrawable(R.drawable.recents_move_task_freeform_dark);
+ mLightFullscreenIcon = context.getDrawable(R.drawable.recents_move_task_fullscreen_light);
+ mDarkFullscreenIcon = context.getDrawable(R.drawable.recents_move_task_fullscreen_dark);
+
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
@@ -223,7 +232,9 @@
mTaskViewRect.set(0, 0, width, height);
boolean updateMoveTaskButton = mMoveTaskButton.getVisibility() != View.GONE;
int appIconWidth = mIconView.getMeasuredWidth();
- int activityDescWidth = mTitleView.getMeasuredWidth();
+ int activityDescWidth = (mTask != null)
+ ? (int) mTitleView.getPaint().measureText(mTask.title)
+ : mTitleView.getMeasuredWidth();
int dismissIconWidth = mDismissButton.getMeasuredWidth();
int moveTaskIconWidth = mMoveTaskButton.getVisibility() == View.VISIBLE
? mMoveTaskButton.getMeasuredWidth()
@@ -360,14 +371,14 @@
if (ssp.hasFreeformWorkspaceSupport()) {
if (t.isFreeformTask()) {
mMoveTaskTargetStackId = FULLSCREEN_WORKSPACE_STACK_ID;
- mMoveTaskButton.setImageResource(t.useLightOnPrimaryColor
- ? R.drawable.recents_move_task_fullscreen_light
- : R.drawable.recents_move_task_fullscreen_dark);
+ mMoveTaskButton.setImageDrawable(t.useLightOnPrimaryColor
+ ? mLightFullscreenIcon
+ : mDarkFullscreenIcon);
} else {
mMoveTaskTargetStackId = FREEFORM_WORKSPACE_STACK_ID;
- mMoveTaskButton.setImageResource(t.useLightOnPrimaryColor
- ? R.drawable.recents_move_task_freeform_light
- : R.drawable.recents_move_task_freeform_dark);
+ mMoveTaskButton.setImageDrawable(t.useLightOnPrimaryColor
+ ? mLightFreeformIcon
+ : mDarkFreeformIcon);
}
if (mMoveTaskButton.getVisibility() != View.VISIBLE) {
mMoveTaskButton.setVisibility(View.VISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 824d10a..c16703e8 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -363,21 +363,6 @@
return mStartPosition + touchY - mStartY;
}
- private int invertDockSide(int dockSide) {
- switch (dockSide) {
- case WindowManager.DOCKED_LEFT:
- return WindowManager.DOCKED_RIGHT;
- case WindowManager.DOCKED_TOP:
- return WindowManager.DOCKED_BOTTOM;
- case WindowManager.DOCKED_RIGHT:
- return WindowManager.DOCKED_LEFT;
- case WindowManager.DOCKED_BOTTOM:
- return WindowManager.DOCKED_TOP;
- default:
- return WindowManager.DOCKED_INVALID;
- }
- }
-
private void alignTopLeft(Rect containingRect, Rect rect) {
int width = rect.width();
int height = rect.height();
@@ -409,8 +394,9 @@
mLastResizeRect.set(mDockedRect);
if (taskPosition != TASK_POSITION_SAME) {
- calculateBoundsForPosition(position, invertDockSide(mDockSide), mOtherRect);
- int dockSideInverted = invertDockSide(mDockSide);
+ calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
+ mOtherRect);
+ int dockSideInverted = DockedDividerUtils.invertDockSide(mDockSide);
int taskPositionDocked =
restrictDismissingTaskPosition(taskPosition, mDockSide, taskSnapTarget);
int taskPositionOther =