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

Jetpack Compose中监听Lazy Column内青色项的可见进度

监听LazyColumn项的可见进度并实现文本移除动画

完全可以实现这个需求,核心是借助LazyListState提供的布局信息,实时计算青色背景项的可见高度占总高度的比例,再用这个比例控制文本的动画效果。

实现步骤

  • 计算可见比例:通过LazyListState.layoutInfo获取目标项的布局参数,对比它与LazyColumn视口的位置关系,算出可见高度占自身总高度的比例(范围0-1)。
  • 实时更新进度:用LaunchedEffect监听滚动状态变化,每次滚动时重新计算可见比例并更新状态。
  • 绑定动画效果:将比例值应用到文本的透明度、偏移量等属性,实现滚动时的移除动画。

完整代码示例

val scaffoldState = rememberScaffoldState()
val lazyListState = rememberLazyListState()
// 保存可见进度,1代表完全可见,0代表完全不可见
val visibleProgress by remember { mutableStateOf(1f) }
// 给目标项设置唯一key,方便定位
val targetItemKey = "profile-header"

LaunchedEffect(lazyListState) {
    snapshotFlow { lazyListState.layoutInfo }
        .collect { layoutInfo ->
            // 找到目标项的布局信息
            val targetItem = layoutInfo.visibleItemsInfo.find { it.key == targetItemKey }
            targetItem?.let { item ->
                val itemTotalHeight = item.size
                val viewportHeight = layoutInfo.viewportEndOffset - layoutInfo.viewportStartOffset

                // 计算可见部分高度
                val hiddenTop = maxOf(0, layoutInfo.viewportStartOffset - item.offset)
                val hiddenBottom = maxOf(0, item.offset + itemTotalHeight - layoutInfo.viewportEndOffset)
                val visibleHeight = itemTotalHeight - hiddenTop - hiddenBottom

                // 更新进度,确保值在0-1之间
                visibleProgress = (visibleHeight.toFloat() / itemTotalHeight).coerceIn(0f, 1f)
            } ?: run {
                // 目标项完全不可见时进度设为0
                visibleProgress = 0f
            }
        }
}

Scaffold(
    scaffoldState = scaffoldState,
    topBar = {
        TopAppBar(
            title = {
                Text(fontSize = 30.sp, text = "Account", color = Color.White)
            },
            backgroundColor = Color.Black
        )
    },
    content = {
        LazyColumn(state = lazyListState) {
            item(key = targetItemKey) {
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .wrapContentHeight()
                        .background(color = Color.Cyan)
                ) {
                    Text(
                        text = "First Last",
                        fontSize = 20.sp,
                        color = Color.White,
                        modifier = Modifier
                            .padding(20.dp)
                            // 用进度驱动动画:透明度从1到0,同时向左偏移
                            .alpha(visibleProgress)
                            .offset(x = (1 - visibleProgress) * (-30).dp)
                    )
                }
            }

            items(list) {
                Row(
                    Modifier
                        .fillMaxWidth()
                        .wrapContentHeight()
                        .padding(start = 20.dp, top = 10.dp, bottom = 10.dp)
                ) {
                    Text(it)
                }
            }
        }
    }
)

关键说明

  • 目标项定位:给青色项设置唯一key,能在滚动时快速从可见项列表中找到它。
  • 可见高度计算:通过对比项的偏移量与视口的起止偏移,算出实际可见高度,再除以总高度得到比例。
  • 动画自定义:示例用了透明度和水平偏移动画,你也可以根据需求改成缩放、淡出等其他效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 09:54:18