You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Compose ModalBottomSheet内Emoji2表情选择器无法滚动的问题求助

问题:AndroidX EmojiPicker在Compose ModalBottomSheet中无法滚动或卡顿

使用AndroidX的emoji2-emojipicker,其XML结构如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/emoji_picker_header"
        android:layout_width="wrap_content"
        android:layout_height="@dimen/emoji_picker_header_height"
        android:paddingEnd="@dimen/emoji_picker_header_padding"
        android:paddingStart="@dimen/emoji_picker_header_padding" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/emoji_picker_body"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

在Compose中调用的代码:

AndroidView(
    factory = { context ->
        EmojiPickerView(context)
    },
    modifier = Modifier
        .fillMaxWidth()
        .height(300.dp)
)

在Scaffold、Column等普通布局中使用时滚动流畅,但放入ModalBottomSheet这类可滚动Composable后,表情选择器无法滚动。给AndroidView添加verticalScroll(rememberScrollState())修饰符后,虽能滚动但加载卡顿、表情标签功能失效——推测是该修饰符让内部RecyclerView认为高度无限,导致一次性渲染所有表情,无法懒加载。核心问题是RecyclerView嵌套可滚动Composable时,滚动事件传递异常。


解决方案

方案1:让EmojiPicker优先处理滚动事件

给ModalBottomSheet添加嵌套滚动互操作连接,让AndroidView的滚动事件优先被处理,避免被ModalBottomSheet拦截:

ModalBottomSheet(
    onDismissRequest = { /* 关闭逻辑 */ },
    sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true),
    modifier = Modifier.nestedScroll(rememberNestedScrollInteropConnection())
) {
    AndroidView(
        factory = { context -> EmojiPickerView(context) },
        modifier = Modifier.fillMaxWidth().height(300.dp)
    )
}

此方案适用于ModalBottomSheet不需要整体滚动的场景,保留EmojiPicker自身的懒加载和滚动流畅性。

方案2:禁用EmojiPicker内部RecyclerView的嵌套滚动

在创建EmojiPickerView时,手动关闭内部RecyclerView的嵌套滚动功能,避免滚动事件被外部Composable拦截:

AndroidView(
    factory = { context ->
        EmojiPickerView(context).apply {
            findViewById<RecyclerView>(R.id.emoji_picker_body)?.isNestedScrollingEnabled = false
            findViewById<RecyclerView>(R.id.emoji_picker_header)?.isNestedScrollingEnabled = false
        }
    },
    modifier = Modifier.fillMaxWidth().height(300.dp)
)

该方案可保留ModalBottomSheet的整体滚动,同时确保EmojiPicker内部RecyclerView保持懒加载,不会卡顿。

方案3:使用Compose原生EmojiPicker(推荐)

直接使用官方提供的Compose版表情选择器,完全适配Compose环境,无View嵌套滚动冲突:

// 依赖:implementation "androidx.emoji2:emoji2-emojipicker-compose:1.4.0"
EmojiPicker(
    onEmojiSelected = { emoji -> /* 处理选中逻辑 */ },
    modifier = Modifier.fillMaxWidth().height(300.dp)
)

原生Compose实现无需处理跨框架滚动问题,滚动流畅且功能完整。


内容的提问来源于stack exchange,提问作者Giuliopime

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 07:07:04