Merge "Magnification button applies fade-in and fade-out animation"
This commit is contained in:
@@ -46,9 +46,15 @@ import com.android.systemui.R;
|
||||
*/
|
||||
class MagnificationModeSwitch {
|
||||
|
||||
private static final int DURATION_MS = 5000;
|
||||
private static final int START_DELAY_MS = 3000;
|
||||
private final Runnable mAnimationTask;
|
||||
@VisibleForTesting
|
||||
static final long FADING_ANIMATION_DURATION_MS = 300;
|
||||
private static final int DEFAULT_FADE_OUT_ANIMATION_DELAY_MS = 3000;
|
||||
// The button visible duration starting from the last showButton() called.
|
||||
private int mVisibleDuration = DEFAULT_FADE_OUT_ANIMATION_DELAY_MS;
|
||||
private final Runnable mFadeInAnimationTask;
|
||||
private final Runnable mFadeOutAnimationTask;
|
||||
@VisibleForTesting
|
||||
boolean mIsFadeOutAnimating = false;
|
||||
|
||||
private final Context mContext;
|
||||
private final WindowManager mWindowManager;
|
||||
@@ -100,12 +106,19 @@ class MagnificationModeSwitch {
|
||||
}
|
||||
});
|
||||
|
||||
mAnimationTask = () -> {
|
||||
mFadeInAnimationTask = () -> {
|
||||
mImageView.animate()
|
||||
.alpha(1f)
|
||||
.setDuration(FADING_ANIMATION_DURATION_MS)
|
||||
.start();
|
||||
};
|
||||
mFadeOutAnimationTask = () -> {
|
||||
mImageView.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(DURATION_MS)
|
||||
.setDuration(FADING_ANIMATION_DURATION_MS)
|
||||
.withEndAction(() -> removeButton())
|
||||
.start();
|
||||
mIsFadeOutAnimating = true;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -128,7 +141,6 @@ class MagnificationModeSwitch {
|
||||
}
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mImageView.setAlpha(1.0f);
|
||||
mImageView.animate().cancel();
|
||||
mLastDown.set(event.getRawX(), event.getRawY());
|
||||
mLastDrag.set(event.getRawX(), event.getRawY());
|
||||
@@ -169,9 +181,13 @@ class MagnificationModeSwitch {
|
||||
if (!mIsVisible) {
|
||||
return;
|
||||
}
|
||||
mImageView.animate().cancel();
|
||||
mWindowManager.removeView(mImageView);
|
||||
// Reset button status.
|
||||
mImageView.removeCallbacks(mFadeInAnimationTask);
|
||||
mImageView.removeCallbacks(mFadeOutAnimationTask);
|
||||
mImageView.animate().cancel();
|
||||
mIsFadeOutAnimating = false;
|
||||
mImageView.setAlpha(0f);
|
||||
mWindowManager.removeView(mImageView);
|
||||
mIsVisible = false;
|
||||
mParams.x = 0;
|
||||
mParams.y = 0;
|
||||
@@ -185,14 +201,15 @@ class MagnificationModeSwitch {
|
||||
if (!mIsVisible) {
|
||||
mWindowManager.addView(mImageView, mParams);
|
||||
mIsVisible = true;
|
||||
mImageView.postOnAnimation(mFadeInAnimationTask);
|
||||
}
|
||||
mImageView.setAlpha(1.0f);
|
||||
// TODO(b/143852371): use accessibility timeout as a delay.
|
||||
// Dismiss the magnification switch button after the button is displayed for a period of
|
||||
// time.
|
||||
mImageView.animate().cancel();
|
||||
mImageView.removeCallbacks(mAnimationTask);
|
||||
mImageView.postDelayed(mAnimationTask, START_DELAY_MS);
|
||||
if (mIsFadeOutAnimating) {
|
||||
mImageView.animate().cancel();
|
||||
mImageView.setAlpha(1f);
|
||||
}
|
||||
// Refresh the time slot of the fade-out task whenever this method is called.
|
||||
mImageView.removeCallbacks(mFadeOutAnimationTask);
|
||||
mImageView.postOnAnimationDelayed(mFadeOutAnimationTask, mVisibleDuration);
|
||||
}
|
||||
|
||||
void onConfigurationChanged(int configDiff) {
|
||||
@@ -222,6 +239,7 @@ class MagnificationModeSwitch {
|
||||
imageView.setClickable(true);
|
||||
imageView.setFocusable(true);
|
||||
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
|
||||
imageView.setAlpha(0f);
|
||||
return imageView;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import static android.view.MotionEvent.ACTION_MOVE;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK;
|
||||
|
||||
import static com.android.systemui.accessibility.MagnificationModeSwitch.FADING_ANIMATION_DURATION_MS;
|
||||
import static com.android.systemui.accessibility.MagnificationModeSwitch.getIconResId;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
@@ -35,7 +36,6 @@ import static org.mockito.ArgumentMatchers.anyFloat;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -69,6 +69,9 @@ import org.mockito.MockitoAnnotations;
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class MagnificationModeSwitchTest extends SysuiTestCase {
|
||||
|
||||
private static final float FADE_IN_ALPHA = 1f;
|
||||
private static final float FADE_OUT_ALPHA = 0f;
|
||||
|
||||
private ImageView mSpyImageView;
|
||||
@Mock
|
||||
private WindowManager mWindowManager;
|
||||
@@ -87,49 +90,47 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
|
||||
).when(mWindowManager).getMaximumWindowMetrics();
|
||||
mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
|
||||
mSpyImageView = Mockito.spy(new ImageView(mContext));
|
||||
doAnswer(invocation -> null).when(mSpyImageView).setOnTouchListener(
|
||||
mTouchListenerCaptor.capture());
|
||||
initMockImageViewAndAnimator();
|
||||
resetMockImageViewAndAnimator();
|
||||
|
||||
mMagnificationModeSwitch = new MagnificationModeSwitch(mContext, mSpyImageView);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeButton_removeView() {
|
||||
public void removeButton_buttonIsShowing_removeView() {
|
||||
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
|
||||
|
||||
mMagnificationModeSwitch.removeButton();
|
||||
|
||||
verify(mWindowManager).removeView(mSpyImageView);
|
||||
// First invocation is in showButton.
|
||||
verify(mViewPropertyAnimator, times(2)).cancel();
|
||||
verify(mViewPropertyAnimator).cancel();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showWindowModeButton_fullscreenMode_addViewAndSetImageResource() {
|
||||
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
|
||||
|
||||
verify(mSpyImageView).setAlpha(1.0f);
|
||||
verify(mSpyImageView).setImageResource(
|
||||
getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW));
|
||||
assertShowButtonAnimation();
|
||||
assertShowFadingAnimation(FADE_IN_ALPHA);
|
||||
assertShowFadingAnimation(FADE_OUT_ALPHA);
|
||||
|
||||
ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
|
||||
verify(mViewPropertyAnimator).withEndAction(captor.capture());
|
||||
verify(mWindowManager).addView(eq(mSpyImageView), any(WindowManager.LayoutParams.class));
|
||||
|
||||
captor.getValue().run();
|
||||
|
||||
// First invocation is in showButton.
|
||||
verify(mViewPropertyAnimator, times(2)).cancel();
|
||||
verify(mViewPropertyAnimator).cancel();
|
||||
verify(mWindowManager).removeView(mSpyImageView);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onConfigurationChanged_setImageResource() {
|
||||
public void onConfigurationChanged_buttonIsShowing_setImageResource() {
|
||||
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
|
||||
resetMockImageViewAndAnimator();
|
||||
|
||||
mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY);
|
||||
|
||||
verify(mSpyImageView, times(2)).setImageResource(
|
||||
verify(mSpyImageView).setImageResource(
|
||||
getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN));
|
||||
}
|
||||
|
||||
@@ -162,7 +163,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
|
||||
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
|
||||
listener.onTouch(mSpyImageView, MotionEvent.obtain(
|
||||
0, 0, ACTION_DOWN, 100, 100, 0));
|
||||
verify(mSpyImageView).setAlpha(1.0f);
|
||||
verify(mViewPropertyAnimator).cancel();
|
||||
|
||||
listener.onTouch(mSpyImageView, MotionEvent.obtain(
|
||||
@@ -173,9 +173,8 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
|
||||
resetMockImageViewAndAnimator();
|
||||
listener.onTouch(mSpyImageView, MotionEvent.obtain(
|
||||
0, ViewConfiguration.getTapTimeout() + 10, ACTION_UP, 100 + offset, 100, 0));
|
||||
verify(mSpyImageView).setAlpha(1.0f);
|
||||
assertModeUnchanged(previousMode);
|
||||
assertShowButtonAnimation();
|
||||
assertShowFadingAnimation(FADE_OUT_ALPHA);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -193,9 +192,8 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
|
||||
resetMockImageViewAndAnimator();
|
||||
listener.onTouch(mSpyImageView, MotionEvent.obtain(
|
||||
0, ViewConfiguration.getTapTimeout(), ACTION_CANCEL, 100, 100, 0));
|
||||
verify(mSpyImageView).setAlpha(1.0f);
|
||||
assertModeUnchanged(previousMode);
|
||||
assertShowButtonAnimation();
|
||||
assertShowFadingAnimation(FADE_OUT_ALPHA);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -216,9 +214,8 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
|
||||
resetMockImageViewAndAnimator();
|
||||
listener.onTouch(mSpyImageView, MotionEvent.obtain(
|
||||
0, ViewConfiguration.getTapTimeout(), ACTION_CANCEL, 100 + offset, 100, 0));
|
||||
verify(mSpyImageView).setAlpha(1.0f);
|
||||
assertModeUnchanged(previousMode);
|
||||
assertShowButtonAnimation();
|
||||
assertShowFadingAnimation(FADE_OUT_ALPHA);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -249,37 +246,55 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
|
||||
verifyTapAction(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showButton_showFadeOutAnimation_fadeOutAnimationCanceled() {
|
||||
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
|
||||
assertShowFadingAnimation(FADE_OUT_ALPHA);
|
||||
resetMockImageViewAndAnimator();
|
||||
|
||||
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
|
||||
|
||||
verify(mViewPropertyAnimator).cancel();
|
||||
assertEquals(1f, mSpyImageView.getAlpha());
|
||||
assertShowFadingAnimation(FADE_OUT_ALPHA);
|
||||
}
|
||||
|
||||
private void assertModeUnchanged(int expectedMode) {
|
||||
final int actualMode = Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
|
||||
assertEquals(expectedMode, actualMode);
|
||||
}
|
||||
|
||||
private void assertShowButtonAnimation() {
|
||||
verify(mViewPropertyAnimator).cancel();
|
||||
verify(mViewPropertyAnimator).setDuration(anyLong());
|
||||
verify(mViewPropertyAnimator).alpha(anyFloat());
|
||||
private void assertShowFadingAnimation(float alpha) {
|
||||
ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
|
||||
if (alpha == FADE_IN_ALPHA) { // Fade-in
|
||||
verify(mSpyImageView).postOnAnimation(runnableCaptor.capture());
|
||||
} else { // Fade-out
|
||||
verify(mSpyImageView).postOnAnimationDelayed(runnableCaptor.capture(), anyLong());
|
||||
}
|
||||
resetMockAnimator();
|
||||
|
||||
runnableCaptor.getValue().run();
|
||||
|
||||
verify(mViewPropertyAnimator).setDuration(eq(FADING_ANIMATION_DURATION_MS));
|
||||
verify(mViewPropertyAnimator).alpha(alpha);
|
||||
verify(mViewPropertyAnimator).start();
|
||||
}
|
||||
|
||||
private void initMockImageViewAndAnimator() {
|
||||
private void resetMockImageViewAndAnimator() {
|
||||
Mockito.reset(mSpyImageView);
|
||||
doAnswer(invocation -> null).when(mSpyImageView).setOnTouchListener(
|
||||
mTouchListenerCaptor.capture());
|
||||
resetMockAnimator();
|
||||
}
|
||||
|
||||
private void resetMockAnimator() {
|
||||
Mockito.reset(mViewPropertyAnimator);
|
||||
when(mViewPropertyAnimator.setDuration(anyLong())).thenReturn(mViewPropertyAnimator);
|
||||
when(mViewPropertyAnimator.alpha(anyFloat())).thenReturn(mViewPropertyAnimator);
|
||||
when(mViewPropertyAnimator.withEndAction(any(Runnable.class))).thenReturn(
|
||||
mViewPropertyAnimator);
|
||||
|
||||
when(mSpyImageView.animate()).thenReturn(mViewPropertyAnimator);
|
||||
doAnswer(invocation -> {
|
||||
Runnable run = invocation.getArgument(0);
|
||||
run.run();
|
||||
return null;
|
||||
}).when(mSpyImageView).postDelayed(any(), anyLong());
|
||||
}
|
||||
|
||||
private void resetMockImageViewAndAnimator() {
|
||||
Mockito.reset(mViewPropertyAnimator);
|
||||
Mockito.reset(mSpyImageView);
|
||||
initMockImageViewAndAnimator();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user