How to hide keyboard in iOS mobile automation using Appium

I am using iOS version of 10.2 and xcode version is 8.3.

Can anyone let me know how to hide the keyboard in iOS mobile automation using Appium?

programming language used: Java.

@Arijit_Biswas you have 2 ways:

  1. hide keyboard with tap outside keyboard
  2. type last keyboard key (“Go”, “Next”, “Done” …) to continue

You can also try…

appiumDriver.hideKeyboard();

Which works in some cases still.

I did something wacky like this…

public static void hideKeyboard() {
    if (testParms.isIOS) {
        try {
            if (testParms.isTablet) {
                throw new EmptyStackException();
            } else {
                appiumDriver.hideKeyboard();
                Functions.sleep(2);

                if (keyboardExists()) {
                    // It didn't go away.  Try the alternate method
                    throw new EmptyStackException();
                }
            }
        } catch (Exception e) {
            List<String> ids = Arrays.asList("Hide keyboard", "DONE", "Done", "Return");

            for (int i = 0; i < ids.size() && keyboardExists(); i++) {
                try {
                    AutoControl btnHideKeyboard = new AutoControl(By.id(ids.get(i)));

                    if (btnHideKeyboard.exists() && btnHideKeyboard.isDisplayed()) {
                        btnHideKeyboard.click();
                        break;
                    }
                } catch (Exception e2) {
                    log.info(appiumDriver.getPageSource());
                    log.exceptionAsInfo(e2);
                }
            }
        }
    } else {
        try {
            appiumDriver.hideKeyboard();
        } catch (Exception e) {
            // Yuck!
        }
    }
}
2 Likes

Use swipe() outside keyboard

Did anyone observe this weird issue: when hideKeyboard() is called for iOS simulator, driver taps the microphone button, and instead of just hiding the keyboard, it brings up the “Enable dictation” dialog?

appium 1.6.5, java, ios simulator is iPhone 6, platform 10.3.1, running on macOs

That’s how it looks BEFORE hideKeyboard() : https://pasteboard.co/GATmMGJ.png
Right after hideKeyboard(): https://pasteboard.co/GATn98R.png

@darina-techery you can at least 4 ways:


            ((IOSDriver) driver).hideKeyboard(HideKeyboardStrategy.PRESS_KEY, "Done"); // Done can change to whatever valid on our screen
            ((IOSDriver) driver).hideKeyboard(HideKeyboardStrategy.TAP_OUTSIDE);
            last_iOSKeyboardKey.click(); //my favourite. last_iOSKeyboardKey you can find by any way you know.
            // last 4 is tap yourself outside in any place on screen outside keyboard e.g. in center of header
1 Like

Thanks Aleksei, I’ll try these. No luck with the first one, though.
But actually, the situation I described sounds like a bug to me: is it ok to bring up voice input on hideKeyboard()?
I updated appium to 1.6.6, beta 2, java client to 5.0.0-BETA9, and the behavior is the same.

UPD: I also noticed that there is no “Done” or “Close” button on soft keyboard, its last button is “#”: Pasteboard - Uploaded Image

@darina-techery in your case i suggest to tap outside on this screen.

Doesn’t work either, unfortunately. None of the ways mentioned above worked.

I solved this issue by adding a workaround: instead of custom setText() operation, which includes sendKeys() and hideKeyboard() calls, I simply send keys and tap “Done” button above the text field.

Still, it is a workaround. I believe the general problem is the following: if there is no “return”/“done”/“hide” button on a soft keyboard, driver hits voice input key instead.
I think it’s worth mentioning it in Appium docs (that is, if there is no “return” button on a soft keyboard in particular situation, hideKeyboard() will not work). Or the method should throw an exception (e.g., “Appium driver tried to close the keyboard, but no “close” button was found, use some controls outside the keyboard to dismiss it”). Now this method does something different from what’s mentioned in its name, and does it silently, no warning, no exception.

I just did this:

    const doneButton = await this._driver.findElementByText('Done');
    await doneButton.tap();

Worked for me.

Locate the return or Done keyboard button in inspector

