SOLVED: Sliding element horizontally on Adnroid

The React-Native application that I am testing has a modal view with payment methods


When a credit card element is getting moved horizontally (right-to-left), a new button “REMOVE” opens that allows the corresponding card to be removed from the user account

Using the XPath, I can get a list of mobile elements for TextView “MasterCard ****4444, 12/2020” and then randomly pick one. However sliding that element to open the button proved to be challenging. I have tried

    int screenWidth = (int) driver.manage().window().getSize().width;
    MobileElement chosenCreditCard = paymentMethodsList.get(chosenItem);
    TouchAction touchAction = new TouchAction(driver);
    touchAction.press(paymentMethodsList.get(chosenItem)).moveTo(-0.5*screenWidth, 0).release().perform();

and

    int screenWidth = (int) driver.manage().window().getSize().width;
    MobileElement chosenCreditCard = paymentMethodsList.get(chosenItem);
    int chosenCreditCardY = chosenCreditCard.getLocation().getY();
    TouchAction touchAction = new TouchAction(driver);
    touchAction.press(0.8*screenWidth, chosenCreditCardY).moveTo(-0.5*screenWidth, 0).release().perform();

But neither way works. When I observe the action on my phone, the element is getting shifted just a bit, may be by 50 units, and moves back, i.e. the “REMOVE” button does not appear. Appium logs show both press and moveTo actions
responded with 200. I tried adding waitAction before the release() but it seems to do nothing.

What am I possibly missing here? :thinking:

My setup:

  • com.microsoft.appcenter.appium.EnhancedAndroidDriver
  • Appium server 1.7.2 / 1.8.0
  • Java 1.8.0.152
  • io.appium:java-client:5.0.4
  • Sony XPERIA M4 (Android 5.0.1)

SOLVED: Ok, finally I got it working:

  • press needs int coordinates
  • moveTo operates with destination coordinates, not with relative coordinates as some docs are claiming
  • moveTo works poorly when trying to slide an element too far and requires splitting into several consecutive moveTo steps

The final code looks like that (which is a bit too verbose but should be clear to read):

        int screenWidth = (int) driver.manage().window().getSize().width;
        int screenWidth90 = (int) (.9 * screenWidth);
        int screenWidth65 = (int) (.65 * screenWidth);
        int screenWidth40 = (int) (.4 * screenWidth);

        List<MobileElement> paymentMethodsList = driver.findElementsByXPath("//android.widget.TextView[@text=\"MasterCard ****4444, 12/2020\"]");

        TouchAction touchAction = new TouchAction(driver);
        MobileElement chosenCreditCard = paymentMethodsList.get(chosenItem);
        int chosenCreditCardY = chosenCreditCard.getLocation().getY();

        touchAction.press(screenWidth90, chosenCreditCardY)
                .moveTo(screenWidth65, chosenCreditCardY)
                .moveTo(screenWidth40, chosenCreditCardY)
                .release()
                .perform();

As I understand, when you swipe horizontally, REMOVE button shows up and you need to press it, right?

Maybe try changing your touchAction like this:

new TouchAction(driver).press(screenWidth90, chosenCreditCardY).waitAction(1000).moveTo(screenWidth40, chosenCreditCardY).waitAction(1000).release().perform();

… and then click on REMOVE button.

Or if you need to swipe twice, you can do:

touchAction.press(screenWidth90, chosenCreditCardY)
.moveTo(screenWidth65, chosenCreditCardY)
.waitAction(500)
.moveTo(screenWidth40, chosenCreditCardY)
.release()
.perform();

Thanks, @MrZigaS!

Yeah, as I wrote, my solution was too verbose and there definitely some room for removing the redundant staff. I got all of those while doing step-by-step debugging what works and what does not. :wink:

I, as a user, do NOT need to swipe twice. But during the trial-and-error process I have realized that doing the swipe in one go is too fast for application UI to react properly. At the same time, I wanted to avoid extra sleep cycles unless I really have to. having two moveTo’s did the trick but I am sure there are some other ways of achieving the same.

I think …

.waitAction(500)
.waitAction(1500)

… is what you are looking for. Try it in debug mode, you will see the difference :slight_smile: I think you do not need 2 moveTo() methods.

Hi Vic

I am facing same issue for IOS.Can u please help me in that.