Search code examples
androidwebviewandroid-softkeyboard

How to dismiss keyboard while pressing go button in a webview


I have a webview which loads a webpage (with javascript enabled and an interface between that page and the activity which I use to open the camera directly from the webview). I have several fields in that webpage, some of them are numbers some of them are plain text. Every field have a different keyboard layout (although both have the go button).

Currently the Go button is not doing anything. I have a requirement to dismiss the keyboard while clicking on it.

I found this tutorial on how to achieve this, but unfortunately this solution is not working for me as I have different keyboard layouts. When I applied this solution all the fields get number pad layout. or letters depending on outAttrs.inputType

This is my code so far:

public class WebViewGo extends WebView {
    public WebViewGo(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        BaseInputConnection inputConnection = new BaseInputConnection(this, false);
        outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE;
        outAttrs.inputType = EditorInfo.TYPE_CLASS_NUMBER;
        return inputConnection;
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        boolean isDispached = super.dispatchKeyEvent(event);

        if(event.getAction() == KeyEvent.ACTION_UP){
            switch (event.getKeyCode())
            {
                case KeyEvent.KEYCODE_ENTER:
                    InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Activity.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(getWindowToken(), 0);
                break;
            }
        }

        return isDispached;
    }


}

Can I use this solution while keeping several keyboards layouts, or are there other solutions to this issue.

Thank you in advance.

UPDATE

I completely forgot to mention that I tried to remove onCreateInputConnection but without it, it seems dispatchKeyEvent is not working.

UPDATE 2

I managed to add the done button with dismiss functionality only to number fields for some reason it's not working correctly while using text fields

This is my custom webview code so far

public class WebViewGo extends WebView {

    public WebViewGo(Context context, AttributeSet attrs) {
        super(context, attrs);
    }


    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {

        InputConnection connection = super.onCreateInputConnection(outAttrs);
        outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE;
        if ((outAttrs.inputType & InputType.TYPE_CLASS_NUMBER) == InputType.TYPE_CLASS_NUMBER)
        {
            connection = new BaseInputConnection(this, false);
        }else{
            outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT;
        }

        return connection;
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        boolean isDispached = super.dispatchKeyEvent(event);

        if(event.getAction() == KeyEvent.ACTION_UP){
            Log.d("anton","dispatchKeyEvent="+event.getKeyCode());
            switch (event.getKeyCode())
            {
                case KeyEvent.KEYCODE_ENTER:
                    InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Activity.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(getWindowToken(), 0);
                break;
            }
        }

        return isDispached;

    }

}

Solution

  • So this solution evolves many steps which are both native and angular.

    1. Need to create a custom webview to mock enter (action button) in the keyboard to be replaced to 'Done' action

      public class WebViewGo extends WebView {

      public WebViewGo(Context context, AttributeSet attrs) {
          super(context, attrs);
      }
      
      @Override
      public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
          InputConnection connection = super.onCreateInputConnection(outAttrs);
          if((outAttrs.imeOptions & EditorInfo.IME_ACTION_GO)==EditorInfo.IME_ACTION_GO ||
             (outAttrs.imeOptions & EditorInfo.IME_ACTION_NONE)==EditorInfo.IME_ACTION_NONE)
          {
              outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE;
          }
      
          return connection;
      
      }
      

      }

    Need to use this webview instead of the regular webview in your activity/fragment

    1. Create a custom javascript interface

      private class WebAppInterface {

          @JavascriptInterface
          public void dismissKeyboard()
          {
              InputMethodManager imm = (InputMethodManager) TodoItemDetailActivity.this.getSystemService(Activity.INPUT_METHOD_SERVICE);
              imm.hideSoftInputFromWindow(webview.getWindowToken(), 0);
          }
      
      }
      

    adding the interface to the webview

    webview.addJavascriptInterface(new WebAppInterface(), "Android");
    
    1. The trick is when the user click on enter he is in the webview (meaning its focused in the web page (angualr)

    I needed to remove the keyboard when the user is clicking 'Done' in this field.

      onKeyUp(event : any){
        if (event.key === 'Enter') {
          if (typeof Android !== 'undefined' && Android) {
              event.target.value = event.target.value.replace(/\n/g, "");
            //console.log(event.target.value);
            Android.dismissKeyboard();
    
          }
        }
      }
    

    Another small problem that I had was even though I managed to dismiss the keyboard it will still add enter to the end of the text and I needed to remove it, after that it was simple just call the native function that dismisses the keyboard from the activity/fragment using the javascript interface.