I have a custom view , which extends ViewGroup, i.e CustomViewGrouup. There I am adding some ImageView. When user will click on some specific rectangular area on the CustomViewGroup, then I need to behave it like a button, i.e Announced by Talkback , like "Rectangle 1, Double Tap to activate". Then, if user double taps on that button I need to perform the code for it.
I tried to add some virtual view structure, with getAccessibilityNodeProvider. Now, when I tap on some defined rectangular area, then it annouces "Rectangle 1" not like "...Double Tap to activate. When I double click on that rectangular area, it doesn't perform desired action in the "performAction" method.
Code is like below :
package com.example.myapplication;
import android.content.Context;
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.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import android.widget.Button;
import android.widget.ImageView;
import androidx.annotation.Nullable;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import java.util.ArrayList;
import java.util.List;
public class MyCustomViewGroup extends ViewGroup {
private ImageView imageView;
// Logical rectangles to represent the newspaper article sections
private List<Rect> logicalRects = new ArrayList<>();
private int focusedRectIndex = -1;
private int previousFocusedRectIndex = -1;
private AccessibilityNodeProvider nodeProvider;
private Paint rectPaint;
boolean drawRects = false;
public MyCustomViewGroup(Context context) {
super(context);
init(context);
}
public MyCustomViewGroup(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MyCustomViewGroup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
imageView = new ImageView(context);
imageView.setImageResource(R.drawable.sample_paper_image);
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setBackgroundColor(Color.LTGRAY);
imageView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
imageView.setClickable(false);
imageView.setFocusable(false);
addView(imageView);
initLogicalRects();
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (drawRects) {
drawRectangles(canvas);
}
}
private void drawRectangles(Canvas canvas) {
// Draw the logical rectangles
for (int i = 0; i < logicalRects.size(); i++) {
if (i == focusedRectIndex) {
// Highlight the focused rectangle
rectPaint.setColor(Color.GREEN);
} else {
// Default color for non-focused rectangles
rectPaint.setColor(Color.RED);
}
canvas.drawRect(logicalRects.get(i), rectPaint);
}
}
private void initLogicalRects() {
// Define some example rectangles
logicalRects.add(new Rect(50, 50, 200, 150)); // Rectangle 1
logicalRects.add(new Rect(250, 50, 400, 150)); // Rectangle 2
logicalRects.add(new Rect(50, 200, 200, 300)); // Rectangle 3
logicalRects.add(new Rect(400, 400, 800, 800)); // Rectangle 4
if (drawRects) {
rectPaint = new Paint();
rectPaint.setStyle(Paint.Style.STROKE);
rectPaint.setStrokeWidth(8);
// Allow ViewGroup to draw
setWillNotDraw(false);
invalidate();
}
}
@Override
public AccessibilityNodeProvider getAccessibilityNodeProvider() {
if (nodeProvider == null) {
nodeProvider = new CustomAccessibilityNodeProvider();
}
return nodeProvider;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Measure the ImageView to fill the parent
measureChild(imageView, widthMeasureSpec, heightMeasureSpec);
// Set the measured dimensions of the ViewGroup
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// Position the ImageView to fill the entire ViewGroup
imageView.layout(0, 0, r - l, b - t);
}
private void performClickAction(int rectIndex) {
// Handle the action for the rectangle
Log.d("MyCustomViewGroup", "Rectangle " + (rectIndex + 1) + " clicked!");
}
@Override
public boolean onHoverEvent(MotionEvent event) {
AccessibilityManager accessibilityManager =
(AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
if (accessibilityManager != null && accessibilityManager.isEnabled()) {
// Forward hover events to accessibility
int index = getRectIndexAt(event.getX(), event.getY());
if (index != -1) {
if (event.getAction() == MotionEvent.ACTION_HOVER_ENTER) {
nodeProvider.performAction(index, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
} else if (event.getAction() == MotionEvent.ACTION_HOVER_EXIT) {
nodeProvider.performAction(index, AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
}
}
Log.d("MyCustomViewGroup", "Hover event: Action = " + event.getAction() + ", Index = " + index);
return true;
}
return super.onHoverEvent(event);
}
private int getRectIndexAt(float x, float y) {
for (int i = 0; i < logicalRects.size(); i++) {
if (logicalRects.get(i).contains((int) x, (int) y)) {
return i;
}
}
return -1;
}
private class CustomAccessibilityNodeProvider extends AccessibilityNodeProvider {
@Override
public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
if (virtualViewId == View.NO_ID) {
// Describe the MyCustomViewGroup itself
AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(MyCustomViewGroup.this);
onInitializeAccessibilityNodeInfo(info);
// Add virtual nodes as children
for (int i = 0; i < logicalRects.size(); i++) {
info.addChild(MyCustomViewGroup.this, i);
}
info.setClassName(ViewGroup.class.getName());
// Prevent the ViewGroup itself from being focusable
info.setFocusable(false);
info.setClickable(false);
//info.setImportantForAccessibility(false);
return info;
} else {
// Describe a virtual rectangle
return createVirtualAccessibilityNodeInfo(virtualViewId);
}
}
@Override
public boolean performAction(int virtualViewId, int action, Bundle arguments) {
Log.d("MyCustomViewGroup", "Perform action: Action = " + action + ", Index = " + virtualViewId);
if (virtualViewId == View.NO_ID) {
return super.performAction(virtualViewId, action, arguments);
}
if (virtualViewId >= 0 && virtualViewId < logicalRects.size()) {
if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) {
focusedRectIndex = virtualViewId;
//sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
sendAccessibilityEventForVirtualNode(virtualViewId, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
if (drawRects) invalidate();
return true;
} else if (action == AccessibilityNodeInfo.ACTION_CLICK) {
// Perform the action
performClickAction(virtualViewId);
// Send an event to announce the click
sendAccessibilityEventForVirtualNode(virtualViewId, AccessibilityEvent.TYPE_VIEW_CLICKED);
Log.d("MyCustomViewGroup", "Rectangle " + virtualViewId + " clicked via double-tap!");
return true;
}
}
return false;
}
private AccessibilityNodeInfo createVirtualAccessibilityNodeInfo(int index) {
if (index < 0 || index >= logicalRects.size()) {
return null;
}
AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
info.setPackageName(getContext().getPackageName());
info.setClassName(Button.class.getName());
info.setSource(MyCustomViewGroup.this, index);
// Describe the logical rectangle
Rect rect = logicalRects.get(index);
info.setBoundsInParent(rect);
info.setContentDescription("Rectangle " + (index + 1));
info.setEnabled(true);
info.setFocusable(true);
info.setClickable(true);
// Add focus and click actions using AccessibilityAction
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK);
return info;
}
}
private void sendAccessibilityEventForVirtualNode(int virtualViewId, int eventType) {
AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
event.setPackageName(getContext().getPackageName());
event.setClassName(Button.class.getName());
event.setContentDescription("Rectangle " + (virtualViewId + 1)); // Description of the rectangle
event.setSource(this, virtualViewId);
Log.d("MyCustomViewGroup", "Accessibility Event: Type = " + eventType + ", Index = " + virtualViewId);
getParent().requestSendAccessibilityEvent(MyCustomViewGroup.this, event);
}
}
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745273471a4619892.html
评论列表(0条)