Page tree
Skip to end of metadata
Go to start of metadata

Last updated: Apr 04, 2019 14:35

With the deprecation of ScrollTo and ScrollToExact functions of Appium, scrolling to a specific element we want to interact with has become a little harder.
One option might be to use Perfecto´s Visual Analysis to scroll to a visual queue. See Scrolling in visual analysis to find a needle for details.

Using native objects, we can use Android´s UIAutomator to leverage the Android UISelector, as well as NsPredicates on iOS (on XCUITest).

Android

We can leverage the UIAutomator methods by executing the findElementByAndroidUIAutomator.

The first thing we need, is to identify a scrollable object on the page, within which we can then scroll to a specific object.

  1. Let's take the Android settings app as an example- com.android.settings, eg. on the Samsung S8.



  2. Using the Object spy, we can see that there is a number of android.widget.LinearLayout object that represent the items we want to click.


  3. In order to scroll, we need to specify the parent within which the object we are looking for is listed. This parent needs to be scrollable.
    In this case we can pick the direct parent, the android.support.v7.widget.RecyclerViewer, or a higher level ancestor like this FrameLayout:


    A difficulty about using AndroidUIAutomator Findby, is that we are limited to the UISelector's element identification, which is not as flexible as XPath.
    For the search we are mainly limited to text, resourcId and index- so finding a uniquely identifiable scrollable container as well as child is important.
    In this case here, the FrameLayout has the resourceID android:id/content, which we can easily obtain from the Perfecto ObjectSpy:


  4. In this example, we want to scroll to and click the "Lock Screen and Security" setting, which is uniquely identified by text:


  5. The code we can now use to scroll to this object, to then click it is:
    1. By Specifying the Scrollable parent- in our example identified by com.android.settings:id/content

      MobileElement elementToClick = (MobileElement) driver
      	.findElementByAndroidUIAutomator("new UiScrollable(new UiSelector()"
      		+ ".resourceId(\"com.android.settings:id/content\")).scrollIntoView("
      		+ "new UiSelector().text(\"Lock screen and security\"));");
      elementToClick.click(); 
    2. If there is only a single scrollable container, UISelector can just be used with scrollable(true) instead of identifying the parent object:

      MobileElement el = (MobileElement) driver
      	.findElementByAndroidUIAutomator("new UiScrollable("
      		+ "new UiSelector().scrollable(true)).scrollIntoView("                       
      		+ "new UiSelector().textContains(\"Lock screen and security\"));");
      elementToClick.click(); 

iOS


Refer to Scrolling on iOS for further information.

One way we can swipe on iOS, eg. utilizing the iOSNsPredicates. The same is possible using Class Chain or AccessibilityID.
Here we just need to define an object we want to scroll to using NsPredicates.

Eg. on iOS settings (which can be started using bundleId com.apple.Preferences), we want to scroll down to the Notes section, and click it.

Notes can be identified by its value, which is "Notes" - so we know that the object could be found (among other options) through

driver.findElementByIosNsPredicate("value CONTAINS 'Notes'") or driver.findElementByIosNsPredicate("value == 'Notes'")


In order to scroll to the object we can use ExecuteScript:

    HashMap scrollObject = new HashMap<>();
    scrollObject.put("predicateString", "value CONTAINS 'Notes'");
    driver.executeScript("mobile: scroll", scrollObject);

We could then follow a click on it using also NsPredicate, or any other Appium FindElementBy:

driver.findElementByIosNsPredicate("value CONTAINS 'Notes'").click();