How to swipe in a specific area until target element is show?

appium version: V1.13.0
simulator android version: 9.0
i want to swipe in the specific area like below picture shows, and until the “edit” element is appear.
the target element is not in the current page, here is my codes, but swipe action doesn’t work.
touchAction is useless,too. cause element touch press is beyond this area.
1 2

area = self.driver.find_element_by_class_name("android.support.v7.widget.RecyclerView").size
height = area["height"]
width = area["width"]
while True:
    try:
        matchString = "Edit"
        end_el = self.driver.find_element_by_android_uiautomator("new UiSelector().\
       text(\""+matchString+"\")").is_displayed()
        if end_el:
            break
    except:
        self.driver.swipe_right(width/2, height/2, width/3, height/2, 200)
        #TouchAction(self.driver).press(x=width/4, y=height/2). \
        #                    move_to(x=width/2, y=height/2).release().perform()
        continue

many thanks for help!

@johny try:

String text = "your text"
WebElement el = driver.findElement(MobileBy
                    .AndroidUIAutomator("new UiScrollable(new UiSelector()).setAsVerticalList().scrollIntoView("
                            + "new UiSelector().text(\""+text+"\"));"))); 

as far as you have several scroll views also better set scrollView ID:

String text = "your text"
WebElement el = driver.findElement(MobileBy
                    .AndroidUIAutomator("new UiScrollable(new UiSelector().resourceId(\"YOUR_RECYCLERVIEW_ID\")).setAsVerticalList().scrollIntoView("
                            + "new UiSelector().text(\""+text+"\"));"))); 
3 Likes

@Aleksei thanks for reply first, i’ve tried your code, but it doesn’t work.cause it’s scroll the page vertically, all i want is swipe in that area horizontally

Oiiiii replace to horisontal :slight_smile:

setAsHorizontalList

1 Like

@Aleksei i don’t want to swipe the whole page :joy: i mean i need swipe in a specific area to find an element not in current page.

It will swipe whatever you asking it for! If on page several scroll views it will swipe whatever first which means random. So you need specify in such case scrollView element that needed to be swiped.

So in general you can specify view id, orientation (horisontal or vertical) and swipe direction. These all needed when view has several scrollViews - to help uiAutomator understand what is needed.

On your view you have at least 3 scrollViews.

@Aleksei Thank you so much, it’s ok now, like you said before(method 2), i have to specify which element i need to swipe, use attribute like resource-id or className etc.

1 Like

Hi @Aleksei I tried using the same command its swiping but instead of swiping down its swiping up . Is there is any way to say the direction in which it will swipe .

Code snippet:

MobileElement element = (MobileElement)getTLDriver().findElement(MobileBy.AndroidUIAutomator(
                    "new UiScrollable(new UiSelector().resourceId(\"resourceId\")).setAsVerticalList().scrollIntoView("
                            + "new UiSelector().text(\"Paragraph\"))"));
1 Like

@deepikathiru all command are here -> https://developer.android.com/reference/android/support/test/uiautomator/UiScrollable

UISelector tries first to find start of scrollableView.

Thanks @Aleksei I have a doubt, the ListView I am trying to scroll has its scrollable value as ‘false’ does that got any impact with scrolling that Appium is trying to do ?

no idea. but if you try to check “scrollable=true” - it will affect. just not add it.

Ohkk will ask them to try and let me check on that

Hier 3 possible solutions:
for more details check here:
https://developer.android.com/reference/android/support/test/uiautomator/UiScrollable
https://developer.android.com/reference/androidx/test/uiautomator/UiSelector

public MobileElement swipeToChildByDescription(String locatorType, String viewIdentificator, String text)
{
    WebElement element = driver.findElement(MobileBy
            .AndroidUIAutomator("new UiScrollable(new UiSelector()."+locatorType+"(\""+viewIdentificator+"\")).setAsHorizontalList()." +
                    "getChildByDescription("
                    + "new UiSelector().className(\"android.widget.View\"),\""+ text+ "\",true);"));
    return (MobileElement) element;
}

