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

Commit 34dea56b authored by Jacqueline Bronger's avatar Jacqueline Bronger
Browse files

Improve A11y for TV PiP move menu.

Will make the arrow-buttons selectable/clickable if accessibility is
turned on and adds a done button in the center. This allows for better
Talkback announcements and also allows for usage with switch access
since it doesn't depend on a DPAD.

Bug: 219887361
Test: manual - turn on talkback, launch a PiP, open menu and check that
moving the PiP works using the buttons

Change-Id: I1d5e7b37eef97ce36891d6f499ce57d32ff4895b
parent b5b54c55
Loading
Loading
Loading
Loading
+15 −0
Original line number Original line Diff line number Diff line
@@ -128,6 +128,7 @@
            android:layout_height="@dimen/pip_menu_edu_text_view_height"
            android:layout_height="@dimen/pip_menu_edu_text_view_height"
            android:layout_gravity="bottom|center"
            android:layout_gravity="bottom|center"
            android:gravity="center"
            android:gravity="center"
            android:clickable="false"
            android:paddingBottom="@dimen/pip_menu_border_width"
            android:paddingBottom="@dimen/pip_menu_border_width"
            android:text="@string/pip_edu_text"
            android:text="@string/pip_edu_text"
            android:singleLine="true"
            android:singleLine="true"
@@ -144,6 +145,16 @@
        android:layout_margin="@dimen/pip_menu_outer_space_frame"
        android:layout_margin="@dimen/pip_menu_outer_space_frame"
        android:background="@drawable/tv_pip_menu_border"/>
        android:background="@drawable/tv_pip_menu_border"/>


    <com.android.wm.shell.pip.tv.TvPipMenuActionButton
        android:id="@+id/tv_pip_menu_done_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:src="@drawable/pip_ic_close_white"
        android:visibility="gone"
        android:text="@string/a11y_action_pip_move_done" />

    <ImageView
    <ImageView
        android:id="@+id/tv_pip_menu_arrow_up"
        android:id="@+id/tv_pip_menu_arrow_up"
        android:layout_width="@dimen/pip_menu_arrow_size"
        android:layout_width="@dimen/pip_menu_arrow_size"
@@ -151,6 +162,7 @@
        android:layout_centerHorizontal="true"
        android:layout_centerHorizontal="true"
        android:layout_alignParentTop="true"
        android:layout_alignParentTop="true"
        android:alpha="0"
        android:alpha="0"
        android:contentDescription="@string/a11y_action_pip_move_up"
        android:elevation="@dimen/pip_menu_arrow_elevation"
        android:elevation="@dimen/pip_menu_arrow_elevation"
        android:src="@drawable/pip_ic_move_up" />
        android:src="@drawable/pip_ic_move_up" />


@@ -161,6 +173,7 @@
        android:layout_centerVertical="true"
        android:layout_centerVertical="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentRight="true"
        android:alpha="0"
        android:alpha="0"
        android:contentDescription="@string/a11y_action_pip_move_right"
        android:elevation="@dimen/pip_menu_arrow_elevation"
        android:elevation="@dimen/pip_menu_arrow_elevation"
        android:src="@drawable/pip_ic_move_right" />
        android:src="@drawable/pip_ic_move_right" />


@@ -171,6 +184,7 @@
        android:layout_centerHorizontal="true"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:layout_alignParentBottom="true"
        android:alpha="0"
        android:alpha="0"
        android:contentDescription="@string/a11y_action_pip_move_down"
        android:elevation="@dimen/pip_menu_arrow_elevation"
        android:elevation="@dimen/pip_menu_arrow_elevation"
        android:src="@drawable/pip_ic_move_down" />
        android:src="@drawable/pip_ic_move_down" />


@@ -181,6 +195,7 @@
        android:layout_centerVertical="true"
        android:layout_centerVertical="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentLeft="true"
        android:alpha="0"
        android:alpha="0"
        android:contentDescription="@string/a11y_action_pip_move_left"
        android:elevation="@dimen/pip_menu_arrow_elevation"
        android:elevation="@dimen/pip_menu_arrow_elevation"
        android:src="@drawable/pip_ic_move_left" />
        android:src="@drawable/pip_ic_move_left" />
