From 50cd6361d7cb50bdc0ee199f42307885abc65f0b Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Fri, 22 Jan 2016 17:18:29 -0800 Subject: [PATCH] Refine divider behavior - Switch earlier to the dismissing/fullscreen layout, so we minimize holes. - For the bottom/right one, switch also earlier to the larger size to minimize holes. We can't do this for the upper one because it will be confusing there if the layout bounds doesn't equal the bounds while snapping. Change-Id: I8f065514f7aaa15ae76af648794ab8b23302e534 --- .../internal/policy/DividerSnapAlgorithm.java | 16 +++++ .../systemui/stackdivider/DividerView.java | 64 ++++++++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java index 5b40bc0ed3a90..a572486744473 100644 --- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java +++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java @@ -237,6 +237,22 @@ public class DividerSnapAlgorithm { return mMiddleTarget; } + public SnapTarget getNextTarget(SnapTarget snapTarget) { + int index = mTargets.indexOf(snapTarget); + if (index != -1 && index < mTargets.size() - 1) { + return mTargets.get(index + 1); + } + return snapTarget; + } + + public SnapTarget getPreviousTarget(SnapTarget snapTarget) { + int index = mTargets.indexOf(snapTarget); + if (index != -1 && index > 0) { + return mTargets.get(index - 1); + } + return snapTarget; + } + /** * Represents a snap target for the divider. */ diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 9e83dcf64a805..08793e8107a42 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -44,7 +44,6 @@ import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import android.widget.FrameLayout; -import android.widget.ImageButton; import com.android.internal.policy.DividerSnapAlgorithm; import com.android.internal.policy.DockedDividerUtils; @@ -72,6 +71,18 @@ public class DividerView extends FrameLayout implements OnTouchListener, private static final float DIM_START_FRACTION = 0.5f; private static final float DIM_DAMP_FACTOR = 1.7f; + /** + * Fraction of the divider position between two snap targets to switch to the full-screen + * target. + */ + private static final float SWITCH_FULLSCREEN_FRACTION = 0.12f; + + /** + * Fraction of the divider position between two snap targets to switch to the larger target + * for the bottom/right app layout. + */ + private static final float BOTTOM_RIGHT_SWITCH_BIGGER_FRACTION = 0.2f; + private static final PathInterpolator SLOWDOWN_INTERPOLATOR = new PathInterpolator(0.5f, 1f, 0.5f, 1f); @@ -404,6 +415,12 @@ public class DividerView extends FrameLayout implements OnTouchListener, restrictDismissingTaskPosition(taskPosition, mDockSide, taskSnapTarget); int taskPositionOther = restrictDismissingTaskPosition(taskPosition, dockSideInverted, taskSnapTarget); + + taskPositionDocked = minimizeHoles(position, taskPositionDocked, mDockSide, + taskSnapTarget); + taskPositionOther = minimizeHoles(position, taskPositionOther, dockSideInverted, + taskSnapTarget); + calculateBoundsForPosition(taskPositionDocked, mDockSide, mDockedTaskRect); calculateBoundsForPosition(taskPositionOther, dockSideInverted, mOtherTaskRect); alignTopLeft(mDockedRect, mDockedTaskRect); @@ -434,6 +451,51 @@ public class DividerView extends FrameLayout implements OnTouchListener, fraction); } + /** + * Given the current split position and the task position calculated by dragging, this + * method calculates a "better" task position in a sense so holes get smaller while dragging. + * + * @return the new task position + */ + private int minimizeHoles(int position, int taskPosition, int dockSide, + SnapTarget taskSnapTarget) { + if (dockSideTopLeft(dockSide)) { + if (position > taskPosition) { + SnapTarget nextTarget = mSnapAlgorithm.getNextTarget(taskSnapTarget); + + // If the next target is the dismiss end target, switch earlier to make the hole + // smaller. + if (nextTarget != taskSnapTarget + && nextTarget == mSnapAlgorithm.getDismissEndTarget()) { + float t = (float) (position - taskPosition) + / (nextTarget.position - taskPosition); + if (t > SWITCH_FULLSCREEN_FRACTION) { + return nextTarget.position; + } + } + } + } else if (dockSideBottomRight(dockSide)) { + if (position < taskPosition) { + SnapTarget previousTarget = mSnapAlgorithm.getPreviousTarget(taskSnapTarget); + if (previousTarget != taskSnapTarget) { + float t = (float) (taskPosition - position) + / (taskPosition - previousTarget.position); + + // In general, switch a bit earlier (at 20% instead of 50%), but if we are + // dismissing the top, switch really early. + float threshold = previousTarget == mSnapAlgorithm.getDismissStartTarget() + ? SWITCH_FULLSCREEN_FRACTION + : BOTTOM_RIGHT_SWITCH_BIGGER_FRACTION; + if (t > threshold) { + return previousTarget.position; + } + + } + } + } + return taskPosition; + } + /** * When the snap target is dismissing one side, make sure that the dismissing side doesn't get * 0 size.