public MobileElement swipeToChildByText(String locatorType, String viewIdentificator, String text)
{
WebElement element = driver.findElement(MobileBy
.AndroidUIAutomator(“new UiScrollable(new UiSelector().”+locatorType+"(""+viewIdentificator+"")).setAsHorizontalList()." +
“getChildByText(”
+ “new UiSelector().className(“android.widget.TextView”),”"+ text+ “”,true);"));
return (MobileElement) element;
}

public MobileElement swipeHorizontalyToEnd(String locatorType, String viewIdentificator)
{
    WebElement element = driver.findElement(MobileBy
            .AndroidUIAutomator("new UiScrollable(new UiSelector()."+locatorType+"(\""+viewIdentificator+"\")).setAsHorizontalList()." +
                    "scrollToEnd();"));
    return (MobileElement) element;
}


public MobileElement swipeHorizontaly(String locatorType, String viewIdentificator, String text, String attribute)
{
    WebElement element = driver.findElement(MobileBy
            .AndroidUIAutomator("new UiScrollable(new UiSelector()."+locatorType+"(\""+viewIdentificator+"\")).setAsHorizontalList()." +
                    "scrollIntoView("
                    + "new UiSelector()."+attribute+"(\""+text+"\"));"));
    return (MobileElement) element;
}

i tried this code to make horizontal swipe in specific area and its worked. thank you so much :slight_smile:

@Aleksei
Good evening

Please tell me, I use your method (which was thrown above) and it works with the whole page.

But here I needed to swipe a specific text to the left. And it doesn’t help me.

Can you please tell me what to think?

Here is a screenshot of what I need to do, but I can’t figure out how to write the code =(

it will not help in this way. create your function that will swipe by element. some examples like -> https://appium.io/docs/en/writing-running-appium/tutorial/swipe/simple-element/

the only problem that TouchAction is deprecated. and you need replace it with something new :slight_smile:

i use appium w3c -> https://appium.io/docs/en/commands/interactions/actions/

mine code example is:

                PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
                Sequence tapSeq = new Sequence(finger, 1);
                tapSeq.addAction(finger.createPointerMove(Duration.ofMillis(0),
                        PointerInput.Origin.viewport(), centerX, centerY));
                tapSeq.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
                tapSeq.addAction(finger.createPointerMove(Duration.ofMillis(200),
                        PointerInput.Origin.viewport(), endX, endY));
                tapSeq.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
                driver.perform(Arrays.asList(tapSeq));

Please direct me :піт:

  1. I get an InvalidArgumentException error: on my line driver.perform(Arrays.asList(dragNDrop));

I don’t understand why?

  1. I don’t quite understand how it works and what needs to be indicated here:
    MobileElement dragMe = (MobileElement) driver.findElementByAccessibilityId(“dragMe”);
    MobileElement drop =(MobileElement)driver.findElementByAccessibilityId(“dropzone”);

What I wrote:

MobileElement dragMe = (MobileElement) driver.findElement(By.xpath(“//android.widget.TextView[contains(@text, ‘м. Дніпро, вул. Щукіна, буд. 1’)]”));
MobileElement drop =(MobileElement)driver.findElement(By.xpath(“//android.widget.TextView[contains(@text, ‘м. Дніпро, вул. Щукіна, буд. 1’)]”));

    Point source = dragMe.getCenter();
    Point target = drop.getCenter();
    PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
    Sequence dragNDrop = new Sequence(finger, 1);
    dragNDrop.addAction(finger.createPointerMove(Duration.ofSeconds(1),
            PointerInput.Origin.viewport(), source.x, source.y));
    dragNDrop.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
    dragNDrop.addAction(finger.createPointerMove(Duration.ofSeconds(1),
            PointerInput.Origin.viewport(),target.x, target.y));
    dragNDrop.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
    driver.perform(Arrays.asList(dragNDrop));

mine code swipe from element center to some direction (in your case you need swipe to Left to see edit buttons):

Rectangle rect = ((WebElement) el).getRect();

        int centerX = rect.x + (rect.width / 2);
        int centerY = rect.y + (rect.height / 2);
        int endX = 0;
        int endY = 0;

        if (dir.equals("u")) {
            endX = centerX;
            endY = rect.y + 5;
        }
        if (dir.equals("d")) {
            endX = centerX;
            endY = rect.y + (rect.getHeight() - 5);
        }
        if (dir.equals("l")) {
            endX = rect.x + 5;
            endY = centerY;
        }
        if (dir.equals("r")) {
            endX = rect.x + (rect.getWidth() - 5);
            endY = centerY;
        }
try {
                PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
                Sequence tapSeq = new Sequence(finger, 1);
                tapSeq.addAction(finger.createPointerMove(Duration.ofMillis(0),
                        PointerInput.Origin.viewport(), centerX, centerY));
                tapSeq.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
                tapSeq.addAction(finger.createPointerMove(Duration.ofMillis(200),
                        PointerInput.Origin.viewport(), endX, endY));
                tapSeq.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
                driver.perform(Arrays.asList(tapSeq));
                break;
            } catch (Exception ex) {
                Logger.log(createAssertionLog("FAILED"));
            }

Thank you!!
It is work
Have a nice day :smiling_face_with_three_hearts: