简体   繁体   English

从 Jetpack Compose 调用 InputMethodService 的方法

[英]Calling methods of InputMethodService from Jetpack Compose

Trying to make a custom Keyboard using Jetpack Compose.尝试使用 Jetpack Compose 制作自定义键盘。 Cannot figure out how call currentInputConnection or other methods from Composable.无法弄清楚如何从 Composable 调用currentInputConnection或其他方法。

@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...这里的 InputMethodService 类...

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, ie doSomethingWith(mData: String) , or a few of them, then you can pass them into your composables and call them when you want to.如果您只需要调用一个函数,即doSomethingWith(mData: String)或其中的几个,那么您可以将它们传递到您的可组合项中,并在需要时调用它们。 This approach would be more loosely coupled and easier to @Preview the CustomKeyboard composable.这种方法将更加松散耦合,并且更容易@Preview CustomKeyboard可组合。

@Composable
fun CustomKeyboard(onKeyPressed: (String) -> Unit) {
    //...
            MyButton(mText = "A") {
                inputVal = it
                onKeyPressed(it)
            }
            // ...
}

class ComposeKeyboardView(
    context: Context,
    private val onKeyPressed: (String) -> Unit,
) : AbstractComposeView(context) {

    @Composable
    override fun Content() {
        CustomKeyboard(onKeyPressed)
    }
}

class IMEService : InputMethodService() {
    override fun onCreateInputView(): View {
        val view = ComposeKeyboardView(this, onKeyPressed = this::doSomethingWith)
        // ...
        return view
    }

    private fun doSomethingWith(mData: String) {
        currentInputConnection?.commitText(mData, 1)
    }
}

If you plan to add many more functions to the IMEService that you will have to also call, then you can just pass the IMEService (or some interface that IMEService implements) into your composables and then call its members normally.如果您计划向IMEService添加更多必须调用的功能,那么您可以将IMEService (或IMEService实现的某些接口)传递到您的可组合项中,然后正常调用其成员。 Using an interface over an actual class would make it possible to @Preview the CustomKeyboard composable.在实际类上使用接口可以@Preview CustomKeyboard可组合。

@Composable
fun CustomKeyboard(imeService: IMEService) {
    //...
            MyButton(mText = "A") {
                inputVal = it
                imeService.doSomethingWith(it)
            }
            // ...
}

class ComposeKeyboardView(private val imeService: IMEService) : AbstractComposeView(imeService) {

    @Composable
    override fun Content() {
        CustomKeyboard(imeService)
    }
}

class IMEService : InputMethodService() {
    override fun onCreateInputView(): View {
        val view = ComposeKeyboardView(this)
        // ...
        return view
    }

    fun doSomethingWith(mData: String) {
        currentInputConnection?.commitText(mData, 1)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 InputMethodService 与 Jetpack Compose - ComposeView 导致:组合到不传播 ViewTreeLifecycleOwner 的视图中 - InputMethodService with Jetpack Compose - ComposeView causes: Composed into the View which doesn't propagate ViewTreeLifecycleOwner 在 Jetpack Compose UI 中设置内容视图的方法 - Methods to set content view in Jetpack Compose UI Jetpack compose 中未解决的修改器方法引用 - Unresolved reference with Modifier methods in Jetpack compose 从 Jetpack Compose 导航到 Fragment 以及从 Fragment 导航到 Jetpack Compose 屏幕 - Navigate from Jetpack Compose to Fragment and from Fragment to Jetpack Compose Screen Jetpack Compose:从协程中使用 lambda 调用函数时出现后端内部错误 - Jetpack Compose: Backend Internal error when calling function with lambda from Coroutine Jetpack Compose:Jetpack Compose 中的优雅文本高度 - Jetpack Compose: elegantTextHeight in Jetpack Compose 在jetpack compose中没有从rememberLauncherForActivityResult()获得结果 - Not Getting result from rememberLauncherForActivityResult() in jetpack compose 无法在 Jetpack Compose 中显示来自 onClick 的 AlertDialog - Not able to show AlertDialog from onClick in Jetpack Compose 从 Jetpack Compose 的 Composables 中访问传感器 - Access sensors from within Composables in Jetpack Compose 将 ImageVector 从 Jetpack Compose 转换为 BitmapDescriptor - Converting ImageVector from Jetpack Compose to BitmapDescriptor
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM