How to Use Touch Actions in Appium: Swipe Tap Touch

How to Use Touch Actions in Appium? Hi all, in this article, I will answer this question and share with you the details of how to do some appium mobile actions such as swipe, tap, press, multi-touch. I wrote a MobileActions class which comprises of these actions. You can instantiate it into your BaseScreen or BasePage class and use it in your Screen/Page classes. I will start with the MobileActions class. By using these class, you can do the below actions:

  • Tab by using an element
  • Tab by using x,y coordinates
  • Press by using an element and duration (in seconds)
  • Press by using x,y coordinates, and duration (in seconds)
  • Horizontal swipe by using the start and end percentage of the screen and an anchor for the height.
  • Vertical swipe by using the start and end percentage of the screen and an anchor for the width.
  • Swipe one element to another element
  • Multitouch by using an element

How to Use Touch Actions in Appium Code Examples

MobileActions Class – Here is the code of all actions:

package utilities;

import static io.appium.java_client.touch.TapOptions.tapOptions;
import static io.appium.java_client.touch.WaitOptions.waitOptions;
import static io.appium.java_client.touch.offset.ElementOption.element;
import static io.appium.java_client.touch.offset.PointOption.point;
import static java.time.Duration.ofMillis;
import static java.time.Duration.ofSeconds;

import io.appium.java_client.MobileElement;
import io.appium.java_client.MultiTouchAction;
import io.appium.java_client.TouchAction;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
import org.openqa.selenium.Dimension;

public class MobileActions {
    private AndroidDriver<MobileElement> driver;

    public MobileActions (AndroidDriver driver) {
        this.driver = driver;
    }

    //Tap to an element for 250 milliseconds
    public void tapByElement (AndroidElement androidElement) {
        new TouchAction(driver)
            .tap(tapOptions().withElement(element(androidElement)))
            .waitAction(waitOptions(ofMillis(250))).perform();
    }

    //Tap by coordinates
    public void tapByCoordinates (int x,  int y) {
        new TouchAction(driver)
            .tap(point(x,y))
            .waitAction(waitOptions(ofMillis(250))).perform();
    }

    //Press by element
    public void pressByElement (AndroidElement element, long seconds) {
        new TouchAction(driver)
            .press(element(element))
            .waitAction(waitOptions(ofSeconds(seconds)))
            .release()
            .perform();
    }

    //Press by coordinates
    public void pressByCoordinates (int x, int y, long seconds) {
        new TouchAction(driver)
            .press(point(x,y))
            .waitAction(waitOptions(ofSeconds(seconds)))
            .release()
            .perform();
    }

    //Horizontal Swipe by percentages
    public void horizontalSwipeByPercentage (double startPercentage, double endPercentage, double anchorPercentage) {
        Dimension size = driver.manage().window().getSize();
        int anchor = (int) (size.height * anchorPercentage);
        int startPoint = (int) (size.width * startPercentage);
        int endPoint = (int) (size.width * endPercentage);

        new TouchAction(driver)
            .press(point(startPoint, anchor))
            .waitAction(waitOptions(ofMillis(1000)))
            .moveTo(point(endPoint, anchor))
            .release().perform();
    }

    //Vertical Swipe by percentages
    public void verticalSwipeByPercentages(double startPercentage, double endPercentage, double anchorPercentage) {
        Dimension size = driver.manage().window().getSize();
        int anchor = (int) (size.width * anchorPercentage);
        int startPoint = (int) (size.height * startPercentage);
        int endPoint = (int) (size.height * endPercentage);

        new TouchAction(driver)
            .press(point(anchor, startPoint))
            .waitAction(waitOptions(ofMillis(1000)))
            .moveTo(point(anchor, endPoint))
            .release().perform();
    }

    //Swipe by elements
    public void swipeByElements (AndroidElement startElement, AndroidElement endElement) {
        int startX = startElement.getLocation().getX() + (startElement.getSize().getWidth() / 2);
        int startY = startElement.getLocation().getY() + (startElement.getSize().getHeight() / 2);

        int endX = endElement.getLocation().getX() + (endElement.getSize().getWidth() / 2);
        int endY = endElement.getLocation().getY() + (endElement.getSize().getHeight() / 2);

        new TouchAction(driver)
            .press(point(startX,startY))
            .waitAction(waitOptions(ofMillis(1000)))
            .moveTo(point(endX, endY))
            .release().perform();
    }

