Trying to make a custom Keyboard using Jetpack Compose. Cannot figure out how call currentInputConnection or other methods from Composable.
@Composable
fun CustomKeyboard() {
var inputVal by remember { mutableStateOf("") }
Column(
modifier = Modifier
.fillMaxSize()
.padding(8.dp)
) {
Spacer(modifier = Modifier.height(50.dp))
Text("Last key pressed: $inputVal")
Row(modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically)
{
MyButton(mText = "A") { inputVal = it}
MyButton(mText = "B") { inputVal = it}
MyButton(mText = "C") { inputVal = it}
}
}
}
@Composable
private fun MyButton(
mText: String,
onPressed: (String) -> Unit
) {
OutlinedButton(
onClick = {
onPressed(mText)
},
modifier = Modifier.padding(4.dp)
) {
Text(text = mText, fontSize = 30.sp, color = Color.White)
}
}
And the InputMethodService class here...
class ComposeKeyboardView(context: Context) : AbstractComposeView(context) {
@Composable
override fun Content() {
CustomKeyboard()
}
}
class IMEService : InputMethodService(), LifecycleOwner, ViewModelStoreOwner,
SavedStateRegistryOwner {
override fun onCreateInputView(): View {
val view = ComposeKeyboardView(this)
window!!.window!!.decorView.let { decorView ->
ViewTreeLifecycleOwner.set(decorView, this)
ViewTreeViewModelStoreOwner.set(decorView, this)
ViewTreeSavedStateRegistryOwner.set(decorView, this)
}
view.let {
ViewTreeLifecycleOwner.set(it, this)
ViewTreeViewModelStoreOwner.set(it, this)
ViewTreeSavedStateRegistryOwner.set(it, this)
}
return view
}
fun doSomethingWith(mData: String) {
currentInputConnection?.commitText(mData, 1)
}
//Lifecylce Methods
private var lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(this)
override fun getLifecycle(): Lifecycle {
return lifecycleRegistry
}
private fun handleLifecycleEvent(event: Lifecycle.Event) =
lifecycleRegistry.handleLifecycleEvent(event)
override fun onCreate() {
super.onCreate()
savedStateRegistry.performRestore(null)
handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
}
override fun onDestroy() {
super.onDestroy()
handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
}
//ViewModelStore Methods
private val store = ViewModelStore()
override fun getViewModelStore(): ViewModelStore = store
//SaveStateRegestry Methods
private val savedStateRegistry = SavedStateRegistryController.create(this)
override fun getSavedStateRegistry(): SavedStateRegistry = savedStateRegistry.savedStateRegistry
}
If you just need to call a single function, i.e.
doSomethingWith(mData: String), or a few of them, then you can pass them into your composables and call them when you want to. This approach would be more loosely coupled and easier to@PreviewtheCustomKeyboardcomposable.If you plan to add many more functions to the
IMEServicethat you will have to also call, then you can just pass theIMEService(or some interface thatIMEServiceimplements) into your composables and then call its members normally. Using an interface over an actual class would make it possible to@PreviewtheCustomKeyboardcomposable.