繁体   English   中英

Android onAccessibilityEvent获取TextView的X和Y位置

[英]Android onAccessibilityEvent get X and Y position of TextView

我正在尝试使用辅助功能服务在我的屏幕上获取 TextView 的 X 和 Y 位置以查找 TextView,这可能吗? 我发现的所有内容都需要您先触摸屏幕。 这是我获取节点信息的方式。

public class MyAccessibilityService extends AccessibilityService {

    @TargetApi(16)
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        AccessibilityNodeInfo source = event.getSource();
    }
}

您可以随时从无障碍服务中任意搜索无障碍视图层次结构,不过,我建议您在某种类型的无障碍事件的上下文中这样做。 然后确保有要遍历的屏幕内容:在随机回调中这样做充其量是挑剔的。 这是用于此类目的的合理的可访问性配置 XML 文件:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/accessibility_service_description"
    android:accessibilityEventTypes="typeWindowContentChanged|typeWindowsChanged|typeWindowStateChanged"
    android:accessibilityFlags="flagReportViewIds|flagIncludeNotImportantViews"
    android:canRetrieveWindowContent="true"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:notificationTimeout="1000" 
    android:settingsActivity=".SettingsActivity"
    />

以下是对其中一些领域的一些评论。

android:notificationTimeout="1000"

每秒仅检索一次给定类型的可访问性事件,并列出事件。 任何较低的设置都会非常冗长。 我们只依靠它来调用我们的回调并确保我们有节点。 对于这些目的,每秒一次只是 DANDY。 根据需要进行调整。

android:accessibilityEventTypes="typeWindowContentChanged|typeWindowsChanged|typeWindowStateChanged"

粗略地说,这是允许您捕获所有屏幕更改事件的事件子集。 打开一个新窗口...扫描视图层次结构!

android:accessibilityFlags="flagReportViewIds|flagIncludeNotImportantViews"

标志包括不重要的视图将在 AccessibilityNodeInfo 层次结构中包含更多视图。 具体来说,许多布局视图等 Android 操作系统通常认为出于可访问性目的不需要。 我喜欢包括这个,因为这也是一个开发人员可调整的属性,Android 开发人员在可访问性方面是出了名的不了解。 最好只获取所有内容并自己整理!

好的,现在是您的服务配置。 剩下的就很简单了。 你想要做的是递归遍历根节点子节点,直到找到一个 TextView 节点,我在下面设置了一个愚蠢的服务,它会在每次屏幕更新时找到第一个 TextView 节点(除非它们每秒出现不止一次,因为上面的服务配置 XML)。 然后记录它的屏幕坐标。

class MyAccessibilityService extends AccessibilityService {

    @Override
    public void onAccessibilityEvent(AccessibilityEvent e) {

        //You can actually call getRootInActiveWindow() any time!
        //Doing so here ensures that the screen is in a reasonable state
        //and not in the middle of rendering or something else silly.
        final AccessibilityNodeInfo textNodeInfo = findTextViewNode(getRootInActiveWindow());

        if (textNodeInfo == null) return;

        Rect rect = new Rect();

        textNodeInfo.getBoundsInScreen(rect);

        Log.i(A11yService.class.getSimpleName(), "The TextView Node: " + rect.toString());

    }


    public AccessibilityNodeInfo findTextViewNode(AccessibilityNodeInfo nodeInfo) {

        //I highly recommend leaving this line in! You never know when the screen content will
        //invalidate a node you're about to work on, or when a parents child will suddenly be gone!
        //Not doing this safety check is very dangerous!
        if (nodeInfo == null) return null;

        Log.v(A11yService.class.getSimpleName(), nodeInfo.toString());

        //Notice that we're searching for the TextView's simple name!
        //This allows us to find AppCompat versions of TextView as well
        //as 3rd party devs well names subclasses... though with perhaps
        //a few poorly named unintended stragglers!
        if (nodeInfo.getClassName().toString().contains(TextView.class.getSimpleName())) {
            return nodeInfo;
        }

        //Do other work!

        for (int i = 0; i < nodeInfo.getChildCount(); i++) {
            AccessibilityNodeInfo result = findTextViewNode(nodeInfo.getChild(i));

            if (result != null) return result;
        }

        return null;
    }

    //Required for a valid Accessibility Service.
    @Override
    public void onInterrupt() {}
}

您还可以寻找我构建的开源库,称为Accessibility Service Utilities ,它使所有这些东西变得更加容易! A11yNodeInfoMatcher类就是您想要的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM