iOS scrolling not stopping at desired specified element and keep on scrolling down

I tried to following code snippets to scroll to specific element on iPhone 6 having iOS 12.4 but it doesn’t stop at desired element. It keeps on scrolling till end of screen

Using below version of Appium + Selenium

compile group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '3.141.59'

compile group: 'io.appium', name: 'java-client', version: '7.3.0'
MobileElement parent = (MobileElement)driver.findElement(By.className("XCUIElementTypeTable"));
String parentID = parent.getId();
HashMap<String, String> scrollObject = new HashMap<String, String>();
scrollObject.put("element", parentID);
scrollObject.put("name", "elementName");
driver.executeScript("mobile:scroll", scrollObject);

OR

MobileElement parent = (MobileElement)driver.findElement(By.className("XCUIElementTypeTable")); 
String parentID = parent.getId();
HashMap<String, String> scrollObject = new HashMap<String, String>();
scrollObject.put("element", parentID);
scrollObject.put("predicateString", "label == 'elementLabel'");
driver.executeScript("mobile:scroll", scrollObject);  // scroll to the target element

But, in both the case the scrolling hasn’t stopped to desired element and it keeps on scrolling till end of screen.

What could be issue here and how can I overcome it?

it happens. it is iOS part. Appium cant do anything.

  1. double check that element you are looking has your text in: name, label OR value!
  2. try predicate
name == 'elementLabel' OR label == 'elementLabel' OR value == 'elementLabel'
1 Like

name == ‘elementLabel’ OR label == ‘elementLabel’ OR value == ‘elementLabel’ even accessibilityId == ‘elementLabel’

none of them are giving desired results.

I made it sure that those ‘name’ or ‘label’ or ‘value’ are detectable by driver… if I manually scroll to that element them driver can click on name == 'elementLabel' OR label == 'elementLabel' OR value == 'elementLabel' properly. there is no issue with detecting the element.

It is something crazy thing going on.

well no chance. write to Apple. swipe yourself and check each time after swipe that element is visible.

The solution for workaround this case by

  • Calculation how many scroll down pages there are needed to scroll
    example:
    . There are 5 visible elements in each page of dropdown list. 15 is expected value to set
    . num of scroll page is 15/5 = 3
    . use the below function for scrolling page

{
eleRemote = getElementByClassName(driver, “XCUIElementTypeTable”);
Integer x = eleRemote.getLocation().getX();
Integer y = eleRemote.getLocation().getY();
Integer windowHeight = eleRemote.getSize().getHeight();
Integer windowWidth = eleRemote.getSize().getWidth();
for (int i = 0; i < numScroll; i++) {
int starty = (int) (y + (windowHeight * 0.8)); // 80%
int endy = (int) (y + (windowHeight * 0.2)); // 20%
int startx = (x + windowWidth / 2); // middle
TouchAction touch = new TouchAction(driver);
touch.longPress(LongPressOptions.longPressOptions().withPosition(PointOption.point(startx, starty))).moveTo(PointOption.point(startx, endy)).release().perform();
}

  • Use ioschain (need to use appium 1.19) to find the expected value

String selector = “**/XCUIElementTypeCell[” + Idx + “]”;
ele = driver.findElement(MobileBy.iOSClassChain(selector));
in this case, idx of 15 maybe 14 or 15. Use appium desktop to check correct index

Currently it works well in my environment.

This is what I tried and it seemed to be working.

This scrolling logic was implemented for native app context for iOS, Java.

public void scrollToMobileElement(String elementName, String direction) {

    final int maximumScrolls = 5

    for (int i = 0; i < maximumScrolls; i++) {
        try {
            if (findElementsByPredicateString("label CONTAINS \"" + elementName + "\"").size() > 0)
            // PredicateString & label is the locator strategy that I used. It can be changed to others as needed for your app.
                break;
        } catch (Exception e) {
            e.printStackTrace()
        }
        scroll(direction)
    }
}

private void scroll(String direction) {
    final HashMap<String, String> scrollObject = new HashMap<String, String>()
    scrollObject.put("direction", direction)
    driver.executeScript("mobile:scroll", scrollObject);
}

public List<MobileElement> findElementsByPredicateString(String predicateString) {
    return driver.findElements(MobileBy.iOSNsPredicateString(predicateString))
}

When calling scrollToMobileElement method, pass direction “down” or “up”.

It works well with appium 1.20.2. No need to scroll specified element.