androidandroid-softkeyboardandroid-input-methodandroid-viewgroup

Wrapping KeyboardView in ViewGroup: java.lang.IllegalStateException: The specified child already has a parent


I am using InputMethodService, Keyboard and KeyboardView (i know, it has been deprecated recently) in order to create a custom keyboard.

  override fun onCreateInputView(): View {
    view = layoutInflater.inflate(
        R.layout.keyboard_view_test,
        null
    )
    keyboardView =
        view.findViewById<KeyboardView>(R.id.keyboard)
    keyboard = Keyboard(this, R.xml.keyboard_layout)
    keyboardView.keyboard = keyboard
    keyboardView.isPreviewEnabled = false
    keyboardView.setOnKeyboardActionListener(this)
    return keyboardView

}

The keyboard works perfecly fine when using a KeyboardView in keyboard_view_test.xml as root element. When i start wrapping it in a LinearLayout or any other ViewGroup without changing anything else (see keyboard_view_test.xml) i get an IllegalStateException. I don't understand it, the stacktrace doesn't reference any of my code. How can i make it work?

keyboard_view_test.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorGboardBackground">

<android.inputmethodservice.KeyboardView
    android:id="@+id/keyboard"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"

    android:background="@color/colorGboardBackground"
    android:keyBackground="@drawable/key_background"
    android:keyPreviewLayout="@layout/key_preview"
    android:keyPreviewOffset="10dp"
    android:keyTextColor="@color/colorGboardKeyText"
    android:keyTextSize="22sp"
    android:labelTextSize="22sp"
    android:shadowRadius="0" />

The error seems to occur right after onCreateInputView() returns

Error stack:

 java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
    at android.view.ViewGroup.addViewInner(ViewGroup.java:5038)
    at android.view.ViewGroup.addView(ViewGroup.java:4869)
    at android.view.ViewGroup.addView(ViewGroup.java:4841)
    at android.inputmethodservice.InputMethodService.setInputView(InputMethodService.java:1596)
    at android.inputmethodservice.InputMethodService.updateInputViewShown(InputMethodService.java:1431)
    at android.inputmethodservice.InputMethodService.showWindowInner(InputMethodService.java:1835)
    at android.inputmethodservice.InputMethodService.showWindow(InputMethodService.java:1803)
    at android.inputmethodservice.InputMethodService$InputMethodImpl.showSoftInput(InputMethodService.java:570)
    at android.inputmethodservice.IInputMethodWrapper.executeMessage(IInputMethodWrapper.java:207)
    at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:37)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:201)
    at android.app.ActivityThread.main(ActivityThread.java:6810)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)

Solution

  • As @Ben P. pointed out, I obviously have to change return keyboardView to return view. I had overlooked it at first.