17

我正在尝试识别 ui 元素的父视图,以便可以在 UI 中自由导航。

例如,在设置应用程序中,我可以找到带有文本“蓝牙”的视图:

UiObject btView = new UiObject(new UiSelector().text("Bluetooth"));

现在,我被卡住的部分是这个:我想向上导航两个级别并开始新搜索启用和禁用蓝牙的开/关按钮。

注意:如果我使用下面的代码,我可以获得按钮。

UiObject btButtonView = new UiObject(new UiSelector().className("android.widget.Switch").instance(1));

这将搜索开关按钮并返回第二次遭遇。我希望搜索更精确,并在包含“蓝牙”文本的线性布局中查找按钮。

更新:这是设置应用程序的布局(我需要的蓝牙部分):

LinearLayout
    LinearLayout
        ImageView
    RelativeLayout
        TextView (with text = "Bluetooth")
    Switch ()
4

5 回答 5

17

您需要先使用文本找到两个级别的 UiObject。这可以使用getChildByText()UiCollection 或 UiScrollable 中的方法来完成。然后你可以很容易地找到开关。对于“设置”,此代码适用于我的设备:

UiScrollable settingsList = new UiScrollable(new UiSelector().scrollable(true));
UiObject btItem = settingsList.getChildByText(new UiSelector().className(LinearLayout.class.getName()),"Bluetooth", true);

UiObject btSwitch = btItem.getChild(new UiSelector().className(android.widget.Switch.class.getName()));
btSwitch.click();
于 2013-07-19T07:17:34.200 回答
4

下面的代码对我有用。

//Getting the scrollable view

UiScrollable settingsList = new UiScrollable(new UiSelector().scrollable(true));

for (int i=0; i<=settingsList.getChildCount(new UiSelector ().className(LinearLayout.class.getName())); i++) {
//Looping through each linear layout view
UiObject linearLayout = settingsList.getChild(new UiSelector().className(LinearLayout.class.getName()).instance(i));

//Checking if linear layout have the text. If yes, get the switch, click and break out of the loop.
if (linearLayout.getChild(new UiSelector ().text("Bluetooth")).exists()) {
    UiObject btSwitch = linearLayout.getChild(new UiSelector().className(android.widget.Switch.class.getName()));
    btSwitch.click ();
    break;
    }
}
于 2013-09-15T10:32:57.923 回答
0

如果您只想搜索 ON/OFF 滑块 -> 您可以直接搜索蓝牙 OFF/ON 按钮并单击它以禁用/启用蓝牙 -

您可以在命令提示符下检查蓝牙页面的屏幕截图(使用命令 - uiautomatorviewer),并查看 OFF 按钮将在 OFF/ON 滑块中有文本。然后只需使用 -

   new UiObject(new UiSelector().text("OFF")).click();
于 2013-07-17T08:34:32.543 回答
0

最近发现我们可以使用 getFromParent(用于 UiObject)和 fromParent(用于 UiSelector)来选择对象的叔叔。如果我们有这样的布局:

`LinearLayout
    relative layout
        text View
    relative layout
        check box`

我们可以使用以下代码从 textview 获取复选框:

TextViewTitle().getFromParent(new UiSelector()
            .fromParent(new UiSelector()
                    .resourceId("android:id/checkbox")));

其中 TextViewTitle 是带有文本视图的 Uiobject

于 2017-01-25T13:31:12.620 回答
0

uiautomator不支持:直接获取父节点

但是您可以自己添加它(这需要很多工作)

一般步骤:

  1. 添加xpathuiautomator
  2. 用于xpath定位父节点d.xpath("/current_node_path/..")

附加节点:

我用

通过以下方式成功找到父节点:

self.driver.xpath("//android.widget.TextView[@text='Contact']/..")

和完整的代码:

    def isMatchNode(self, curNodeAttrib, toMathInfo):
        isAllMatch = True
        for eachKey, eachToMatchValue in toMathInfo.items():
            if eachKey not in curNodeAttrib:
                isAllMatch = False
                break

            curValue = curNodeAttrib[eachKey]
            if curValue != eachToMatchValue:
                isAllMatch = False
                break


        return isAllMatch


    def findParentNode(self, curNodeXpath, matchDict, maxUpLevel=3):
        matchNode = None

        curNode = self.driver.xpath(curNodeXpath).get()
        curNodeAttrib = curNode.attrib # .attrib contain 'clickable'
        # curNodeInfo = curNode.info # .info not contain 'clickable'
        isCurMatch = self.isMatchNode(curNodeAttrib, matchDict)
        if isCurMatch:
            # current is match
            matchNode = curNode
        else:
            # try parent nodes
            curUpLevel = 1
            curParentNodeXpath = curNodeXpath
            hasFound = False
            while((not hasFound) and (curUpLevel <= maxUpLevel)):
                curParentNodeXpath += "/.."
                curParentNode = self.driver.xpath(curParentNodeXpath).get()
                curParentNodeAttrib = curParentNode.attrib
                isCurParentMatch = self.isMatchNode(curParentNodeAttrib, matchDict)
                if isCurParentMatch:
                    matchNode = curParentNode
                    break


        return matchNode


    def location_WexinAdd(self, reload=False):
        for eachNodeText in ["Contact", "Public Account"]:
            eachNodeXpath = "//android.widget.TextView[@text='%s']" % eachNodeText
            matchDict = {"clickable": "true"}
            clickableParentNode = self.findParentNode(curNodeXpath=eachNodeXpath, matchDict=matchDict)
            if clickableParentNode:
                clickableParentNode.click()
            else:
                logging.warning("Fail click %s for not found clickable=true (parent) node", eachNodeText)

供您参考。

于 2020-02-06T11:18:26.723 回答