Appuim2 not able to identify android elements after scrolling down the mobile screen

Description: The issue described below exists only for Android and not IOS
When I scroll down the mobile device, then the appium stops identifying the elements on the screen after scrolling. As a workaround, I need to switch to web view, perform the action on the element and then switch back to web view. This started happening after I moved to appium 2.

Capabilities defined for device: “appiumVersion”: “2.0.0”, “automationName”: “uiautomator2”

appium java client version in pom.xml: 9.2.0
selenium java client version in pom.xml: 4.18.1

What method/approach do you use for Scrolling? W3C, TouchAction or UiScrollable ?

Hi , I am using TouchAction to scroll. Tried UiScrollable as well but UiScrollable does not work for Android as Android elements are not available until they are in the view.

@parulbhagat-SBS UI scrollable actually works for elements not in view, if you add arg “scrollIntoView”. Basically it will try to scroll multiple times looking for the element that matches the ID/Text/Content-desc.
UiScrollable is the most stable too.

Please try:
given element you want has resource-id: “test1” and index is 0
call the method: scrollToID(“test1”,0);
Method below:

    public void scrollToID(String id, int index) throws InterruptedException {
        try {
            androidDriver.findElement(AppiumBy.androidUIAutomator("new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().resourceId(\"" + id + "\").instance(" + index + "))"));
        }catch (InvalidSelectorException ignored){}
        Thread.sleep(1000);
    }

Lastly TouchAction is now deprecated. Please try W3C

@derolk Some of our elements are identified by xpath instead of ID/Text/Content-desc due to development restrictions in the application . How can I scroll in such case as for xpath I could not find any function like you mentioned for resourceId .

@parulbhagat-SBS It’s best practice to add resource-Ids to all elements but anyways if you still want to scroll using xpaths I would suggest W3C:

    public void swipe(By element, String direction) throws InterruptedException {
        WebElement ele = find(element);
        PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
        Sequence dragNDrop = new Sequence(finger, 1);
        int startX, startY, endX, endY;
        switch (direction) {
            case "RIGHT":
                startX = ele.getRect().x + (ele.getSize().width / 4);
                startY = ele.getRect().y + (ele.getSize().height / 2);
                endX = ele.getRect().x + (ele.getSize().width * 3 / 4);
                endY = ele.getRect().y + (ele.getSize().height / 2);
                break;
            case "LEFT":
                startX = ele.getRect().x + (ele.getSize().width * 3 / 4);
                startY = ele.getRect().y + (ele.getSize().height / 2);
                endX = ele.getRect().x + (ele.getSize().width / 4);
                endY = ele.getRect().y + (ele.getSize().height / 2);
                break;
            case "DOWN":
                startX = ele.getRect().x + (ele.getSize().width / 2);
                startY = ele.getRect().y + (ele.getSize().height / 4);
                endX = ele.getRect().x + (ele.getSize().width / 2);
                endY = ele.getRect().y + (ele.getSize().height * 3 / 4);
                break;
            case "UP":
                startX = ele.getRect().x + (ele.getSize().width / 2);
                startY = ele.getRect().y + (ele.getSize().height * 3 / 4);
                endX = ele.getRect().x + (ele.getSize().width / 2);
                endY = ele.getRect().y + (ele.getSize().height / 4);
                break;
            default:
                throw new IllegalArgumentException("Invalid swipe direction: " + direction);
        }
        dragNDrop.addAction(finger.createPointerMove(Duration.ofSeconds(0),
                PointerInput.Origin.viewport(), startX, startY));
        dragNDrop.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
        dragNDrop.addAction(finger.createPointerMove(Duration.ofMillis(700),
                PointerInput.Origin.viewport(), endX, endY));
        dragNDrop.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
        androidDriver.perform(List.of(dragNDrop));
        Thread.sleep(1000);
    }
It's swipe so remember to scroll Down you actually need to parse parameter "UP"; to scroll UP you need to parse parameter: "DOWN"