driver.findElement(By.xpath("//XCUIElementTypeKeyboard//XCUIElementTypeButton[@name=‘Return’]")).click();

Define it in the cap:

capabilities.setCapability(“unicodeKeyboard”, true);

You could inspect for the element OK or DONE from the iOS Keyboard and you will have something like these:

//JAVA
List els1 = (MobileElement) driver.findElementsByName(“OK”);
els1.get(0).click();

//Python
element = driver.find_elements_by_name(“OK”)
element[0].click()

//Javascript Webdriver.io
let element = driver.elements(“name=OK”);
element[0].click();

Hope that could work for you, for me works perfectly.

Use the below swiped down method for the hide keyboard in IOS.

public void swipeDown() throws InterruptedException
{
Thread.sleep(3000);

		  	Dimension dimension = driver.manage().window().getSize();
	    	int end_x = (int)(dimension.width*.5);
	    	int end_y = (int)(dimension.height*.96);
	    	
	    	int start_x = (int)(dimension.width*.5);
	    	int start_y = (int)(dimension.height*.35);
	    			
	    	
	    	TouchAction  action =new TouchAction(driver);
	    	action.press(PointOption.point(start_x, start_y))
	    	.waitAction(WaitOptions.waitOptions(Duration.ofMillis(2200)))
	    	.moveTo(PointOption.point(end_x, end_y))
	    	.release()
	    	.perform();	    	
	    	
}

Appium 2+ has deprecated TouchActions also. So, here is my working solution. Hope it will be helpful.


Android solution:

As mentioned above:
capabilities.setCapability(“unicodeKeyboard”, true); //This will works only for Android


iOS solution:

// This method will handle NoSuchElementException if WebElement can't be found on the page
public static boolean isElementDisplayed(final String selector) {
  boolean isDisplayed;
  try {
    WebElement element = appiumDriver.findElement(AppiumBy.xpath(selector);
    isDisplayed = element.isDisplayed();
  } catch (NoSuchElementException | StaleElementReferenceException e) {
    isDisplayed = false;
  }
  return isDisplayed;
}

// This method will check if keyboard is present over the screen
private static boolean isKeyboardPresent() {
  return appiumDriver.executeScript("mobile: isKeyboardShown").toString().equals("true");
}

// This method will hide keyboard in three ways
public static void hideKeyboardLayout() {
 if (isKeyboardPresent()) {
   try {
     // As official documentation says, 'hideKeyboard()' method will only work if there is a present button
     // that can close the keyboard
     appiumDriver.getPageSource();
     ((IOSDriver) appiumDriver).hideKeyboard("Done"); 
     // Using 'Done' as key name will handle different language keyboard
   } catch(InvalidElementStateException e) {
     // This will catch exception when keyboard doesn't have present button to close the keyboard
     if (isElementDisplayed("//XCUIElementTypeButton[@name='Next:']")) {
       // This step will click on the keyboard 'Next' button to enable 'Done' button, then hide it
       // Use xpath strategy for the next button to handle different language keyboard
       appiumDriver.findElement(AppiumBy.xpath("//XCUIElementTypeButton[@name='Next:']")).click();
       ((IOSDriver) appiumDriver).hideKeyboard("Done"); 
     } else if (isElementDisplayed("//XCUIElementTypeButton[@name='Done']")) {
       // This step will handle if phone number Dialer keypad is present over the screen
       appiumDriver.findElement(AppiumBy.xpath("//XCUIElementTypeButton[@name='Done']")).click();
     }
 }
assertFalse(isKeyboardPresent());
appiumDriver.getPageSource();
}

Note: This is a raw solution. All the WebElement defining is recommended to be done in the page-object pattern.

Any solution for this with java client 9.0.0. They seem to have removed this capability (unicodeKeyboard and resetKeyboard capbilities removed from java-client 9.0.0 · Issue #2059 · appium/java-client · GitHub)

I have replied to the above issue

1 Like

Wowww. Welcome back!

1 Like

He he :slight_smile: Yes, I was away from mobile automation for several years. But I’m back now :blush:

Thanks for the welcome back and thanks @mykola-mokhnach for the answer. I need to study the documentation again :sweat_smile:

1 Like