diff options
| author | 2016-04-18 16:57:27 -0700 | |
|---|---|---|
| committer | 2016-04-18 18:20:43 -0700 | |
| commit | 99ef458ff1b79c93a8dfdc289fb6ff80fd7aacf6 (patch) | |
| tree | 088fa67745580cf7bbe4e24e8203b366dc6b71fb | |
| parent | 3664426dcf3a603a52d630a74f3caef9da682457 (diff) | |
Adding hint text for drop targets.
Bug: 28192178
Change-Id: Id7be5129488622b56082d2dfa328b751311cabd7
5 files changed, 144 insertions, 39 deletions
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 03b9837e6175..504361008570 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -640,6 +640,9 @@ <!-- The amount of overscroll allowed when flinging to the end of the stack. --> <dimen name="recents_fling_overscroll_distance">24dp</dimen> + <!-- The size of the drag hint text. --> + <dimen name="recents_drag_hint_text_size">14sp</dimen> + <!-- The min alpha to apply to a task affiliation group color. --> <item name="recents_task_affiliation_color_min_alpha_percentage" format="float" type="dimen">0.6</item> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 37b00bbfdc27..a03aa28c47c5 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -737,6 +737,8 @@ <string name="recents_stack_action_button_label">Clear all</string> <!-- Recents: Incompatible task message. [CHAR LIMIT=NONE] --> <string name="recents_incompatible_app_message">App doesn\'t support split screen</string> + <!-- Recents: Hint text that shows on the drop targets to start multiwindow. [CHAR LIMIT=NONE] --> + <string name="recents_drag_hint_message">Drag here to use split screen</string> <!-- Recents: MultiStack add stack split horizontal radio button. [CHAR LIMIT=NONE] --> <string name="recents_multistack_add_stack_dialog_split_horizontal">Split Horizontal</string> 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 95e276f7c8cf..47995c4b73f3 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java @@ -30,17 +30,21 @@ import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; -import android.animation.RectEvaluator; +import android.annotation.IntDef; import android.content.ComponentName; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; +import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.ColorDrawable; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.IntProperty; import android.util.SparseArray; import android.view.animation.Interpolator; @@ -56,6 +60,8 @@ import com.android.systemui.recents.views.DropTarget; import com.android.systemui.recents.views.TaskStackLayoutAlgorithm; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -240,22 +246,30 @@ public class TaskStack { */ public static class DockState implements DropTarget { + // The rotation to apply to the hint text + @Retention(RetentionPolicy.SOURCE) + @IntDef({HORIZONTAL, VERTICAL}) + public @interface TextOrientation {} + private static final int HORIZONTAL = 0; + private static final int VERTICAL = 1; + private static final int DOCK_AREA_ALPHA = 192; - public static final DockState NONE = new DockState(DOCKED_INVALID, -1, 80, null, null, null); + public static final DockState NONE = new DockState(DOCKED_INVALID, -1, 80, 255, HORIZONTAL, + null, null, null); public static final DockState LEFT = new DockState(DOCKED_LEFT, - DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, + DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, 0, VERTICAL, 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, + DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, 0, HORIZONTAL, 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, + DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA, 0, VERTICAL, 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, + DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA, 0, HORIZONTAL, new RectF(0, 0.875f, 1, 1), new RectF(0, 0.875f, 1, 1), new RectF(0, 0.5f, 1, 1)); @@ -267,33 +281,109 @@ public class TaskStack { } // Represents the view state of this dock state - public class ViewState { + public static class ViewState { + private static final IntProperty<ViewState> HINT_ALPHA = + new IntProperty<ViewState>("drawableAlpha") { + @Override + public void setValue(ViewState object, int alpha) { + object.mHintTextAlpha = alpha; + object.dockAreaOverlay.invalidateSelf(); + } + + @Override + public Integer get(ViewState object) { + return object.mHintTextAlpha; + } + }; + public final int dockAreaAlpha; public final ColorDrawable dockAreaOverlay; - private AnimatorSet dockAreaOverlayAnimator; - - private ViewState(int alpha) { - dockAreaAlpha = alpha; + public final int hintTextAlpha; + public final int hintTextOrientation; + + private final int mHintTextResId; + private String mHintText; + private Paint mHintTextPaint; + private Point mHintTextBounds = new Point(); + private int mHintTextAlpha = 255; + private AnimatorSet mDockAreaOverlayAnimator; + private Rect mTmpRect = new Rect(); + + private ViewState(int areaAlpha, int hintAlpha, @TextOrientation int hintOrientation, + int hintTextResId) { + dockAreaAlpha = areaAlpha; dockAreaOverlay = new ColorDrawable(0xFFffffff); dockAreaOverlay.setAlpha(0); + hintTextAlpha = hintAlpha; + hintTextOrientation = hintOrientation; + mHintTextResId = hintTextResId; + mHintTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mHintTextPaint.setColor(Color.WHITE); + } + + /** + * Updates the view state with the given context. + */ + public void update(Context context) { + Resources res = context.getResources(); + mHintText = context.getString(mHintTextResId); + mHintTextPaint.setTextSize(res.getDimensionPixelSize( + R.dimen.recents_drag_hint_text_size)); + mHintTextPaint.getTextBounds(mHintText, 0, mHintText.length(), mTmpRect); + mHintTextBounds.set((int) mHintTextPaint.measureText(mHintText), mTmpRect.height()); + } + + /** + * Draws the current view state. + */ + public void draw(Canvas canvas) { + // Draw the overlay background + if (dockAreaOverlay.getAlpha() > 0) { + dockAreaOverlay.draw(canvas); + } + + // Draw the hint text + if (mHintTextAlpha > 0) { + Rect bounds = dockAreaOverlay.getBounds(); + int x = bounds.left + (bounds.width() - mHintTextBounds.x) / 2; + int y = bounds.top + (bounds.height() + mHintTextBounds.y) / 2; + mHintTextPaint.setAlpha(mHintTextAlpha); + if (hintTextOrientation == VERTICAL) { + canvas.save(); + canvas.rotate(-90f, bounds.centerX(), bounds.centerY()); + } + canvas.drawText(mHintText, x, y, mHintTextPaint); + if (hintTextOrientation == VERTICAL) { + canvas.restore(); + } + } } /** * Creates a new bounds and alpha animation. */ - public void startAnimation(Rect bounds, int alpha, int duration, + public void startAnimation(Rect bounds, int areaAlpha, int hintAlpha, int duration, Interpolator interpolator, boolean animateAlpha, boolean animateBounds) { - if (dockAreaOverlayAnimator != null) { - dockAreaOverlayAnimator.cancel(); + if (mDockAreaOverlayAnimator != null) { + mDockAreaOverlayAnimator.cancel(); } ArrayList<Animator> animators = new ArrayList<>(); - if (dockAreaOverlay.getAlpha() != alpha) { + if (dockAreaOverlay.getAlpha() != areaAlpha) { if (animateAlpha) { animators.add(ObjectAnimator.ofInt(dockAreaOverlay, - Utilities.DRAWABLE_ALPHA, dockAreaOverlay.getAlpha(), alpha)); + Utilities.DRAWABLE_ALPHA, dockAreaOverlay.getAlpha(), areaAlpha)); } else { - dockAreaOverlay.setAlpha(alpha); + dockAreaOverlay.setAlpha(areaAlpha); + } + } + if (mHintTextAlpha != hintAlpha) { + if (animateAlpha) { + animators.add(ObjectAnimator.ofInt(this, HINT_ALPHA, mHintTextAlpha, + hintAlpha)); + } else { + mHintTextAlpha = hintAlpha; + dockAreaOverlay.invalidateSelf(); } } if (bounds != null && !dockAreaOverlay.getBounds().equals(bounds)) { @@ -307,11 +397,11 @@ public class TaskStack { } } if (!animators.isEmpty()) { - dockAreaOverlayAnimator = new AnimatorSet(); - dockAreaOverlayAnimator.playTogether(animators); - dockAreaOverlayAnimator.setDuration(duration); - dockAreaOverlayAnimator.setInterpolator(interpolator); - dockAreaOverlayAnimator.start(); + mDockAreaOverlayAnimator = new AnimatorSet(); + mDockAreaOverlayAnimator.playTogether(animators); + mDockAreaOverlayAnimator.setDuration(duration); + mDockAreaOverlayAnimator.setInterpolator(interpolator); + mDockAreaOverlayAnimator.start(); } } } @@ -331,17 +421,26 @@ public class TaskStack { * the initial touch area. This is also the new dock area to * draw. */ - DockState(int dockSide, int createMode, int dockAreaAlpha, RectF touchArea, RectF dockArea, + DockState(int dockSide, int createMode, int dockAreaAlpha, int hintTextAlpha, + @TextOrientation int hintTextOrientation, RectF touchArea, RectF dockArea, RectF expandedTouchDockArea) { this.dockSide = dockSide; this.createMode = createMode; - this.viewState = new ViewState(dockAreaAlpha); + this.viewState = new ViewState(dockAreaAlpha, hintTextAlpha, hintTextOrientation, + R.string.recents_drag_hint_message); this.dockArea = dockArea; this.touchArea = touchArea; this.expandedTouchDockArea = expandedTouchDockArea; } /** + * Updates the dock state with the given context. + */ + public void update(Context context) { + viewState.update(context); + } + + /** * Returns whether {@param x} and {@param y} are contained in the area scaled to the * given {@param width} and {@param 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 6604cccdb93d..a5ca302bac2f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -426,10 +426,7 @@ public class RecentsView extends FrameLayout { ArrayList<TaskStack.DockState> visDockStates = mTouchHandler.getVisibleDockStates(); for (int i = visDockStates.size() - 1; i >= 0; i--) { - Drawable d = visDockStates.get(i).viewState.dockAreaOverlay; - if (d.getAlpha() > 0) { - d.draw(canvas); - } + visDockStates.get(i).viewState.draw(canvas); } } @@ -465,6 +462,7 @@ public class RecentsView extends FrameLayout { public final void onBusEvent(DragStartEvent event) { updateVisibleDockRegions(mTouchHandler.getDockStatesForCurrentOrientation(), true /* isDefaultDockState */, TaskStack.DockState.NONE.viewState.dockAreaAlpha, + TaskStack.DockState.NONE.viewState.hintTextAlpha, true /* animateAlpha */, false /* animateBounds */); } @@ -472,11 +470,12 @@ public class RecentsView extends FrameLayout { if (event.dropTarget == null || !(event.dropTarget instanceof TaskStack.DockState)) { updateVisibleDockRegions(mTouchHandler.getDockStatesForCurrentOrientation(), true /* isDefaultDockState */, TaskStack.DockState.NONE.viewState.dockAreaAlpha, + TaskStack.DockState.NONE.viewState.hintTextAlpha, true /* animateAlpha */, true /* animateBounds */); } else { final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget; updateVisibleDockRegions(new TaskStack.DockState[] {dockState}, - false /* isDefaultDockState */, -1, true /* animateAlpha */, + false /* isDefaultDockState */, -1, -1, true /* animateAlpha */, true /* animateBounds */); } if (mStackActionButton != null) { @@ -498,13 +497,9 @@ public class RecentsView extends FrameLayout { final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget; // Hide the dock region - updateVisibleDockRegions(null, false /* isDefaultDockState */, -1, + updateVisibleDockRegions(null, false /* isDefaultDockState */, -1, -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(); @@ -548,7 +543,7 @@ public class RecentsView extends FrameLayout { event.task.getTopComponent().flattenToShortString()); } else { // Animate the overlay alpha back to 0 - updateVisibleDockRegions(null, true /* isDefaultDockState */, -1, + updateVisibleDockRegions(null, true /* isDefaultDockState */, -1, -1, true /* animateAlpha */, false /* animateBounds */); } } @@ -710,8 +705,8 @@ public class RecentsView extends FrameLayout { * Updates the dock region to match the specified dock state. */ private void updateVisibleDockRegions(TaskStack.DockState[] newDockStates, - boolean isDefaultDockState, int overrideAlpha, boolean animateAlpha, - boolean animateBounds) { + boolean isDefaultDockState, int overrideAreaAlpha, int overrideHintAlpha, + boolean animateAlpha, boolean animateBounds) { ArraySet<TaskStack.DockState> newDockStatesSet = Utilities.arrayToSet(newDockStates, new ArraySet<TaskStack.DockState>()); ArrayList<TaskStack.DockState> visDockStates = mTouchHandler.getVisibleDockStates(); @@ -720,11 +715,16 @@ public class RecentsView extends FrameLayout { TaskStack.DockState.ViewState viewState = dockState.viewState; if (newDockStates == null || !newDockStatesSet.contains(dockState)) { // This is no longer visible, so hide it - viewState.startAnimation(null, 0, DOCK_AREA_OVERLAY_TRANSITION_DURATION, + viewState.startAnimation(null, 0, 0, DOCK_AREA_OVERLAY_TRANSITION_DURATION, Interpolators.ALPHA_OUT, animateAlpha, animateBounds); } else { // This state is now visible, update the bounds and show it - int alpha = (overrideAlpha != -1 ? overrideAlpha : viewState.dockAreaAlpha); + int areaAlpha = overrideAreaAlpha != -1 + ? overrideAreaAlpha + : viewState.dockAreaAlpha; + int hintAlpha = overrideHintAlpha != -1 + ? overrideHintAlpha + : viewState.hintTextAlpha; Rect bounds = isDefaultDockState ? dockState.getPreDockedBounds(getMeasuredWidth(), getMeasuredHeight()) : dockState.getDockedBounds(getMeasuredWidth(), getMeasuredHeight(), 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 70c4dbdc9665..214ec90fe5ee 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java @@ -171,6 +171,7 @@ public class RecentsViewTouchHandler { TaskStack.DockState[] dockStates = getDockStatesForCurrentOrientation(); for (TaskStack.DockState dockState : dockStates) { registerDropTargetForCurrentDrag(dockState); + dockState.update(mRv.getContext()); mVisibleDockStates.add(dockState); } } |