Android Lollipop soft keyboard doesn't accept keypresses with GL surface

谁都会走 提交于 2020-01-04 05:22:18

问题


In a current fullscreen opengl based project I work on, I have some GL based graphical elements, notably a text entry field. For the use to enter text when this element has the focus, I display the soft keyboard (which appears fine).

On android version before 5.0, the Google Keyboard was working fine, sending key events like for hardware keyboards. On android Lollipop, some other keyboards like Swiftkey or the free Hacker's keyboard are still working, but the Google Keyboard isn't anymore.

When pressing a key on the Google Keyboard on Lollipop, no visual feedback appears on the keyboard itself and my application receives the touch events as if the keyboard was not shown (but it is). The 'hardware' back key works fine though.

The view used in the app is a SurfaceView (and it's not a TextView). I've overridden onCheckIsTextEditor and I return a specific InputConnection from onCreateInputConnection where I've set the inputType to be TYPE_NULL. Note that onCreateInputConnection doesn't seem to be called.

This app is compiled with android level 15 compatibility.

Any idea what would prevent the keyboard to accept touch events? What should I do to debug the touch events flow?


回答1:


I finally found a workaround to my problem, even though I don't really understand exactly why it works. This solution is partially based on what Cocos2d-x does for input on Android.

I created an android EditText (actually a class than inherits EditText in which I overrode onKeyUp and onKeyDown, this is to track focus and the back key).

Instead of having the SurfaceView the sole element of the activity, I created a layout that has the fake edit text in the background (but not fullscreen), and the SurfaceView on top:

private FrameLayout setupView(View androidView)
{
  ViewGroup.LayoutParams framelayout_params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,                                                                                                                                                    ViewGroup.LayoutParams.MATCH_PARENT);
  frameLayout = new FrameLayout(this);
  getFrameLayout().setLayoutParams(framelayout_params);

  ViewGroup.LayoutParams edittext_layout_params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,                                                                                                                           ViewGroup.LayoutParams.WRAP_CONTENT);

  edittext = new FakeEditText(this);
  edittext.setLayoutParams(edittext_layout_params);

  // make sure this edit text is not fullscreen
  edittext.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_FLAG_NO_EXTRACT_UI);

  // ...add to FrameLayout
  frameLayout.addView(edittext);
  frameLayout.addView(androidView);
  return frameLayout;
}

I also added a TextWatcher linked to the fake edit text, this is mainly to capture the text entered by the user and send it back to the GL based edit text I have on the SurfaceView (in my case, when the afterTextChanged method is called, I transform the received characters to internal keydown/keyup events that are routed to my GL control).

When the virtual keyboard needs to be shown (for example when the GL text field has focus), I set the fake edit text content from the GL text field content, and attach this TextWatcher to the fake edit text, and attach the virtual keyboard to the android fake edit text.

// Control is the base class of my GL controls
private void uiShowVirtualKeyboard(Control control)
{
  if (fakeEdit.requestFocus()) {
    // textWrapper is our TextWatcher
    fakeEdit.removeTextChangedListener(textWrapper);
    fakeEdit.setText("");

    // get the text from the GL Text entry
    final String text = control.getTextContent();

    // and make sure it's in the android EditText at start
    fakeEdit.append(text);

    // listen to user changes
    fakeEdit.addTextChangedListener(textWrapper);

    // show the virtual keyboard
    InputMethodManager imm = (InputMethodManager) fAndroidActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.showSoftInput(fakeEdit, InputMethodManager.SHOW_FORCED);
  }
}



回答2:


I had exactly the same problem. Google keyboard did no show up correctly and passed touch input through it's buttons.

As it turned out Google keyboard was not happy with the default settings of EditorInfo class passed into onCreateInputConnection for a view. If you fill in at least imeOptions field and leave the rest to their default values it will work, even if you return null from the function.

In order to fix it i've added these lines to my SurfaceView subclass:

@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
    outAttrs.inputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE | InputType.TYPE_CLASS_TEXT;
    outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_FLAG_NO_FULLSCREEN;
    return super.onCreateInputConnection(outAttrs);
}


来源:https://stackoverflow.com/questions/27860497/android-lollipop-soft-keyboard-doesnt-accept-keypresses-with-gl-surface

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!