如何从 Jetpack Compose 中的键盘接收 GIF?

How can I receive GIF's from the keyboard in jetpack compose?

我正在尝试在 jetpack compose 中进行聊天,我希望能够在我的三星上使用标准 gif 键盘来发送 gif。

当我在普通 TextField 上单击 GIF 时,我目前收到一条消息“无法在此处输入此内容”

我发现了一个叫做 Commit Content API 的东西,它应该可以在旧的 EditText 中添加 GIF,所以我在 AndroidView 中尝试,现在我不再收到错误消息,但我也不知道 GIF 在哪里以及它是如何表示的。

AndroidView(factory = {
    val editText = @SuppressLint("AppCompatCustomView")
    object : EditText(it) {

        override fun setOnReceiveContentListener(
            mimeTypes: Array<out String>?,
            listener: OnReceiveContentListener?
        ) {
            super.setOnReceiveContentListener(mimeTypes, listener)
        }


        override fun onCreateInputConnection(editorInfo: EditorInfo): InputConnection {
            val ic: InputConnection = super.onCreateInputConnection(editorInfo)
            EditorInfoCompat.setContentMimeTypes(editorInfo, arrayOf("image/gif"))

            val callback =
                InputConnectionCompat.OnCommitContentListener { inputContentInfo, _, _ ->
                    try {
                        inputContentInfo.requestPermission()
                    } catch (e: Exception) {
                        return@OnCommitContentListener false
                    }
                    true  // return true if succeeded
                }
            return InputConnectionCompat.createWrapper(ic, editorInfo, callback)
        }
    }
    editText
}) {}
每次选择 GIF 时调用

callback。您可以从 inputContentInfo:

获取 URI
val callback =
    InputConnectionCompat.OnCommitContentListener { inputContentInfo, _, _ ->
        try {
            inputContentInfo.requestPermission()
        } catch (e: Exception) {
            return@OnCommitContentListener false
        }
        gifUri = inputContentInfo.contentUri
        true  // return true if succeeded
    }

完美,您应该将此 URI 中的文件复制到您自己的存储中并调用 inputContentInfo.releasePermission(),因为 contentUri 将在某个时候被释放。可以在 documentation.

中找到更多信息

您可以使用 Coil 显示此 URI 的内容,如 this answer 所示。注意需要添加依赖io.coil-kt:coil-gif:$coil_version

一个完整的工作示例:

var gifUri by remember { mutableStateOf<Uri?>(null) }
val context = LocalContext.current
Image(
    rememberImagePainter(
        gifUri,
        imageLoader = remember {
            ImageLoader(context).newBuilder()
                .componentRegistry {
                    if (SDK_INT >= 28) {
                        add(ImageDecoderDecoder(context))
                    } else {
                        add(GifDecoder())
                    }
                }.build()
        }
    ),
    contentDescription = null,
    modifier = Modifier.size(300.dp)
)

AndroidView(factory = { context ->
    val editText = @SuppressLint("AppCompatCustomView")
    object : EditText(context) {

        override fun setOnReceiveContentListener(
            mimeTypes: Array<out String>?,
            listener: OnReceiveContentListener?
        ) {
            super.setOnReceiveContentListener(mimeTypes, listener)
        }


        override fun onCreateInputConnection(editorInfo: EditorInfo): InputConnection {
            val ic: InputConnection = super.onCreateInputConnection(editorInfo)
            EditorInfoCompat.setContentMimeTypes(editorInfo, arrayOf("image/gif"))

            val callback =
                InputConnectionCompat.OnCommitContentListener { inputContentInfo, _, _ ->
                    try {
                        inputContentInfo.requestPermission()
                    } catch (e: Exception) {
                        return@OnCommitContentListener false
                    }
                    gifUri = inputContentInfo.contentUri
                    true  // return true if succeeded
                }
            return InputConnectionCompat.createWrapper(ic, editorInfo, callback)
        }
    }
    editText
}) {}