Preliminary accessibility support for CropView

Making accessibility nodes for the top and bottom boundaries. They don't
do anything yet, just informational labeling.

Bug: 180062481
Test: Explore UI with switch access and talkback
Change-Id: Icc05fd865c70d32239e955745f1496bbd117529c
This commit is contained in:
Matt Casey
2021-02-12 10:21:23 -05:00
parent 36c202530e
commit fade30952a
2 changed files with 93 additions and 0 deletions

View File

@@ -247,6 +247,10 @@
<string name="screenshot_dismiss_description">Dismiss screenshot</string>
<!-- Content description indicating that the view is a preview of the screenshot that was just taken [CHAR LIMIT=NONE] -->
<string name="screenshot_preview_description">Screenshot preview</string>
<!-- Content description for the top boundary of the screenshot being cropped [CHAR LIMIT=NONE] -->
<string name="screenshot_top_boundary">Top boundary</string>
<!-- Content description for the bottom boundary of the screenshot being cropped [CHAR LIMIT=NONE] -->
<string name="screenshot_bottom_boundary">Bottom boundary</string>
<!-- Notification title displayed for screen recording [CHAR LIMIT=50]-->
<string name="screenrecord_name">Screen Recorder</string>

View File

@@ -24,15 +24,21 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.IntArray;
import android.util.Log;
import android.util.MathUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import androidx.annotation.Nullable;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import com.android.internal.widget.ExploreByTouchHelper;
import com.android.systemui.R;
/**
@@ -80,6 +86,8 @@ public class CropView extends View {
t.recycle();
// 48 dp touchable region around each handle.
mCropTouchMargin = 24 * getResources().getDisplayMetrics().density;
setAccessibilityDelegate(new AccessibilityHelper());
}
@Override
@@ -231,6 +239,87 @@ public class CropView extends View {
return CropBoundary.NONE;
}
private class AccessibilityHelper extends ExploreByTouchHelper {
private static final int TOP_HANDLE_ID = 1;
private static final int BOTTOM_HANDLE_ID = 2;
AccessibilityHelper() {
super(CropView.this);
}
@Override
protected int getVirtualViewAt(float x, float y) {
if (Math.abs(y - fractionToPixels(mTopCrop)) < mCropTouchMargin) {
return TOP_HANDLE_ID;
}
if (Math.abs(y - fractionToPixels(mBottomCrop)) < mCropTouchMargin) {
return BOTTOM_HANDLE_ID;
}
return ExploreByTouchHelper.INVALID_ID;
}
@Override
protected void getVisibleVirtualViews(IntArray virtualViewIds) {
virtualViewIds.add(TOP_HANDLE_ID);
virtualViewIds.add(BOTTOM_HANDLE_ID);
}
@Override
protected void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) {
switch(virtualViewId) {
case TOP_HANDLE_ID:
event.setContentDescription(
getResources().getString(R.string.screenshot_top_boundary));
break;
case BOTTOM_HANDLE_ID:
event.setContentDescription(
getResources().getString(R.string.screenshot_bottom_boundary));
break;
}
}
@Override
protected void onPopulateNodeForVirtualView(int virtualViewId,
AccessibilityNodeInfo node) {
switch(virtualViewId) {
case TOP_HANDLE_ID:
node.setContentDescription(
getResources().getString(R.string.screenshot_top_boundary));
setNodePositions(mTopCrop, node);
break;
case BOTTOM_HANDLE_ID:
node.setContentDescription(
getResources().getString(R.string.screenshot_bottom_boundary));
setNodePositions(mBottomCrop, node);
break;
}
// TODO: need to figure out the full set of actions to support here.
node.addAction(
AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK);
node.setClickable(true);
node.setFocusable(true);
}
@Override
protected boolean onPerformActionForVirtualView(
int virtualViewId, int action, Bundle arguments) {
return false;
}
private void setNodePositions(float fraction, AccessibilityNodeInfo node) {
int pixels = fractionToPixels(fraction);
Rect rect = new Rect(0, (int) (pixels - mCropTouchMargin),
getWidth(), (int) (pixels + mCropTouchMargin));
node.setBoundsInParent(rect);
int[] pos = new int[2];
getLocationOnScreen(pos);
rect.offset(pos[0], pos[1]);
node.setBoundsInScreen(rect);
}
}
/**
* Listen for crop motion events and state.
*/