Merge "Animate bounce effect when tapping"

This commit is contained in:
Ryan Lin
2021-01-06 05:52:15 +00:00
committed by Android (Google) Code Review
2 changed files with 76 additions and 18 deletions

View File

@@ -20,6 +20,8 @@ import static android.view.WindowManager.LayoutParams;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -28,7 +30,6 @@ import android.content.res.Resources;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
@@ -66,7 +67,7 @@ import java.util.Locale;
* Class to handle adding and removing a window magnification.
*/
class WindowMagnificationController implements View.OnTouchListener, SurfaceHolder.Callback,
MirrorWindowControl.MirrorWindowDelegate {
MirrorWindowControl.MirrorWindowDelegate, MagnificationGestureDetector.OnGestureListener {
private static final String TAG = "WindowMagnificationController";
// Delay to avoid updating state description too frequently.
@@ -74,6 +75,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
// It should be consistent with the value defined in WindowMagnificationGestureHandler.
private static final Range<Float> A11Y_ACTION_SCALE_RANGE = new Range<>(2.0f, 8.0f);
private static final float A11Y_CHANGE_SCALE_DIFFERENCE = 1.0f;
private static final float ANIMATION_BOUNCE_EFFECT_SCALE = 1.05f;
private final Context mContext;
private final Resources mResources;
private final Handler mHandler;
@@ -102,7 +104,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
private View mRightDrag;
private View mBottomDrag;
private final PointF mLastDrag = new PointF();
@NonNull
private final WindowMagnifierCallback mWindowMagnifierCallback;
@@ -123,9 +124,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
private int mNavGestureHeight;
private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
private final MagnificationGestureDetector mGestureDetector;
private final int mBounceEffectDuration;
private Choreographer.FrameCallback mMirrorViewGeometryVsyncCallback;
private Locale mLocale;
private NumberFormat mPercentFormat;
private float mBounceEffectAnimationScale;
@Nullable
private MirrorWindowControl mMirrorWindowControl;
@@ -147,14 +151,19 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
mResources = mContext.getResources();
mScale = mResources.getInteger(R.integer.magnification_default_scale);
mBounceEffectDuration = mResources.getInteger(
com.android.internal.R.integer.config_shortAnimTime);
updateDimensions();
setInitialStartBounds();
computeBounceAnimationScale();
mMirrorWindowControl = mirrorWindowControl;
if (mMirrorWindowControl != null) {
mMirrorWindowControl.setWindowDelegate(this);
}
mTransaction = transaction;
setInitialStartBounds();
mGestureDetector =
new MagnificationGestureDetector(mContext, handler, this);
// Initialize listeners.
mMirrorViewRunnable = () -> {
@@ -203,6 +212,13 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
updateNavigationBarDimensions();
}
private void computeBounceAnimationScale() {
final float windowWidth = mMagnificationFrame.width() + 2 * mMirrorSurfaceMargin;
final float visibleWindowWidth = windowWidth - 2 * mOuterBorderSize;
final float animationScaleMax = windowWidth / visibleWindowWidth;
mBounceEffectAnimationScale = Math.min(animationScaleMax, ANIMATION_BOUNCE_EFFECT_SCALE);
}
private void updateNavigationBarDimensions() {
if (!supportsSwipeUpGesture()) {
mNavGestureHeight = 0;
@@ -248,6 +264,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
void onConfigurationChanged(int configDiff) {
if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) {
updateDimensions();
computeBounceAnimationScale();
if (isWindowVisible()) {
deleteWindowMagnification();
enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN);
@@ -483,20 +500,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
public boolean onTouch(View v, MotionEvent event) {
if (v == mDragView || v == mLeftDrag || v == mTopDrag || v == mRightDrag
|| v == mBottomDrag) {
return handleDragTouchEvent(event);
}
return false;
}
private boolean handleDragTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastDrag.set(event.getRawX(), event.getRawY());
return true;
case MotionEvent.ACTION_MOVE:
moveWindowMagnifier(event.getRawX() - mLastDrag.x, event.getRawY() - mLastDrag.y);
mLastDrag.set(event.getRawX(), event.getRawY());
return true;
return mGestureDetector.onTouch(event);
}
return false;
}
@@ -685,6 +689,36 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
return mPercentFormat.format(scale);
}
@Override
public boolean onSingleTap() {
animateBounceEffect();
return true;
}
@Override
public boolean onDrag(float offsetX, float offsetY) {
moveWindowMagnifier(offsetX, offsetY);
return true;
}
@Override
public boolean onStart(float x, float y) {
return true;
}
@Override
public boolean onFinish(float x, float y) {
return false;
}
private void animateBounceEffect() {
final ObjectAnimator scaleAnimator = ObjectAnimator.ofPropertyValuesHolder(mMirrorView,
PropertyValuesHolder.ofFloat(View.SCALE_X, 1, mBounceEffectAnimationScale, 1),
PropertyValuesHolder.ofFloat(View.SCALE_Y, 1, mBounceEffectAnimationScale, 1));
scaleAnimator.setDuration(mBounceEffectDuration);
scaleAnimator.start();
}
private class MirrorWindowA11yDelegate extends View.AccessibilityDelegate {
@Override

View File

@@ -26,6 +26,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
@@ -40,6 +41,7 @@ import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.os.Handler;
import android.os.SystemClock;
import android.testing.AndroidTestingRunner;
import android.testing.TestableResources;
import android.view.Display;
@@ -347,4 +349,26 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
verify(mWindowManager).updateViewLayout(eq(mMirrorView), paramsArgumentCaptor.capture());
assertEquals(newA11yWindowTitle, paramsArgumentCaptor.getValue().accessibilityTitle);
}
@Test
public void onSingleTap_enabled_scaleIsChanged() {
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
Float.NaN);
});
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.onSingleTap();
});
final long timeout = SystemClock.uptimeMillis() + 1000;
while (SystemClock.uptimeMillis() < timeout) {
SystemClock.sleep(10);
if (Float.compare(1.0f, mMirrorView.getScaleX()) < 0) {
return;
}
}
fail("mMirrorView scale is not changed");
}
}