Add fling animation when snapping split divider bar
Bug: 172704238 Test: atest WMShellUnitTests Test: manul check the fling behavior Change-Id: Iead37be86d55de2ce357165a2f6ae910f36969cb
This commit is contained in:
@@ -112,7 +112,7 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
|
||||
}
|
||||
if (mMoving) {
|
||||
final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos;
|
||||
mSplitLayout.updateDividePosition(position);
|
||||
mSplitLayout.updateDivideBounds(position);
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
@@ -131,7 +131,7 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
|
||||
final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos;
|
||||
final DividerSnapAlgorithm.SnapTarget snapTarget =
|
||||
mSplitLayout.findSnapTarget(position, velocity);
|
||||
mSplitLayout.setSnapTarget(snapTarget);
|
||||
mSplitLayout.snapToTarget(position, snapTarget);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -22,6 +22,9 @@ import static android.view.WindowManager.DOCKED_TOP;
|
||||
import static com.android.internal.policy.DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END;
|
||||
import static com.android.internal.policy.DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
@@ -31,6 +34,7 @@ import android.view.SurfaceControl;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.policy.DividerSnapAlgorithm;
|
||||
import com.android.wm.shell.animation.Interpolators;
|
||||
|
||||
/**
|
||||
* Records and handles layout of splits. Helps to calculate proper bounds when configuration or
|
||||
@@ -145,17 +149,23 @@ public class SplitLayout {
|
||||
* Updates bounds with the passing position. Usually used to update recording bounds while
|
||||
* performing animation or dragging divider bar to resize the splits.
|
||||
*/
|
||||
public void updateDividePosition(int position) {
|
||||
void updateDivideBounds(int position) {
|
||||
updateBounds(position);
|
||||
mLayoutChangeListener.onBoundsChanging(this);
|
||||
}
|
||||
|
||||
void setDividePosition(int position) {
|
||||
mDividePosition = position;
|
||||
updateBounds(mDividePosition);
|
||||
mLayoutChangeListener.onBoundsChanged(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets new divide position and updates bounds correspondingly. Notifies listener if the new
|
||||
* target indicates dismissing split.
|
||||
*/
|
||||
public void setSnapTarget(DividerSnapAlgorithm.SnapTarget snapTarget) {
|
||||
switch(snapTarget.flag) {
|
||||
public void snapToTarget(int currentPosition, DividerSnapAlgorithm.SnapTarget snapTarget) {
|
||||
switch (snapTarget.flag) {
|
||||
case FLAG_DISMISS_START:
|
||||
mLayoutChangeListener.onSnappedToDismiss(false /* snappedToEnd */);
|
||||
break;
|
||||
@@ -163,9 +173,7 @@ public class SplitLayout {
|
||||
mLayoutChangeListener.onSnappedToDismiss(true /* snappedToEnd */);
|
||||
break;
|
||||
default:
|
||||
mDividePosition = snapTarget.position;
|
||||
updateBounds(mDividePosition);
|
||||
mLayoutChangeListener.onBoundsChanged(this);
|
||||
flingDividePosition(currentPosition, snapTarget.position);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -189,6 +197,27 @@ public class SplitLayout {
|
||||
isLandscape ? DOCKED_LEFT : DOCKED_TOP /* dockSide */);
|
||||
}
|
||||
|
||||
private void flingDividePosition(int from, int to) {
|
||||
ValueAnimator animator = ValueAnimator
|
||||
.ofInt(from, to)
|
||||
.setDuration(250);
|
||||
animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
||||
animator.addUpdateListener(
|
||||
animation -> updateDivideBounds((int) animation.getAnimatedValue()));
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
setDividePosition(to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
setDividePosition(to);
|
||||
}
|
||||
});
|
||||
animator.start();
|
||||
}
|
||||
|
||||
private static boolean isLandscape(Rect bounds) {
|
||||
return bounds.width() > bounds.height();
|
||||
}
|
||||
|
||||
@@ -69,24 +69,27 @@ public class SplitLayoutTests extends ShellTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateDividePosition() {
|
||||
mSplitLayout.updateDividePosition(anyInt());
|
||||
public void testUpdateDivideBounds() {
|
||||
mSplitLayout.updateDivideBounds(anyInt());
|
||||
verify(mLayoutChangeListener).onBoundsChanging(any(SplitLayout.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetSnapTarget() {
|
||||
DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0,
|
||||
@UiThreadTest
|
||||
public void testSnapToTarget() {
|
||||
DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0 /* position */,
|
||||
DividerSnapAlgorithm.SnapTarget.FLAG_NONE);
|
||||
mSplitLayout.setSnapTarget(snapTarget);
|
||||
verify(mLayoutChangeListener).onBoundsChanged(any(SplitLayout.class));
|
||||
mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget);
|
||||
verify(mLayoutChangeListener).onBoundsChanging(any(SplitLayout.class));
|
||||
|
||||
// verify it callbacks properly when the snap target indicates dismissing split.
|
||||
snapTarget = getSnapTarget(0, DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START);
|
||||
mSplitLayout.setSnapTarget(snapTarget);
|
||||
snapTarget = getSnapTarget(0 /* position */,
|
||||
DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START);
|
||||
mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget);
|
||||
verify(mLayoutChangeListener).onSnappedToDismiss(eq(false));
|
||||
snapTarget = getSnapTarget(0, DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END);
|
||||
mSplitLayout.setSnapTarget(snapTarget);
|
||||
snapTarget = getSnapTarget(0 /* position */,
|
||||
DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END);
|
||||
mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget);
|
||||
verify(mLayoutChangeListener).onSnappedToDismiss(eq(true));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user