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
This commit is contained in:
Jorim Jaggi
2016-01-22 17:18:29 -08:00
parent 8ab7759567
commit 50cd6361d7
2 changed files with 79 additions and 1 deletions

View File

@@ -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.
*/

View File

@@ -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.