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

Jetpack Compose中LazyColumn滚动时剪切复制粘贴弹窗错位问题解决

Jetpack Compose LazyColumn滚动时系统剪切/复制弹窗错位问题解决

问题描述

使用Jetpack Compose开发Android应用时,LazyColumn滚动过程中,系统自带的剪切/复制/粘贴弹窗会固定在原地,与滚动的UI元素出现错位。需要实现两种效果之一:要么弹窗跟随滚动内容移动,要么滚动时自动关闭弹窗。


解决方案

方案1:滚动时自动关闭系统弹窗

通过监听LazyListState的滚动状态,在滚动开始时关闭系统文本选择弹窗,这是实现成本最低的方案,符合多数场景需求。

修改后的代码如下:

@Composable
private fun ResultUI(modifier: Modifier,
                     results: List<DictionaryResult>,
                     onDefinitionTap: (String) -> Unit,
                     onExampleTap: (String) -> Unit) {
    val lazyListState = rememberLazyListState()
    val context = LocalContext.current
    val view = LocalView.current

    // 监听滚动状态,滚动触发时关闭系统文本弹窗并清除焦点
    LaunchedEffect(lazyListState.isScrollInProgress) {
        if (lazyListState.isScrollInProgress) {
            val inputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
            inputMethodManager.hideSoftInputFromWindow(view.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
            view.clearFocus()
        }
    }

    LazyColumn(modifier = modifier.padding(top = 8.dp), state = lazyListState){
        item {
            TextField(
                value = "",
                onValueChange =  {})
        }
        items(results) {
            it.meanings?.forEach { m ->
                MeaningUi(meaning = m, onDefinitionTap, onExampleTap)
            }
        }
    }
}

方案2:自定义弹窗实现跟随滚动

系统默认的文本选择弹窗基于全局Window绘制,无法直接跟随Compose滚动布局移动。如果需要弹窗跟随滚动内容,需自定义文本选择逻辑与上下文菜单:

  1. 自定义可选择文本组件,替代系统默认选择逻辑:
@Composable
private fun CustomSelectableText(text: String, onCopy: () -> Unit) {
    SelectionContainer {
        Text(text = text)
    }

    val selectionStatus = LocalTextSelectionStatus.current
    if (selectionStatus.hasSelection) {
        // 获取选中区域的屏幕坐标,计算弹窗位置
        val bounds = remember(selectionStatus.selectionBounds) {
            selectionStatus.selectionBounds
        }
        // 自定义跟随弹窗
        Box(
            modifier = Modifier
                .offset {
                    IntOffset(
                        x = bounds.left,
                        y = bounds.top - 60.dp.roundToPx()
                    )
                }
                .background(Color.White, RoundedCornerShape(4.dp))
                .elevation(4.dp)
                .padding(horizontal = 8.dp, vertical = 4.dp)
        ) {
            TextButton(onClick = {
                onCopy()
                // 关闭选择状态
                selectionStatus.clearSelection()
            }) {
                Text("复制")
            }
        }
    }
}
  1. 在MeaningUi中替换原文本组件为上述自定义组件,即可实现弹窗跟随滚动内容移动的效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 00:11:12