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? 
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. 
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
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.