Android Lollipop 软键盘不接受 GL 表面的按键

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

在我当前从事的基于全屏 opengl 的项目中,我有一些基于 GL 的图形元素,尤其是文本输入字段。为了在这个元素有焦点时输入文本,我显示了软键盘(看起来很好)。

在 5.0 之前的 android 版本中,Google 键盘工作正常,可以像硬件键盘一样发送按键事件。在 android Lollipop 上,其他一些键盘(如 Swiftkey 或免费的 Hacker's 键盘)仍在使用,但 Google 键盘不再可用。

当按下 Lollipop 上 Google 键盘上的某个键时,键盘本身没有视觉反馈出现,我的应用程序接收到触摸事件,就好像键盘没有显示一样(但确实如此)。 'hardware' 后退键工作正常。

应用中使用的视图是 SurfaceView(不是 TextView)。我已经从 onCreateInputConnection 覆盖 onCheckIsTextEditor 和 return 一个特定的 InputConnection,我将 inputType 设置为 TYPE_NULL。 请注意 onCreateInputConnection 似乎没有被调用。

此应用编译时具有 android 级别 15 兼容性。

知道什么会阻止键盘接受触摸事件吗? 我应该如何调试触摸事件流程?

我终于找到了解决我的问题的方法,尽管我并不真正理解它为什么有效。此解决方案部分基于 Cocos2d-x 对 Android.

上的输入所做的操作

我创建了一个 android EditText(实际上是一个 class 而不是继承 EditText,我在其中覆盖了 onKeyUponKeyDown,这是跟踪焦点和返回键)。

我没有让 SurfaceView 成为 activity 的唯一元素,而是创建了一个在背景中包含假编辑文本(但不是全屏)的布局,并且 SurfaceView 在上面:

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;
}

我还添加了一个TextWatcher链接到假的编辑文本,这主要是为了捕获用户输入的文本并将其发送回我在[=16=上的基于GL的编辑文本](在我的例子中,当调用 afterTextChanged 方法时,我将接收到的字符转换为内部 keydown/keyup 事件,这些事件被路由到我的 GL 控件)。

当需要显示虚拟键盘时(例如当GL文本字段有焦点时),我从GL文本字段内容中设置假的编辑文本内容,并将这个TextWatcher附加到假的编辑文本,并将虚拟键盘附加到 android 假编辑文本。

// 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);
  }
}

我遇到了完全相同的问题。 Google 键盘没有正确显示并通过它的按钮传递触摸输入。

事实证明,Google 键盘不满意 EditorInfo class 传递给 onCreateInputConnection 的默认设置。如果您至少填写 imeOptions 字段并将其余部分保留为默认值,即使您从函数 return null

为了修复它,我将这些行添加到我的 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);
}