Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b682704 authored by Peter_Liang's avatar Peter_Liang
Browse files

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 0a2e8f9a

Bug: 173958541
Test: atest AccessibilityFloatingMenuTest
AccessibilityFloatingMenuViewTest AccessibilityTargetAdapterTest

Change-Id: Ib86713cd6a48e102cb9088beb6353391caeadc83
Merged-In: Ib86713cd6a48e102cb9088beb6353391caeadc83
parent 2f5db393
Loading
Loading
Loading
Loading
+4 −16
Original line number Diff line number Diff line
@@ -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);
    }
}
+22 −3
Original line number Diff line number Diff line
@@ -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;
    }
+33 −0
Original line number Diff line number Diff line
@@ -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;