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
This commit is contained in:
Jacqueline Bronger
2022-05-25 16:10:39 +02:00
parent b5b54c55b9
commit 34dea56b20
2 changed files with 65 additions and 4 deletions

View File

@@ -128,6 +128,7 @@
android:layout_height="@dimen/pip_menu_edu_text_view_height"
android:layout_gravity="bottom|center"
android:gravity="center"
android:clickable="false"
android:paddingBottom="@dimen/pip_menu_border_width"
android:text="@string/pip_edu_text"
android:singleLine="true"
@@ -144,6 +145,16 @@
android:layout_margin="@dimen/pip_menu_outer_space_frame"
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
android:id="@+id/tv_pip_menu_arrow_up"
android:layout_width="@dimen/pip_menu_arrow_size"
@@ -151,6 +162,7 @@
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
android:alpha="0"
android:contentDescription="@string/a11y_action_pip_move_up"
android:elevation="@dimen/pip_menu_arrow_elevation"
android:src="@drawable/pip_ic_move_up" />
@@ -161,6 +173,7 @@
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:alpha="0"
android:contentDescription="@string/a11y_action_pip_move_right"
android:elevation="@dimen/pip_menu_arrow_elevation"
android:src="@drawable/pip_ic_move_right" />
@@ -171,6 +184,7 @@
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:alpha="0"
android:contentDescription="@string/a11y_action_pip_move_down"
android:elevation="@dimen/pip_menu_arrow_elevation"
android:src="@drawable/pip_ic_move_down" />
@@ -181,6 +195,7 @@
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:alpha="0"
android:contentDescription="@string/a11y_action_pip_move_left"
android:elevation="@dimen/pip_menu_arrow_elevation"
android:src="@drawable/pip_ic_move_left" />
</RelativeLayout>

View File

@@ -43,6 +43,7 @@ import android.view.SurfaceControl;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.view.accessibility.AccessibilityManager;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
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
* 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 {
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 mArrowDown;
private final ImageView mArrowLeft;
private final TvPipMenuActionButton mA11yDoneButton;
private final ScrollView mScrollView;
private final HorizontalScrollView mHorizontalScrollView;
@@ -110,6 +112,8 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
private final int mPipMenuFadeAnimationDuration;
private final int mResizeAnimationDuration;
private final AccessibilityManager mA11yManager;
public TvPipMenuView(@NonNull Context context) {
this(context, null);
}
@@ -128,6 +132,8 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
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_fullscreen_button)
.setOnClickListener(this);
@@ -152,6 +158,7 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
mArrowRight = findViewById(R.id.tv_pip_menu_arrow_right);
mArrowDown = findViewById(R.id.tv_pip_menu_arrow_down);
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);
mEduTextContainerView = findViewById(R.id.tv_pip_menu_edu_text_container);
@@ -454,6 +461,9 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
showButtonsMenu(false);
showMovementHints(gravity);
setFrameHighlighted(true);
mHorizontalScrollView.setFocusable(false);
mScrollView.setFocusable(false);
}
void showButtonsMenu() {
@@ -468,6 +478,9 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
hideMovementHints();
setFrameHighlighted(true);
mHorizontalScrollView.setFocusable(true);
mScrollView.setFocusable(true);
// Always focus on the first button when opening the menu, except directly after moving.
if (mFocusedButton == null) {
// 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();
}
if (event.getKeyCode() == KEYCODE_BACK) {
mListener.onBackPress();
return true;
}
if (mA11yManager.isEnabled()) {
return super.dispatchKeyEvent(event);
}
switch (event.getKeyCode()) {
case KEYCODE_BACK:
mListener.onBackPress();
return true;
case KEYCODE_DPAD_UP:
case KEYCODE_DPAD_DOWN:
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.RIGHT) ? 1f : 0f, mArrowLeft);
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) {
@@ -706,6 +751,7 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
animateAlphaTo(0, mArrowRight);
animateAlphaTo(0, mArrowDown);
animateAlphaTo(0, mArrowLeft);
animateAlphaTo(0, mA11yDoneButton);
}
/**