Add content descriptions for accessibility
Also fixes the tap-to-dismiss region Bug: 218308984 Bug: 217926688 Fix: 217926688 Test: manual (tested with talkback on) Change-Id: I691c6e1bfd4c54510c9cf7ae4dd90c5a4624ee51
This commit is contained in:
@@ -2390,4 +2390,10 @@
|
||||
<string name="clipboard_edit_source">From <xliff:g id="appName" example="Gmail">%1$s</xliff:g></string>
|
||||
<!-- Label for button to dismiss clipboard overlay [CHAR LIMIT=NONE] -->
|
||||
<string name="clipboard_dismiss_description">Dismiss copy UI</string>
|
||||
<!-- Label for button to edit text that was copied to the clipboard [CHAR LIMIT=NONE] -->
|
||||
<string name="clipboard_edit_text_description">Edit copied text</string>
|
||||
<!-- Label for button to edit an image that was copied to the clipboard [CHAR LIMIT=NONE] -->
|
||||
<string name="clipboard_edit_image_description">Edit copied image</string>
|
||||
<!-- Label for button to send copied content to a nearby device [CHAR LIMIT=NONE] -->
|
||||
<string name="clipboard_send_nearby_description">Send to nearby device</string>
|
||||
</resources>
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.android.systemui.clipboardoverlay;
|
||||
import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS;
|
||||
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
@@ -40,6 +39,7 @@ import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.input.InputManager;
|
||||
@@ -47,11 +47,11 @@ import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Looper;
|
||||
import android.text.TextUtils;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayCutout;
|
||||
import android.view.Gravity;
|
||||
import android.view.InputEvent;
|
||||
import android.view.InputEventReceiver;
|
||||
import android.view.InputMonitor;
|
||||
@@ -93,9 +93,11 @@ public class ClipboardOverlayController {
|
||||
public static final String COPY_OVERLAY_ACTION = "com.android.systemui.COPY";
|
||||
|
||||
private static final int CLIPBOARD_DEFAULT_TIMEOUT_MILLIS = 6000;
|
||||
private static final int SWIPE_PADDING_DP = 12; // extra padding around views to allow swipe
|
||||
|
||||
private final Context mContext;
|
||||
private final DisplayManager mDisplayManager;
|
||||
private final DisplayMetrics mDisplayMetrics;
|
||||
private final WindowManager mWindowManager;
|
||||
private final WindowManager.LayoutParams mWindowLayoutParams;
|
||||
private final PhoneWindow mWindow;
|
||||
@@ -107,6 +109,7 @@ public class ClipboardOverlayController {
|
||||
private final DraggableConstraintLayout mView;
|
||||
private final ImageView mImagePreview;
|
||||
private final TextView mTextPreview;
|
||||
private final View mPreviewBorder;
|
||||
private final OverlayActionChip mEditChip;
|
||||
private final OverlayActionChip mRemoteCopyChip;
|
||||
private final View mActionContainerBackground;
|
||||
@@ -136,18 +139,24 @@ public class ClipboardOverlayController {
|
||||
|
||||
mWindowManager = mContext.getSystemService(WindowManager.class);
|
||||
|
||||
mDisplayMetrics = new DisplayMetrics();
|
||||
mContext.getDisplay().getRealMetrics(mDisplayMetrics);
|
||||
|
||||
mTimeoutHandler = timeoutHandler;
|
||||
mTimeoutHandler.setDefaultTimeoutMillis(CLIPBOARD_DEFAULT_TIMEOUT_MILLIS);
|
||||
|
||||
// Setup the window that we are going to use
|
||||
mWindowLayoutParams = FloatingWindowUtil.getFloatingWindowParams();
|
||||
mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
mWindowLayoutParams.height = WRAP_CONTENT;
|
||||
mWindowLayoutParams.gravity = Gravity.BOTTOM;
|
||||
mWindowLayoutParams.setTitle("ClipboardOverlay");
|
||||
mWindow = FloatingWindowUtil.getFloatingWindow(mContext);
|
||||
mWindow.setWindowManager(mWindowManager, null, null);
|
||||
|
||||
if (!mAccessibilityManager.isTouchExplorationEnabled()) {
|
||||
setWindowFocusable(true);
|
||||
} else {
|
||||
setWindowFocusable(false);
|
||||
}
|
||||
|
||||
mContainer = (FrameLayout)
|
||||
LayoutInflater.from(mContext).inflate(R.layout.clipboard_overlay, null);
|
||||
mView = requireNonNull(mContainer.findViewById(R.id.clipboard_ui));
|
||||
@@ -156,6 +165,7 @@ public class ClipboardOverlayController {
|
||||
mActionContainer = requireNonNull(mView.findViewById(R.id.actions));
|
||||
mImagePreview = requireNonNull(mView.findViewById(R.id.image_preview));
|
||||
mTextPreview = requireNonNull(mView.findViewById(R.id.text_preview));
|
||||
mPreviewBorder = requireNonNull(mView.findViewById(R.id.preview_border));
|
||||
mEditChip = requireNonNull(mView.findViewById(R.id.edit_chip));
|
||||
mRemoteCopyChip = requireNonNull(mView.findViewById(R.id.remote_copy_chip));
|
||||
mDismissButton = requireNonNull(mView.findViewById(R.id.dismiss_button));
|
||||
@@ -265,6 +275,7 @@ public class ClipboardOverlayController {
|
||||
OverlayActionChip chip = (OverlayActionChip) LayoutInflater.from(mContext).inflate(
|
||||
R.layout.overlay_action_chip, mActionContainer, false);
|
||||
chip.setText(action.getTitle());
|
||||
chip.setContentDescription(action.getTitle());
|
||||
chip.setIcon(action.getIcon(), false);
|
||||
chip.setPendingIntent(action.getActionIntent(), this::animateOut);
|
||||
chip.setAlpha(1);
|
||||
@@ -281,11 +292,24 @@ public class ClipboardOverlayController {
|
||||
if (event instanceof MotionEvent) {
|
||||
MotionEvent motionEvent = (MotionEvent) event;
|
||||
if (motionEvent.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||
int[] pt = new int[2];
|
||||
mView.getLocationOnScreen(pt);
|
||||
Rect rect = new Rect(pt[0], pt[1], pt[0] + mView.getWidth(),
|
||||
pt[1] + mView.getHeight());
|
||||
if (!rect.contains(
|
||||
Region touchRegion = new Region();
|
||||
|
||||
final Rect tmpRect = new Rect();
|
||||
mPreviewBorder.getBoundsOnScreen(tmpRect);
|
||||
tmpRect.inset(
|
||||
(int) FloatingWindowUtil.dpToPx(mDisplayMetrics, -SWIPE_PADDING_DP),
|
||||
(int) FloatingWindowUtil.dpToPx(mDisplayMetrics,
|
||||
-SWIPE_PADDING_DP));
|
||||
touchRegion.op(tmpRect, Region.Op.UNION);
|
||||
mActionContainerBackground.getBoundsOnScreen(tmpRect);
|
||||
tmpRect.inset(
|
||||
(int) FloatingWindowUtil.dpToPx(mDisplayMetrics, -SWIPE_PADDING_DP),
|
||||
(int) FloatingWindowUtil.dpToPx(mDisplayMetrics,
|
||||
-SWIPE_PADDING_DP));
|
||||
touchRegion.op(tmpRect, Region.Op.UNION);
|
||||
mDismissButton.getBoundsOnScreen(tmpRect);
|
||||
touchRegion.op(tmpRect, Region.Op.UNION);
|
||||
if (!touchRegion.contains(
|
||||
(int) motionEvent.getRawX(), (int) motionEvent.getRawY())) {
|
||||
animateOut();
|
||||
}
|
||||
@@ -332,6 +356,8 @@ public class ClipboardOverlayController {
|
||||
showTextPreview(text);
|
||||
mEditChip.setVisibility(View.VISIBLE);
|
||||
mEditChip.setAlpha(1f);
|
||||
mEditChip.setContentDescription(
|
||||
mContext.getString(R.string.clipboard_edit_text_description));
|
||||
View.OnClickListener listener = v -> editText();
|
||||
mEditChip.setOnClickListener(listener);
|
||||
mTextPreview.setOnClickListener(listener);
|
||||
@@ -353,6 +379,8 @@ public class ClipboardOverlayController {
|
||||
}
|
||||
View.OnClickListener listener = v -> editImage(uri);
|
||||
mEditChip.setOnClickListener(listener);
|
||||
mEditChip.setContentDescription(
|
||||
mContext.getString(R.string.clipboard_edit_image_description));
|
||||
mImagePreview.setOnClickListener(listener);
|
||||
}
|
||||
|
||||
@@ -525,4 +553,25 @@ public class ClipboardOverlayController {
|
||||
private Display getDefaultDisplay() {
|
||||
return mDisplayManager.getDisplay(DEFAULT_DISPLAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the window focusability. If the window is already showing, then it updates the
|
||||
* window immediately, otherwise the layout params will be applied when the window is next
|
||||
* shown.
|
||||
*/
|
||||
private void setWindowFocusable(boolean focusable) {
|
||||
int flags = mWindowLayoutParams.flags;
|
||||
if (focusable) {
|
||||
mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
} else {
|
||||
mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
}
|
||||
if (mWindowLayoutParams.flags == flags) {
|
||||
return;
|
||||
}
|
||||
final View decorView = mWindow.peekDecorView();
|
||||
if (decorView != null && decorView.isAttachedToWindow()) {
|
||||
mWindowManager.updateViewLayout(decorView, mWindowLayoutParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user