Appium中使用resourceId滚动定位元素失败,报错NoSuchElementException
问题:Appium UiScrollable通过resourceId滚动定位元素失败,抛出NoSuchElementException
尝试执行Appium脚本通过resourceId结合UiScrollable滚动定位元素并点击,但滚动功能失效,抛出NoSuchElementException。已确认resourceId正确,且该方法在使用text或content-desc时可正常工作,但目标元素无这些属性。
代码示例
WebElement element = driver.findElement(AppiumBy.androidUIAutomator("new UiScrollable(new UiSelector().scrollable(true)).scrollIntoView(new UiSelector().resourceId(\""+resourceId+"\"));")); element.click();
报错信息
org.openqa.selenium.NoSuchElementException: An element could not be located on the page using the given search parameters. For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception Build info: version: '4.10.0', revision: 'c14d967899' System info: os.name: 'Mac OS X', os.arch: 'aarch64', os.version: '13.4', java.version: '11.0.19' Driver info: io.appium.java_client.android.AndroidDriver Command: [32fc3d21-6a7f-46eb-b8a2-99f18bdd920a, findElement {using=-android uiautomator, value=new UiScrollable(new UiSelector().scrollable(true)).scrollIntoView(new UiSelector().resourceId("<masking_the_id>"));}] Capabilities {appium:automationName: UIAutomator2, appium:databaseEnabled: false, appium:desired: {automationName: UIAutomator2, platformName: ANDROID}, appium:deviceApiLevel: 33, appium:deviceManufacturer: XXXXX, appium:deviceModel: XXXXXXX, appium:deviceName: XXXXXX, appium:deviceScreenDensity: 450, appium:deviceScreenSize: 1080x2408, appium:deviceUDID: XXXXX, appium:javascriptEnabled: true, appium:locationContextEnabled: false, appium:networkConnectionEnabled: true, appium:pixelRatio: 2.8125, appium:platformVersion: 13, appium:statBarHeight: 70, appium:takesScreenshot: true, appium:viewportRect: {height: 2133, left: 0, top: 70, width: 1080}, appium:warnings: {}, appium:webStorageEnabled: false, platformName: ANDROID} Session ID: 32fc3d21-6a7f-46eb-b8a2-99f18bdd920a
解决方案
1. 明确指定滚动容器的resourceId
默认scrollable(true)可能匹配多个滚动容器,导致滚动逻辑错误。如果知道目标元素所在滚动容器的resourceId,直接定位该容器:
String scrollableContainerId = "com.example.app:id/scroll_container"; WebElement element = driver.findElement(AppiumBy.androidUIAutomator( "new UiScrollable(new UiSelector().resourceId(\"" + scrollableContainerId + "\")).scrollIntoView(new UiSelector().resourceId(\"" + resourceId + "\"));" )); element.click();
2. 添加滚动方向与次数控制
部分场景需要明确滚动方向或限制滚动次数,避免无效滚动:
// 垂直滚动查找元素 WebElement element = driver.findElement(AppiumBy.androidUIAutomator( "new UiScrollable(new UiSelector().scrollable(true)).setAsVerticalList().scrollIntoView(new UiSelector().resourceId(\"" + resourceId + "\"));" )); element.click(); // 最多向前滚动10次查找 WebElement element = driver.findElement(AppiumBy.androidUIAutomator( "new UiScrollable(new UiSelector().scrollable(true)).scrollForward(10).scrollIntoView(new UiSelector().resourceId(\"" + resourceId + "\"));" )); element.click();
3. 结合其他属性缩小元素范围
如果resourceId唯一但定位失败,可结合元素className、packageName等属性一起定位:
WebElement element = driver.findElement(AppiumBy.androidUIAutomator( "new UiScrollable(new UiSelector().scrollable(true)).scrollIntoView(new UiSelector().resourceId(\"" + resourceId + "\").className(\"android.widget.TextView\"));" )); element.click();
4. 验证元素所在页面状态
确认目标元素确实在当前Activity/页面中,未被弹窗、Tab切换等隐藏。
5. 改用Appium原生滚动方法替代UiAutomator
若UiScrollable始终失效,可通过TouchAction模拟手动滚动:
// 获取屏幕尺寸 Dimension size = driver.manage().window().getSize(); int startX = size.width / 2; int startY = (int) (size.height * 0.8); int endY = (int) (size.height * 0.2); boolean found = false; int maxAttempts = 10; int attempts = 0; while (!found && attempts < maxAttempts) { try { WebElement element = driver.findElement(AppiumBy.id(resourceId)); element.click(); found = true; } catch (NoSuchElementException e) { // 执行滚动操作 new TouchAction<>(driver) .press(PointOption.point(startX, startY)) .waitAction(WaitOptions.waitOptions(Duration.ofMillis(500))) .moveTo(PointOption.point(startX, endY)) .release() .perform(); attempts++; } }
内容的提问来源于stack exchange,提问作者Aaditya Awasthi
相关产品推荐
相关产品推荐

