问题
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