    //Multitouch action by using an android element
    public void multiTouchByElement (AndroidElement androidElement) {
        TouchAction press = new TouchAction(driver)
            .press(element(androidElement))
            .waitAction(waitOptions(ofSeconds(1)))
            .release();

        new MultiTouchAction(driver)
            .add(press)
            .perform();
    }
}

You can use this class by instantiating it in BasePage or BaseScreen class as shown below:

public class BaseScreen {
    protected AndroidDriver<MobileElement> driver;
    protected WebDriverWait                wait;
    protected MobileActions                mobileActions;

    public BaseScreen(AndroidDriver<MobileElement> driver) {
        this.driver = driver;
        wait = new WebDriverWait(driver, 15);
        mobileActions = new MobileActions(driver);
    }

......
......
......
//You BaseScreen class code continues.

And from now on you can use mobileActions object in your screen classes too. You can see its usage in below code snippet.

package screens;

import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
import lombok.SneakyThrows;
import org.openqa.selenium.By;
import org.openqa.selenium.support.ui.ExpectedConditions;

public class CandidateMainScreen extends BaseScreen {
    public CandidateMainScreen(AndroidDriver<MobileElement> driver) {
        super(driver);
    }

    /**
     * Mobile Elements
     */
    By allowWhenUsingBy = By.id("com.android.permissioncontroller:id/permission_allow_foreground_only_button");
    By jobsBy           = By.id("com.isinolsun.app:id/rootRelativeView");

    /**
     * Actions
     */
    public void allowNotification() {
        if (wait.until(ExpectedConditions.visibilityOfElementLocated(allowWhenUsingBy)).isDisplayed()) {
            wait.until(ExpectedConditions.visibilityOfElementLocated(allowWhenUsingBy)).click();
        }
    }

    @SneakyThrows
    public void clickToJob() {
        wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(jobsBy)).get(1).click();
        Thread.sleep(4000); //Just Wait for a while
    }

    public void swipeDownAndClickToJob() {
        waitAndFindElements(jobsBy);

        mobileActions.verticalSwipeByPercentages(0.6, 0.3, 0.5);

        mobileActions.swipeByElements((AndroidElement) waitAndFindElements(jobsBy).get(1),
            (AndroidElement) waitAndFindElements(jobsBy).get(0));

        mobileActions.swipeByElements((AndroidElement) waitAndFindElements(jobsBy).get(0),
            (AndroidElement) waitAndFindElements(jobsBy).get(1));

        mobileActions.tapByElement((AndroidElement) waitAndFindElements(jobsBy).get(1));
    }
}

As you see in the above screen class, we can use mobileAction object to perform swipe and tab actions.

  • verticalSwiteByPercentages gets start point percentage with respect to the screen, endpoint percentage with respect to the screen, and anchor percentage with respect to the screen.
  • swipeByElements gets the first and second elements to perform swipe operation.
  • tabByElement gets an element to tap on it.

You can use all appium mobile actions which are declared in MobileActions class in this way. Also, you can add new appium mobile actions to enhance this class. This code is modified for an Android project but you can change the driver type as AppiumDriver or as IOSDriver to use it in your project needs.

GitHub Project

https://github.com/swtestacademy/appium-parallel-tests/tree/appium-mobile-actions

Youtube Demo Video

I hope you enjoy reading the appium mobile actions article and it helped you in your mobile automation projects. Please share your feedback on the comment section with us.

You can also find our Appium articles here: Appium articles.

Thank you.
Onur Baskirt

