提交 707ff9b4 编写于 作者: H Hixie

Implement hover touch exploration mode on Android.

上级 0fa85242
...@@ -30,6 +30,7 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN ...@@ -30,6 +30,7 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN
private PlatformViewAndroid mOwner; private PlatformViewAndroid mOwner;
private SemanticsServer.Proxy mSemanticsServer; private SemanticsServer.Proxy mSemanticsServer;
private PersistentAccessibilityNode mFocusedNode; private PersistentAccessibilityNode mFocusedNode;
private PersistentAccessibilityNode mHoveredNode;
FlutterSemanticsToAndroidAccessibilityBridge(PlatformViewAndroid owner, SemanticsServer.Proxy semanticsServer) { FlutterSemanticsToAndroidAccessibilityBridge(PlatformViewAndroid owner, SemanticsServer.Proxy semanticsServer) {
assert owner != null; assert owner != null;
...@@ -177,6 +178,32 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN ...@@ -177,6 +178,32 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN
return false; 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 @Override
public void updateSemanticsTree(SemanticsNode[] nodes) { public void updateSemanticsTree(SemanticsNode[] nodes) {
for (SemanticsNode node : nodes) { for (SemanticsNode node : nodes) {
...@@ -212,6 +239,12 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN ...@@ -212,6 +239,12 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN
assert mTreeNodes.containsKey(node.id); assert mTreeNodes.containsKey(node.id);
assert mTreeNodes.get(node.id).parent == null; assert mTreeNodes.get(node.id).parent == null;
mTreeNodes.remove(node.id); mTreeNodes.remove(node.id);
if (mFocusedNode == node) {
mFocusedNode = null;
}
if (mHoveredNode == node) {
mHoveredNode = null;
}
for (PersistentAccessibilityNode child : node.children) { for (PersistentAccessibilityNode child : node.children) {
removePersistentNode(child); removePersistentNode(child);
} }
...@@ -219,7 +252,10 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN ...@@ -219,7 +252,10 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN
public void reset(SemanticsServer.Proxy newSemanticsServer) { public void reset(SemanticsServer.Proxy newSemanticsServer) {
mTreeNodes.clear(); mTreeNodes.clear();
mFocusedNode = null;
mHoveredNode = null;
mSemanticsServer.close(); mSemanticsServer.close();
sendAccessibilityEvent(0, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
mSemanticsServer = newSemanticsServer; mSemanticsServer = newSemanticsServer;
mSemanticsServer.addSemanticsListener(this); mSemanticsServer.addSemanticsListener(this);
} }
...@@ -375,6 +411,20 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN ...@@ -375,6 +411,20 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN
} }
return globalRect; 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 @Override
......
...@@ -248,6 +248,16 @@ public class PlatformViewAndroid extends SurfaceView ...@@ -248,6 +248,16 @@ public class PlatformViewAndroid extends SurfaceView
return true; 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 @Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
mMetrics.physicalWidth = width; mMetrics.physicalWidth = width;
...@@ -332,10 +342,13 @@ public class PlatformViewAndroid extends SurfaceView ...@@ -332,10 +342,13 @@ public class PlatformViewAndroid extends SurfaceView
// ACCESSIBILITY // ACCESSIBILITY
private boolean mTouchExplorationEnabled = false;
@Override @Override
protected void onAttachedToWindow() { protected void onAttachedToWindow() {
super.onAttachedToWindow(); super.onAttachedToWindow();
if (mAccessibilityManager.isEnabled() || mAccessibilityManager.isTouchExplorationEnabled()) mTouchExplorationEnabled = mAccessibilityManager.isTouchExplorationEnabled();
if (mAccessibilityManager.isEnabled() || mTouchExplorationEnabled)
ensureAccessibilityEnabled(); ensureAccessibilityEnabled();
mAccessibilityManager.addAccessibilityStateChangeListener(this); mAccessibilityManager.addAccessibilityStateChangeListener(this);
mAccessibilityManager.addTouchExplorationStateChangeListener(this); mAccessibilityManager.addTouchExplorationStateChangeListener(this);
...@@ -349,9 +362,15 @@ public class PlatformViewAndroid extends SurfaceView ...@@ -349,9 +362,15 @@ public class PlatformViewAndroid extends SurfaceView
@Override @Override
public void onTouchExplorationStateChanged(boolean enabled) { public void onTouchExplorationStateChanged(boolean enabled) {
if (enabled) if (enabled) {
mTouchExplorationEnabled = true;
ensureAccessibilityEnabled(); ensureAccessibilityEnabled();
// TODO(ianh): else, actually discard the state for exploration } else {
mTouchExplorationEnabled = false;
if (mAccessibilityNodeProvider != null) {
mAccessibilityNodeProvider.handleTouchExplorationExit();
}
}
} }
@Override @Override
...@@ -382,12 +401,15 @@ public class PlatformViewAndroid extends SurfaceView ...@@ -382,12 +401,15 @@ public class PlatformViewAndroid extends SurfaceView
} }
} }
// TODO(ianh): implement findAccessibilityNodeInfosByText() private boolean handleAccessibilityHoverEvent(MotionEvent event) {
if (!mTouchExplorationEnabled)
// TODO(ianh): implement findFocus() return false;
if (event.getAction() == MotionEvent.ACTION_HOVER_EXIT) {
// TODO(ianh): implement touch exploration mAccessibilityNodeProvider.handleTouchExplorationExit();
} else {
// TODO(ianh): implement accessibility focus mAccessibilityNodeProvider.handleTouchExploration(event.getX(), event.getY());
}
return true;
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册