Question

I have a problem with soft keyboard backspace in Android (4.2).

I have a custom editor in a WebView (CodeMirror), which uses an empty <textarea> internally. It seems that backspace is not sent by an Android system unless it believes there is some text in the <textarea>.

I have overridden WebView onCreateInputConnection in an attempt to dumb down soft input:

@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
    Log.d("CustomWebView", "onCreateInputConnection(...)");
    BaseInputConnection connection = new BaseInputConnection(this, false);
    outAttrs.inputType = InputType.TYPE_NULL;
    outAttrs.imeOptions = EditorInfo.IME_ACTION_NONE;
    outAttrs.initialSelStart = -1;
    outAttrs.initialSelEnd = -1;

    return connection;
}

However, this does not work, and even onKeyUp is not called for backspace.

How do I force soft keyboard to always send backspace?

Was it helpful?

Solution

Ok, finally figured this out.

In Android 4.2 (maybe in earlier versions as well) the backspace is not sent as a sendKeyEvent(..., KeyEvent.KEYCODE_DEL) by the standard soft keyboard. Instead, it is sent as deleteSurroundingText(1, 0).

So the solution in my case is to make a custom InputConnection with the following:

@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {       
    // magic: in latest Android, deleteSurroundingText(1, 0) will be called for backspace
    if (beforeLength == 1 && afterLength == 0) {
        // backspace
        return super.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
            && super.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
    }

    return super.deleteSurroundingText(beforeLength, afterLength);
}

Note: Please let me know if I am doing something stupid here, as it is my 3rd day writing for Android.

OTHER TIPS

this code will be better, it work with more keyboard :D

@Override
  public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
      outAttrs.actionLabel = null;
      outAttrs.inputType = InputType.TYPE_NULL;
      final InputConnection con = new BaseInputConnection(this,false);
      InputConnectionWrapper public_con = new InputConnectionWrapper(
              super.onCreateInputConnection(outAttrs), true) {
          @Override
          public boolean deleteSurroundingText(int beforeLength, int afterLength) {
              if (beforeLength == 1 && afterLength == 0) {
                  return this.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
                          && this.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
              }
              return super.deleteSurroundingText(beforeLength, afterLength);
          }

          @Override
          public boolean sendKeyEvent(KeyEvent event) {
              if(event.getKeyCode() == KeyEvent.KEYCODE_DEL){
                  return con.sendKeyEvent(event);
              }else {
                  return super.sendKeyEvent(event);
              }
          }
      };
      try {
          return public_con ;
      }catch (Exception e){
          return super.onCreateInputConnection(outAttrs) ;
      }
  }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top