Add new floating action menu for Accessibility targets. (5/n)
Action:
AccessibilityFloatingMenu has two shape types, one is oval style, the other is half oval style.
- Half oval shape when dragging.
- Oval shape when dropping.
The patch will provide the capability of switch shape type by dragging into the screen edge or out.
Cherry picked from commit 0a2e8f9a56
Bug: 173958541
Test: atest AccessibilityFloatingMenuTest
AccessibilityFloatingMenuViewTest AccessibilityTargetAdapterTest
Change-Id: Ib86713cd6a48e102cb9088beb6353391caeadc83
Merged-In: Ib86713cd6a48e102cb9088beb6353391caeadc83
This commit is contained in:
@@ -43,9 +43,10 @@ public class AccessibilityFloatingMenu implements IAccessibilityFloatingMenu {
|
||||
private static final float DEFAULT_OPACITY_VALUE = 0.55f;
|
||||
private final Context mContext;
|
||||
private final AccessibilityFloatingMenuView mMenuView;
|
||||
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
private final ContentObserver mContentObserver =
|
||||
new ContentObserver(new Handler(Looper.getMainLooper())) {
|
||||
new ContentObserver(mHandler) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
mMenuView.onTargetsChanged(getTargets(mContext, ACCESSIBILITY_BUTTON));
|
||||
@@ -53,23 +54,15 @@ public class AccessibilityFloatingMenu implements IAccessibilityFloatingMenu {
|
||||
};
|
||||
|
||||
private final ContentObserver mSizeContentObserver =
|
||||
new ContentObserver(new Handler(Looper.getMainLooper())) {
|
||||
new ContentObserver(mHandler) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
mMenuView.setSizeType(getSizeType(mContext));
|
||||
}
|
||||
};
|
||||
|
||||
private final ContentObserver mShapeContentObserver =
|
||||
new ContentObserver(new Handler(Looper.getMainLooper())) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
mMenuView.setShapeType(getShapeType(mContext));
|
||||
}
|
||||
};
|
||||
|
||||
private final ContentObserver mFadeOutContentObserver =
|
||||
new ContentObserver(new Handler(Looper.getMainLooper())) {
|
||||
new ContentObserver(mHandler) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
mMenuView.updateOpacityWith(isFadeEffectEnabled(mContext),
|
||||
@@ -152,10 +145,6 @@ public class AccessibilityFloatingMenu implements IAccessibilityFloatingMenu {
|
||||
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE),
|
||||
/* notifyForDescendants */ false, mSizeContentObserver,
|
||||
UserHandle.USER_CURRENT);
|
||||
mContext.getContentResolver().registerContentObserver(
|
||||
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_ICON_TYPE),
|
||||
/* notifyForDescendants */ false, mShapeContentObserver,
|
||||
UserHandle.USER_CURRENT);
|
||||
mContext.getContentResolver().registerContentObserver(
|
||||
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED),
|
||||
/* notifyForDescendants */ false, mFadeOutContentObserver,
|
||||
@@ -169,7 +158,6 @@ public class AccessibilityFloatingMenu implements IAccessibilityFloatingMenu {
|
||||
private void unregisterContentObservers() {
|
||||
mContext.getContentResolver().unregisterContentObserver(mContentObserver);
|
||||
mContext.getContentResolver().unregisterContentObserver(mSizeContentObserver);
|
||||
mContext.getContentResolver().unregisterContentObserver(mShapeContentObserver);
|
||||
mContext.getContentResolver().unregisterContentObserver(mFadeOutContentObserver);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,10 @@ public class AccessibilityFloatingMenuView extends FrameLayout
|
||||
private int mAlignment = Alignment.RIGHT;
|
||||
@SizeType
|
||||
private int mSizeType = SizeType.SMALL;
|
||||
@VisibleForTesting
|
||||
@ShapeType
|
||||
private int mShapeType = ShapeType.OVAL;
|
||||
int mShapeType = ShapeType.OVAL;
|
||||
private int mTemporaryShapeType;
|
||||
@RadiusType
|
||||
private int mRadiusType = RadiusType.LEFT_HALF_OVAL;
|
||||
private int mMargin;
|
||||
@@ -185,7 +187,6 @@ public class AccessibilityFloatingMenuView extends FrameLayout
|
||||
|
||||
updateLocationWith(mAlignment, mPercentageY);
|
||||
updateMarginsWith(mAlignment);
|
||||
updateOffsetWith(mShapeType, mAlignment);
|
||||
|
||||
updateInsetWith(getResources().getConfiguration().uiMode, mAlignment);
|
||||
|
||||
@@ -228,6 +229,10 @@ public class AccessibilityFloatingMenuView extends FrameLayout
|
||||
setInset(0, 0);
|
||||
}
|
||||
|
||||
mTemporaryShapeType =
|
||||
isMovingTowardsScreenEdge(mAlignment, currentRawX, mDownX)
|
||||
? ShapeType.HALF_OVAL
|
||||
: ShapeType.OVAL;
|
||||
final int newWindowX = currentRawX + mRelativeToPointerDownX;
|
||||
final int newWindowY = currentRawY + mRelativeToPointerDownY;
|
||||
mCurrentLayoutParams.x = constrain(newWindowX, MIN_WINDOW_X, getMaxWindowX());
|
||||
@@ -246,10 +251,19 @@ public class AccessibilityFloatingMenuView extends FrameLayout
|
||||
final int endY = mCurrentLayoutParams.y;
|
||||
snapToLocation(endX, endY);
|
||||
|
||||
setShapeType(mTemporaryShapeType);
|
||||
|
||||
// Avoid triggering the listener of the item.
|
||||
return true;
|
||||
}
|
||||
updateOffsetWith(mShapeType, mAlignment);
|
||||
|
||||
// Must switch the oval shape type before tapping the corresponding item in the
|
||||
// list view, otherwise it can't work on it.
|
||||
if (mShapeType == ShapeType.HALF_OVAL) {
|
||||
setShapeType(ShapeType.OVAL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fadeOut();
|
||||
break;
|
||||
@@ -393,6 +407,11 @@ public class AccessibilityFloatingMenuView extends FrameLayout
|
||||
return mListView.dispatchTouchEvent(event);
|
||||
}
|
||||
|
||||
private boolean isMovingTowardsScreenEdge(@Alignment int side, int currentRawX, int downX) {
|
||||
return (side == Alignment.RIGHT && currentRawX > downX)
|
||||
|| (side == Alignment.LEFT && downX > currentRawX);
|
||||
}
|
||||
|
||||
private boolean hasExceededTouchSlop(int startX, int startY, int endX, int endY) {
|
||||
return (sq(endX - startX) + sq(endY - startY)) > mSquareScaledTouchSlop;
|
||||
}
|
||||
|
||||
@@ -306,6 +306,39 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase {
|
||||
/* newWindowY = screenCenterY - offsetY */ mScreenHalfHeight - mMenuHalfHeight);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void tapOnAndDragMenuToScreenSide_transformShapeHalfOval() {
|
||||
mMenuView.show();
|
||||
mMenuView.onTargetsChanged(mTargets);
|
||||
mMenuView.setSizeType(0);
|
||||
mMenuView.setShapeType(/* oval */ 0);
|
||||
final int currentWindowX = mMenuView.mCurrentLayoutParams.x;
|
||||
final int currentWindowY = mMenuView.mCurrentLayoutParams.y;
|
||||
final MotionEvent downEvent =
|
||||
mMotionEventHelper.obtainMotionEvent(0, 1,
|
||||
MotionEvent.ACTION_DOWN,
|
||||
currentWindowX + /* offsetXToMenuCenterX */ mMenuHalfWidth,
|
||||
currentWindowY + /* offsetYToMenuCenterY */ mMenuHalfHeight);
|
||||
final MotionEvent moveEvent =
|
||||
mMotionEventHelper.obtainMotionEvent(2, 3,
|
||||
MotionEvent.ACTION_MOVE,
|
||||
/* downX */(currentWindowX + mMenuHalfWidth)
|
||||
+ /* offsetXToScreenRightSide */ mMenuHalfWidth,
|
||||
/* downY */ (currentWindowY + mMenuHalfHeight));
|
||||
final MotionEvent upEvent =
|
||||
mMotionEventHelper.obtainMotionEvent(4, 5,
|
||||
MotionEvent.ACTION_UP,
|
||||
/* downX */(currentWindowX + mMenuHalfWidth)
|
||||
+ /* offsetXToScreenRightSide */ mMenuHalfWidth,
|
||||
/* downY */ (currentWindowY + mMenuHalfHeight));
|
||||
mListView.dispatchTouchEvent(downEvent);
|
||||
mListView.dispatchTouchEvent(moveEvent);
|
||||
mListView.dispatchTouchEvent(upEvent);
|
||||
|
||||
assertThat(mMenuView.mShapeType).isEqualTo(/* halfOval */ 1);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
mInterceptMotionEvent = null;
|
||||
|
||||
Reference in New Issue
Block a user