</RelativeLayout>
</RelativeLayout>
+50 −4
Original line number Original line Diff line number Diff line
@@ -43,6 +43,7 @@ import android.view.SurfaceControl;
import android.view.View;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.view.ViewRootImpl;
import android.view.accessibility.AccessibilityManager;
import android.widget.FrameLayout;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.ImageView;
@@ -65,7 +66,7 @@ import java.util.List;
/**
/**
 * A View that represents Pip Menu on TV. It's responsible for displaying 3 ever-present Pip Menu
 * A View that represents Pip Menu on TV. It's responsible for displaying 3 ever-present Pip Menu
 * actions: Fullscreen, Move and Close, but could also display "additional" actions, that may be set
 * actions: Fullscreen, Move and Close, but could also display "additional" actions, that may be set
 * via a {@link #setAdditionalActions(List, Handler)} call.
 * via a {@link #setAdditionalActions(List, RemoteAction, Handler)} call.
 */
 */
public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
    private static final String TAG = "TvPipMenuView";
    private static final String TAG = "TvPipMenuView";
@@ -93,6 +94,7 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
    private final ImageView mArrowRight;
    private final ImageView mArrowRight;
    private final ImageView mArrowDown;
    private final ImageView mArrowDown;
    private final ImageView mArrowLeft;
    private final ImageView mArrowLeft;
    private final TvPipMenuActionButton mA11yDoneButton;


    private final ScrollView mScrollView;
    private final ScrollView mScrollView;
    private final HorizontalScrollView mHorizontalScrollView;
    private final HorizontalScrollView mHorizontalScrollView;
@@ -110,6 +112,8 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
    private final int mPipMenuFadeAnimationDuration;
    private final int mPipMenuFadeAnimationDuration;
    private final int mResizeAnimationDuration;
    private final int mResizeAnimationDuration;


    private final AccessibilityManager mA11yManager;

    public TvPipMenuView(@NonNull Context context) {
    public TvPipMenuView(@NonNull Context context) {
        this(context, null);
        this(context, null);
    }
    }
