mirror of
https://github.com/encounter/engine.git
synced 2026-03-30 11:09:55 -07:00
Implement hover touch exploration mode on Android.
This commit is contained in:
+50
@@ -30,6 +30,7 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN
|
||||
private PlatformViewAndroid mOwner;
|
||||
private SemanticsServer.Proxy mSemanticsServer;
|
||||
private PersistentAccessibilityNode mFocusedNode;
|
||||
private PersistentAccessibilityNode mHoveredNode;
|
||||
|
||||
FlutterSemanticsToAndroidAccessibilityBridge(PlatformViewAndroid owner, SemanticsServer.Proxy semanticsServer) {
|
||||
assert owner != null;
|
||||
@@ -177,6 +178,32 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(ianh): implement findAccessibilityNodeInfosByText()
|
||||
// TODO(ianh): implement findFocus()
|
||||
|
||||
public void handleTouchExplorationExit() {
|
||||
if (mHoveredNode != null) {
|
||||
sendAccessibilityEvent(mHoveredNode.id, AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
|
||||
mHoveredNode = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void handleTouchExploration(float x, float y) {
|
||||
if (mTreeNodes.isEmpty())
|
||||
return;
|
||||
assert mTreeNodes.containsKey(0);
|
||||
PersistentAccessibilityNode newNode = mTreeNodes.get(0).hitTest(Math.round(x), Math.round(y));
|
||||
if (newNode != mHoveredNode) {
|
||||
if (newNode != null) {
|
||||
sendAccessibilityEvent(newNode.id, AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
|
||||
}
|
||||
if (mHoveredNode != null) {
|
||||
sendAccessibilityEvent(mHoveredNode.id, AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
|
||||
}
|
||||
mHoveredNode = newNode;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSemanticsTree(SemanticsNode[] nodes) {
|
||||
for (SemanticsNode node : nodes) {
|
||||
@@ -212,6 +239,12 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN
|
||||
assert mTreeNodes.containsKey(node.id);
|
||||
assert mTreeNodes.get(node.id).parent == null;
|
||||
mTreeNodes.remove(node.id);
|
||||
if (mFocusedNode == node) {
|
||||
mFocusedNode = null;
|
||||
}
|
||||
if (mHoveredNode == node) {
|
||||
mHoveredNode = null;
|
||||
}
|
||||
for (PersistentAccessibilityNode child : node.children) {
|
||||
removePersistentNode(child);
|
||||
}
|
||||
@@ -219,7 +252,10 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN
|
||||
|
||||
public void reset(SemanticsServer.Proxy newSemanticsServer) {
|
||||
mTreeNodes.clear();
|
||||
mFocusedNode = null;
|
||||
mHoveredNode = null;
|
||||
mSemanticsServer.close();
|
||||
sendAccessibilityEvent(0, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
|
||||
mSemanticsServer = newSemanticsServer;
|
||||
mSemanticsServer.addSemanticsListener(this);
|
||||
}
|
||||
@@ -375,6 +411,20 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN
|
||||
}
|
||||
return globalRect;
|
||||
}
|
||||
|
||||
public PersistentAccessibilityNode hitTest(int x, int y) {
|
||||
Rect rect = getGlobalRect();
|
||||
if (!rect.contains(x, y))
|
||||
return null;
|
||||
for (int index = children.size()-1; index >= 0; index -= 1) {
|
||||
PersistentAccessibilityNode child = children.get(index);
|
||||
PersistentAccessibilityNode result = child.hitTest(x, y);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -248,6 +248,16 @@ public class PlatformViewAndroid extends SurfaceView
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onHoverEvent(MotionEvent event) {
|
||||
boolean handled = handleAccessibilityHoverEvent(event);
|
||||
if (!handled) {
|
||||
// TODO(ianh): Expose hover events to the platform,
|
||||
// implementing ADD, REMOVE, etc.
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
|
||||
mMetrics.physicalWidth = width;
|
||||
@@ -332,10 +342,13 @@ public class PlatformViewAndroid extends SurfaceView
|
||||
|
||||
// ACCESSIBILITY
|
||||
|
||||
private boolean mTouchExplorationEnabled = false;
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
if (mAccessibilityManager.isEnabled() || mAccessibilityManager.isTouchExplorationEnabled())
|
||||
mTouchExplorationEnabled = mAccessibilityManager.isTouchExplorationEnabled();
|
||||
if (mAccessibilityManager.isEnabled() || mTouchExplorationEnabled)
|
||||
ensureAccessibilityEnabled();
|
||||
mAccessibilityManager.addAccessibilityStateChangeListener(this);
|
||||
mAccessibilityManager.addTouchExplorationStateChangeListener(this);
|
||||
@@ -349,9 +362,15 @@ public class PlatformViewAndroid extends SurfaceView
|
||||
|
||||
@Override
|
||||
public void onTouchExplorationStateChanged(boolean enabled) {
|
||||
if (enabled)
|
||||
if (enabled) {
|
||||
mTouchExplorationEnabled = true;
|
||||
ensureAccessibilityEnabled();
|
||||
// TODO(ianh): else, actually discard the state for exploration
|
||||
} else {
|
||||
mTouchExplorationEnabled = false;
|
||||
if (mAccessibilityNodeProvider != null) {
|
||||
mAccessibilityNodeProvider.handleTouchExplorationExit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -382,12 +401,15 @@ public class PlatformViewAndroid extends SurfaceView
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(ianh): implement findAccessibilityNodeInfosByText()
|
||||
|
||||
// TODO(ianh): implement findFocus()
|
||||
|
||||
// TODO(ianh): implement touch exploration
|
||||
|
||||
// TODO(ianh): implement accessibility focus
|
||||
private boolean handleAccessibilityHoverEvent(MotionEvent event) {
|
||||
if (!mTouchExplorationEnabled)
|
||||
return false;
|
||||
if (event.getAction() == MotionEvent.ACTION_HOVER_EXIT) {
|
||||
mAccessibilityNodeProvider.handleTouchExplorationExit();
|
||||
} else {
|
||||
mAccessibilityNodeProvider.handleTouchExploration(event.getX(), event.getY());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user