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

Jetpack Compose:如何通过代码触发AnimatedVisibility进入动画?

问题:如何在ContentList组件外部触发Empty组件的AnimatedVisibility进入动画?

用户代码如下:

@Composable
fun ContentList() {
    if (list.size > 0) {
        Box() {
            Column {
                LazyColumn {
                    items()
                    }
                }
            }
        }
    } else {
        Emplty()
    }
}

@Composable
fun Emplty() {
    var visible by remember { mutableStateOf(false) }
    LaunchedEffect(Unit) {
        visible = true
    }
    Box() {
        AnimatedVisibility(
            visible = visible,
            enter = scaleIn() + expandVertically(expandFrom = Alignment.Top),
        ) {
            Image()
        }
    }
}

需求:当list.size=0时,能触发Empty组件中AnimatedVisibility的进入动画,且支持在ContentList外部通过代码控制触发。


解决方案

核心思路是将动画触发逻辑与列表状态绑定,通过参数传递的方式把外部的列表状态传入Empty组件,让动画触发时机跟随列表变化,而非仅依赖Empty组件的首次渲染。

步骤1:改造Empty组件,接收外部触发条件

让Empty组件的可见性状态依赖外部传入的列表空状态,每当列表从非空变为空时,重新触发动画:

@Composable
fun Empty(listEmpty: Boolean) {
    var visible by remember { mutableStateOf(false) }

    // 依赖listEmpty参数,列表状态变化时重新执行
    LaunchedEffect(listEmpty) {
        if (listEmpty) {
            // 先重置状态,确保重复触发时动画能正常执行
            visible = false
            awaitFrame() // 等待下一帧确保状态更新生效
            visible = true
        } else {
            visible = false
        }
    }

    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        AnimatedVisibility(
            visible = visible,
            enter = scaleIn() + expandVertically(expandFrom = Alignment.Top),
            // 可选:添加退出动画,让列表从空变有的过渡更自然
            exit = fadeOut() + shrinkVertically()
        ) {
            Image(
                painter = painterResource(id = R.drawable.your_empty_icon), // 替换为你的资源
                contentDescription = "Empty list",
                modifier = Modifier.size(120.dp)
            )
        }
    }
}

步骤2:修改ContentList组件,传递触发参数

在ContentList中,将列表是否为空的状态传递给Empty组件:

@Composable
fun ContentList(list: List<Any>) {
    if (list.isNotEmpty()) {
        LazyColumn(modifier = Modifier.fillMaxSize()) {
            items(list) { item ->
                // 你的列表项内容,示例:
                Text(text = item.toString(), modifier = Modifier.padding(16.dp))
            }
        }
    } else {
        // 传递列表空状态作为动画触发条件
        Empty(listEmpty = true)
    }
}

步骤3:外部控制列表状态触发动画

在ContentList的父组件中,只需修改list的状态,当list从非空变为空时,Empty组件会自动触发进入动画:

@Composable
fun ParentScreen() {
    var list by remember { mutableStateOf(listOf("Item 1", "Item 2")) }

    Column(modifier = Modifier.fillMaxSize()) {
        Button(onClick = { list = emptyList() }) {
            Text("清空列表")
        }
        ContentList(list = list)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:43:31