@@ -128,6 +132,8 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {


        inflate(context, R.layout.tv_pip_menu, this);
        inflate(context, R.layout.tv_pip_menu, this);


        mA11yManager = context.getSystemService(AccessibilityManager.class);

        mActionButtonsContainer = findViewById(R.id.tv_pip_menu_action_buttons);
        mActionButtonsContainer = findViewById(R.id.tv_pip_menu_action_buttons);
        mActionButtonsContainer.findViewById(R.id.tv_pip_menu_fullscreen_button)
        mActionButtonsContainer.findViewById(R.id.tv_pip_menu_fullscreen_button)
                .setOnClickListener(this);
                .setOnClickListener(this);
@@ -152,6 +158,7 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
        mArrowRight = findViewById(R.id.tv_pip_menu_arrow_right);
        mArrowRight = findViewById(R.id.tv_pip_menu_arrow_right);
        mArrowDown = findViewById(R.id.tv_pip_menu_arrow_down);
        mArrowDown = findViewById(R.id.tv_pip_menu_arrow_down);
        mArrowLeft = findViewById(R.id.tv_pip_menu_arrow_left);
        mArrowLeft = findViewById(R.id.tv_pip_menu_arrow_left);
        mA11yDoneButton = findViewById(R.id.tv_pip_menu_done_button);


        mEduTextView = findViewById(R.id.tv_pip_menu_edu_text);
        mEduTextView = findViewById(R.id.tv_pip_menu_edu_text);
        mEduTextContainerView = findViewById(R.id.tv_pip_menu_edu_text_container);
        mEduTextContainerView = findViewById(R.id.tv_pip_menu_edu_text_container);
@@ -454,6 +461,9 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
        showButtonsMenu(false);
        showButtonsMenu(false);
        showMovementHints(gravity);
        showMovementHints(gravity);
        setFrameHighlighted(true);
        setFrameHighlighted(true);

        mHorizontalScrollView.setFocusable(false);
        mScrollView.setFocusable(false);
    }
    }


    void showButtonsMenu() {
    void showButtonsMenu() {
@@ -468,6 +478,9 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
        hideMovementHints();
        hideMovementHints();
        setFrameHighlighted(true);
        setFrameHighlighted(true);


        mHorizontalScrollView.setFocusable(true);
        mScrollView.setFocusable(true);

        // Always focus on the first button when opening the menu, except directly after moving.
        // Always focus on the first button when opening the menu, except directly after moving.
        if (mFocusedButton == null) {
        if (mFocusedButton == null) {
            // Focus on first button (there is a Space at position 0)
            // Focus on first button (there is a Space at position 0)
@@ -655,10 +668,16 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
                mFocusedButton = mActionButtonsContainer.getFocusedChild();
                mFocusedButton = mActionButtonsContainer.getFocusedChild();
            }
            }


            switch (event.getKeyCode()) {
            if (event.getKeyCode() == KEYCODE_BACK) {
                case KEYCODE_BACK:
                mListener.onBackPress();
                mListener.onBackPress();
                return true;
                return true;
            }

            if (mA11yManager.isEnabled()) {
                return super.dispatchKeyEvent(event);
            }

            switch (event.getKeyCode()) {
                case KEYCODE_DPAD_UP:
                case KEYCODE_DPAD_UP:
                case KEYCODE_DPAD_DOWN:
                case KEYCODE_DPAD_DOWN:
                case KEYCODE_DPAD_LEFT:
                case KEYCODE_DPAD_LEFT:
@@ -688,6 +707,32 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
        animateAlphaTo(checkGravity(gravity, Gravity.TOP) ? 1f : 0f, mArrowDown);
        animateAlphaTo(checkGravity(gravity, Gravity.TOP) ? 1f : 0f, mArrowDown);
        animateAlphaTo(checkGravity(gravity, Gravity.RIGHT) ? 1f : 0f, mArrowLeft);
        animateAlphaTo(checkGravity(gravity, Gravity.RIGHT) ? 1f : 0f, mArrowLeft);
        animateAlphaTo(checkGravity(gravity, Gravity.LEFT) ? 1f : 0f, mArrowRight);
        animateAlphaTo(checkGravity(gravity, Gravity.LEFT) ? 1f : 0f, mArrowRight);

        boolean a11yEnabled = mA11yManager.isEnabled();
        setArrowA11yEnabled(mArrowUp, a11yEnabled, KEYCODE_DPAD_UP);
        setArrowA11yEnabled(mArrowDown, a11yEnabled, KEYCODE_DPAD_DOWN);
        setArrowA11yEnabled(mArrowLeft, a11yEnabled, KEYCODE_DPAD_LEFT);
        setArrowA11yEnabled(mArrowRight, a11yEnabled, KEYCODE_DPAD_RIGHT);

        animateAlphaTo(a11yEnabled ? 1f : 0f, mA11yDoneButton);
        if (a11yEnabled) {
            mA11yDoneButton.setOnClickListener(v -> {
                if (mListener != null) {
                    mListener.onExitMoveMode();
                }
            });
        }
    }

    private void setArrowA11yEnabled(View arrowView, boolean enabled, int keycode) {
        arrowView.setClickable(enabled);
        if (enabled) {
            arrowView.setOnClickListener(v -> {
                if (mListener != null) {
                    mListener.onPipMovement(keycode);
                }
            });
        }
    }
    }


    private boolean checkGravity(int gravity, int feature) {
    private boolean checkGravity(int gravity, int feature) {
@@ -706,6 +751,7 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
        animateAlphaTo(0, mArrowRight);
        animateAlphaTo(0, mArrowRight);
        animateAlphaTo(0, mArrowDown);
        animateAlphaTo(0, mArrowDown);
        animateAlphaTo(0, mArrowLeft);
        animateAlphaTo(0, mArrowLeft);
        animateAlphaTo(0, mA11yDoneButton);
    }
    }


    /**
    /**