Dealing with scrolling in native mobile apps can be tricky, especially when working with list views. A single approach doesn’t always work across platforms. For example, common methods like TouchAction may not behave consistently, so we often need to handle Android and iOS separately. I am sharing an example script that I implemented in my application using automation.
In this example, I’m providing a script that demonstrates how to manage scrolling in Appium with Selenium:
- On Android → We pass the resource-id of the list view and the text of the target element. The script uses
UiScrollableto scroll through the list until the matching element is found. - On iOS → We pass the locator of the list view and the locator of the target element. The script then performs a scroll gesture by calculating the list view’s position and swiping within its boundaries until the element is located.
This approach ensures reliable scrolling behavior on both Android and iOS when working with list views in native apps. I have provided script in both java and C#
Java Example :
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;
import org.openqa.selenium.By;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ScrollUtils {
private AppiumDriver<MobileElement> driver;
public ScrollUtils(AppiumDriver<MobileElement> driver) {
this.driver = driver;
}
// ✅ Android scroll + return elements
public List<MobileElement> getElementsAndroid(String resourceId, String text) {
String uiScroll = "new UiScrollable(new UiSelector().resourceId(\"" + resourceId + "\"))"
+ ".scrollIntoView(new UiSelector().text(\"" + text + "\"));";
// Scroll to the element
driver.findElementByAndroidUIAutomator(uiScroll);
// Return all matching elements
return driver.findElements(By.xpath(
"//*[@resource-id='" + resourceId + "']//*[@text='" + text + "']"
));
}
// ✅ iOS scroll inside container + return elements
public List<MobileElement> getElementsIOS(By containerLocator, By elementLocator) {
MobileElement container = driver.findElement(containerLocator);
// Get container position and size
int startX = container.getLocation().getX() + container.getSize().width / 2;
int startY = container.getLocation().getY() + container.getSize().height - 10;
int endX = startX;
int endY = container.getLocation().getY() + 10;
// Perform scroll gesture
Map<String, Object> params = new HashMap<>();
params.put("duration", 1.0);
params.put("fromX", startX);
params.put("fromY", startY);
params.put("toX", endX);
params.put("toY", endY);
driver.executeScript("mobile: dragFromToForDuration", params);
// Return all matching elements
return driver.findElements(elementLocator);
}
}
Usage Example:
ScrollUtils utils = new ScrollUtils(driver);
if (driver.getPlatformName().equalsIgnoreCase(“Android”)) {
List elements = utils.getElementsAndroid(“com.example:id/listView”, “Target Item”);
System.out.println(“Found Android elements: ” + elements.size());
elements.forEach(e -> System.out.println(“Text: ” + e.getText()));
} else {
List elements = utils.getElementsIOS(
By.xpath(“//XCUIElementTypeTable”),
By.xpath(“//XCUIElementTypeCell[@name=’Target’]”)
);
System.out.println(“Found iOS elements: ” + elements.size());
elements.forEach(e -> System.out.println(“Label: ” + e.getAttribute(“label”)));
}
C# Example:
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Android;
using OpenQA.Selenium.Appium.iOS;
using OpenQA.Selenium.Appium.MultiTouch;
using OpenQA.Selenium.Appium.Enums;
using System;
using System.Collections.Generic;
public class ScrollUtils
{
private AppiumDriver driver;
public ScrollUtils(AppiumDriver<IWebElement> driver)
{
this.driver = driver;
}
// ✅ ANDROID: Scroll with UiScrollable until element is found
public IList<IWebElement> GetElementsAndroid(string listResourceId, string targetText)
{
string uiScroll = "new UiScrollable(new UiSelector().resourceId(\"" + listResourceId + "\"))"
+ ".scrollIntoView(new UiSelector().text(\"" + targetText + "\"));";
// Perform scroll
driver.FindElement(MobileBy.AndroidUIAutomator(uiScroll));
// Return all matching elements
return driver.FindElements(By.XPath(
"//*[@resource-id='" + listResourceId + "']//*[@text='" + targetText + "']"
));
}
// ✅ IOS: Scroll inside container until element is visible
public IList<IWebElement> GetElementsIOS(By containerLocator, By elementLocator)
{
IWebElement container = driver.FindElement(containerLocator);
// Get container position & size
int startX = container.Location.X + (container.Size.Width / 2);
int startY = container.Location.Y + container.Size.Height - 10;
int endX = startX;
int endY = container.Location.Y + 10;
// Build gesture parameters
Dictionary<string, object> args = new Dictionary<string, object>
{
{ "duration", 1.0 },
{ "fromX", startX },
{ "fromY", startY },
{ "toX", endX },
{ "toY", endY }
};
// Perform scroll gesture
driver.ExecuteScript("mobile: dragFromToForDuration", args);
// Return all matching elements
return driver.FindElements(elementLocator);
}
}