61 thoughts on “How to Use Touch Actions in Appium: Swipe Tap Touch”

    • Welcome Siddhart. I tried some of them and they worked without any problem. If you face with a problem, please do not hesitate to write a comment with the problem definition and I will try to fix it ASAP. :) Have a good day!

      Reply
    • //Wait Visibility of an element
      protected void waitVisibility (By by) {
      wait.until(ExpectedConditions.visibilityOfElementLocated(by));
      }

      protected AndroidElement findElement (By by) {
      return (AndroidElement) driver.findElement(by);
      }

      Reply
  1. Hi Onur,
    Thanks for the article.But it is asking me to create method for point .then i downgraded to java client 6.0.0 version.But still problem remains same.Can you help me

    Reply
  2. Hi Onur Baskirt,
    I have another question:
    Is it necessary to create new TouchAction(driver) in every method?
    Can i create a private member variable of TouchAction and use it without creating a new object for every action, or is it required so that previous configuration will not be executed when i call another method?

    Reply
    • I think you can do it. Right now, I could not try on my machine cuz I need to do a lot of settings for appium but please would you try this for me as well. It is better to try. If u get an error, please share it as well. Thank you.

      Reply
  3. Thank you so much. I have another question: which I didn’t find a solution for it:
    How can I go to the home screen and back to the app? I don’t want to lunch the app again from the first point I want to back to the same page as I left the app.

    Reply
  4. hi sir.

    how to perform the below tap by co-ordinates using appium ios device

    //Tap by coordinates
    public void tapByCoordinates (int x, int y) {
    new TouchAction(driver)
    .tap(point(x,y))
    .waitAction(waitOptions(Duration.ofMillis(250))).perform();
    }

    thank you.

    Reply
  5. Thank you again, your tutorials are like the treasure for me. I head to a problem:
    when I use “sendtext”, application crashes! the text length is not beyond text field limit. but it happens more when the field is empty( for the edit that section doesn’t sometimes!)
    Appium version: 1.9.1
    could you please let me know if you have any solution?

    Reply
  6. Hi Onur,

    We have always issue with handling date time picker in appium even there is no proper solution in appium forum. I would request to check and provide solution how we can deal with .

    Ex. While entering date of birth and we are into year field we have scroll up till past year.
    Scroll down to certain number which is not visible that point of time.

    Waiting for your reply. Here we dont have option to upload screenshot or else I could have posted the same.

    Reply
    • It look so tricky. Is it possible to enter the year text? Only scroll element available? Are you doing

      do a scroll
      then check the year is visible and present
      if yes tab it
      if not do one more scroll
      then check the year is visible and present
      if yes tab it
      if not do one more scroll
      ….

      You should write a loop and try to do this flow. Now, I can only suggest this Siddharth.

      Reply
    • public static void swipeHorizontal(AppiumDriver driver, double startPercentage, double finalPercentage, double anchorPercentage, int duration) throws Exception {
      Dimension size = driver.manage().window().getSize();
      int anchor = (int) (size.height * anchorPercentage);
      int startPoint = (int) (size.width * startPercentage);
      int endPoint = (int) (size.width * finalPercentage);
      new TouchAction(driver).press(startPoint, anchor).waitAction(Duration.ofMillis(duration)).moveTo(endPoint, anchor).release().perform();
      }

      public static void swipeVertical(AppiumDriver driver, double startPercentage, double finalPercentage, double anchorPercentage, int duration) throws Exception {
      Dimension size = driver.manage().window().getSize();
      int anchor = (int) (size.width * anchorPercentage);
      int startPoint = (int) (size.height * startPercentage);
      int endPoint = (int) (size.height * finalPercentage);
      new TouchAction(driver).press(anchor, startPoint).waitAction(Duration.ofMillis(duration)).moveTo(anchor, endPoint).release().perform();
      }
      Call them by:

      For scroll up: swipeVertical((AppiumDriver)driver,0.9,0.1,0.5,3000);

      For scroll down: swipeVertical((AppiumDriver)driver,0.1,0.9,0.5,3000);

      For right to left: swipeHorizontal((AppiumDriver) driver,0.9,0.01,0.5,3000);

      For left to right: swipeHorizontal((AppiumDriver) driver,0.01,0.9,0.5,3000);

      ref: https://stackoverflow.com/questions/49233444/swipe-funtion-in-andriod-for-java-client-5-0-3-is-not-working

      Just play with these numbers on your application.

      Reply
  7. Hi Onur i used same code as per your suggested when i execute test swipe is not showing in screen but the test is passed. Help me on this thank you.
    appium-1.9.0
    java-client – 6.1.0
    selenium – 3.14.0

    my code
    DesiredCapabilities capabilities=new DesiredCapabilities();
    capabilities.setCapability(“platformName”, “Android”);
    capabilities.setCapability(“platformVersion”, “7.0”);
    capabilities.setCapability(“appPackage”, “com.hmh.api”);
    capabilities.setCapability(“appActivity”, “com.hmh.api.ApiDemos”);
    capabilities.setCapability(“deviceName”, “3300e5417489a4ed”);
    AndroidDriver driver=new AndroidDriver(new URL(“http://127.0.0.1:4723/wd/hub”), capabilities);
    Thread.sleep(5000);
    WebElement element = driver.findElement(By.xpath(“//android.widget.TextView[@text=’App’]”));
    TouchAction action=new TouchAction(driver);
    action.tap(ElementOption.element(element)).perform();
    Thread.sleep(3000);
    org.openqa.selenium.Dimension size = driver.manage().window().getSize();
    int anchor = (int) (size.width * 0.50);
    int startPoint = (int) (size.height * 0.50);
    int endPoint = (int) (size.height * 0.90);
    action.press(PointOption.point(anchor, startPoint))
    .waitAction(WaitOptions.waitOptions(Duration.ofMillis(200)))
    .moveTo(PointOption.point(anchor, endPoint)).release().perform();

    Thread.sleep(5000);
    driver.quit();

    Reply
  8. Hi Onur,

    Do you know is possible to perform double tap action and that action not being two consequtive tap actions. It would be like double tap on instagram app, when you like some photos.

    Reply
  9. new TouchAction(android)
    .press(point(startX,startY))
    .waitAction(waitOptions(ofMillis(2000)))
    .moveTo(point(endX, endY))

    .release().perform();

    This does not work, just highlighting one element

    Reply
  10. hello,
    I am facing the problem with swipe for the end of the particular elements in an e-commerce app.
    one time swipe is working but not at the element I need to click.

    Reply
  11. one more thing, can I click on text tox using coordinate and then can I send the send key on that text box…Plz Give solution

    Reply
  12. Hi Onur,

    I wanted to do vertical scroll till the the mentioned/specific data is located. I am using latest appium 1.10 . Please let me know any solution, i m struggling with this alot.

    Reply
  13. Hi Onur,

    Issue 1:

    I’m not able to Click/Tap on particular button when I’m automating in mobile web browser using selenium Java. I have tried in all ways like below:

    Actions:
    (1) Tap action
    public void TapMobile() {
    if (elementEnabled()) {
    WebElement Element1 = Driver.findElement(By.xpath(“Element”));
    TouchActions tapAction = new TouchActions(Driver).singleTap(Element1);
    tapAction.perform();
    }
    (2) PointClick
    if (elementEnabled()) {
    Point point = Element.getLocation();
    int xcord = point.getX();
    System.out.println(“Position of the webelement from left side is ” + xcord + ” pixels”);
    int ycord = point.getY();
    System.out.println(“Position of the webelement from top side is ” + ycord + ” pixels”);
    Actions action = new Actions(Driver)
    action.moveToElement(Element, xcord, ycord).click().build().perform();
    }
    (3) AjaxClick
    if (elementEnabled()) {
    // Wait wait = new FluentWait(Driver)
    // .withTimeout(30,SECONDS)
    // .pollingEvery(5,SECONDS)
    // .ignoring(NoSuchElementException.class);
    WebElement Element1 = (new WebDriverWait(Driver, 30))
    .until(ExpectedConditions.presenceOfElementLocated(By.xpath(“Element”)));
    Element1.click();
    }
    }

    At the end, I’m getting this exception: org.openqa.selenium.JavascriptException: javascript error: Argument to isShown must be of type Element

    Issue 2:
    I’m not able to verify/get a value from a text box when I’m automating in mobile web browser using Selenium Java. Please see my code below:

    (1) Get textbox value
    public void TextBoxValue() {
    if (Element.isEnabled()) {
    String txt= Element.getAttribute(“value”);
    System.out.println(“Text box value is ” + txt);
    }
    }

    (2) Verify a textbox value
    public void VerifyTextMatch() {
    if (Data != null) //Data which wants to verify
    {
    String Actual = Element.getText(); // Here , I’m trying to get the text
    if (Condition.equalsIgnoreCase(“true”)) {
    if (Actual.contains(Data)) {
    Report.updateTestLog(Action, “Text Matched as expected, Actual: ” + Actual + ” Expected: ” + Data,
    Status.PASS);
    } else {
    Report.updateTestLog(Action, “Text not Matched, Actual: ” + Actual + ” Expected: ” + Data,
    Status.FAIL);
    }
    } else if (Condition.equalsIgnoreCase(“false”)) {
    if (!Actual.contains(Data)) {
    Report.updateTestLog(Action,
    “Text not Matched as expected, Actual: ” + Actual + ” Expected: ” + Data, Status.PASS);
    } else {
    Report.updateTestLog(Action, “Text should not Match, Actual: ” + Actual + ” Expected: ” + Data,
    Status.FAIL);
    }
    }

    }
    }

    Please help me to fix these issues & suggest your thoughts.

    Thanks!

    Reply
  14. Hi Onur, Thanks for your response. Setup has been done perfectly, but we are facing some issues as mentioned above. It would be great help if you give any suggestions.

    One more question is, Do you have any idea about “touchstart” javascript mobile action, how to use in selenium web driver java?

    Thanks!!!

    Reply
  15. Hi Onur,

    How do i select value from auto complete drop down?

    I entered the value “Unit” and from the suggestion i want to select 2nd option which is “United States” but don’t know what syntax should be used
    Got an understanding that pressKeyCode method is is deprecated hence,i am not able to find an alternate method to select value from dropdown as don’t know the syntax for presskey method.
    driver.pressKeyCode(AndroidKeyCode.KEYCODE_PAGE_DOWN);
    driver.pressKeyCode(AndroidKeyCode.ENTER);;

    Please assist

    Reply
  16. Hi Onur,

    After i scroll to end of the page , the focus to the element which i have to click is lost. Instead of clicking on element it click on some random location. The Inspector is also not able to locate it after the scroll.

    Reply
    • I have not encountered it before, but I would put a debug point after the scroll and output which elements are there. If the scroll is fast, maybe it’s trying to click before it appears on the screen, or the code clicks the element before it appears.

      Reply
  17. I want to tap on an element on ios device.. I am using below code which works sometime but not trust worthy as it dont perform the action every time

    Map args = new HashMap();
    args.put(“element”, (myelement.getId()));
    args.put(“x”, 2);
    args.put(“y”, 2);
    appiumDriver.get().executeScript(“mobile: tap”, args);

    Reply
    • Bard’s reply:

      There are a few ways to tap a location by coordinate in Appium 2.0. One way is to use the tap command. The tap command takes three arguments: the number of fingers to use, the x-coordinate, and the y-coordinate. For example, the following command would tap the screen with one finger at the coordinates (271, 642):

      Code snippet
      driver.tap(1, 271, 642);
      Use code with caution. Learn more
      Another way to tap a location by coordinate is to use the elementClick command. The elementClick command takes two arguments: the element to click on and the duration of the click. For example, the following command would click on the element with the id foo for 500 milliseconds:

      Code snippet
      driver.elementClick(driver.findElementById(“foo”), 500);
      Use code with caution. Learn more
      Finally, you can also use the actions API to tap a location by coordinate. The actions API allows you to chain together a series of actions, such as press and release. For example, the following code would tap the screen at the coordinates (271, 642) for 500 milliseconds:

      Code snippet
      driver.actions().press(271, 642).release().perform();
      Use code with caution. Learn more
      Which method you use to tap a location by coordinate depends on your specific needs. The tap command is the simplest option, but it is not as flexible as the elementClick command or the actions API. The elementClick command is more flexible than the tap command, but it requires you to know the ID of the element you want to click on. The actions API is the most flexible option, but it is also the most complex.

      Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.