亲宝软件园·资讯

展开

Jetpack Compose列表 动画

大前端之旅 人气:0

创建一个列表消息卡片

到目前为止,我们只有一个消息的卡片,看上去有点单调,所以让我们来改善它,让它拥有多条信息。我们需要创建一个能够显示多条消息的函数。对于这种情况,我们可以使用 Compose 的 LazyColumn 和 LazyRow。这些 Composable 只渲染屏幕上可见的元素,所以它们的设计对于长列表来说很有效果。同时,它们避免了 RecyclerView 与 XML 布局的复杂性。

import androidx.compose.foundation.lazy.items
​
@Composable
fun Conversation(messages: List<Message>) {
    LazyColumn {
        items(messages) { message ->
            MessageCard(msg = message)
        }
    }
}
​
@Composable
fun PreviewMessageCard() {
    ComposestudyTheme {
        Conversation(messages = MsgData.messages)
    }
}

你可以在这里获取 MsgData 的代码

MsgData.kt

​
​
object MsgData {
    private const val author = "大前端之旅"
    val messages = listOf(
        Message(author, "我们开始更新啦"),
        Message(author, "秋刀鱼会过期吗?"),
        Message(author, "下周就是端午了"),
        Message(author, "男人最好的状态是,25岁的时候能带着30岁的成熟去经营爱情,30岁的时候还带着18岁的不怕,去勇敢爱\uD83D\uDCAA"),
        Message(author, "Android之旅"),
​
    )
}

在这个代码片段中,你可以看到 LazyColumn 有一个 items 子项。它接收一个 List 作为参数,它的 lambda 接收一个我们命名为 message 的参数(我们可以随便命名)。 而这个 lambda 将会调用每个 List 中里面提供的 item。

可交互的动画效果

我们的对话越来越有趣了,是时候玩玩动画了! 我们将会实现当点击一个卡片查看详细内容的时候,使内容的大小和背景颜色都有动画效果。为了存储这个本地 UI 状态,我们需要跟踪一条消息是否已经展开了。为了跟踪这种状态变化,我们必须使用 remember 和 mutableStateOf 函数。

Composable 函数可以通过使用 remember 将本地状态存储在内存中,并跟踪传递给 mutableStateOf 的值的变化。当值被更新时,使用该状态的 Composable 函数(及其子函数)将被自动重新绘制。我们把这称为重组(recomposition)。

通过使用 Compose 的状态 API,如 remember 和 mutableStateOf,任何对状态的改变都会自动更新 UI。

@Composable
fun MessageCard(msg: Message) {
​
    var isExpanded by remember { mutableStateOf(false) } // 创建一个能够检测卡片是否被展开的变量
​
    Surface(
        shape = MaterialTheme.shapes.medium,
        elevation = 5.dp,
        modifier = Modifier
            .padding(all = 8.dp)
            .clickable { // 添加一个新的 Modifier 扩展方法,可以让元素具有点击的效果
                isExpanded = !isExpanded // 编写点击的事件内容
            }
    ) {
        Row(
            modifier = Modifier.padding(all = 8.dp)
        ) {
            Image(
                painterResource(id = R.drawable.profile_picture),
                contentDescription = "profile picture",
                modifier = Modifier
                    .size(50.dp)
                    .clip(CircleShape)
                    .border(1.5.dp, MaterialTheme.colors.secondary, shape = CircleShape)
            )
            Spacer(Modifier.padding(horizontal = 8.dp))
            Column {
                Text(
                    text = msg.author,
                    color = MaterialTheme.colors.secondaryVariant,
                    style = MaterialTheme.typography.subtitle2
                )
                Spacer(Modifier.padding(vertical = 4.dp))
                Text(
                    text = msg.body,
                    style = MaterialTheme.typography.body2,
                    // 修改 maxLines 参数,在默认情况下,只显示一行文本内容
                    maxLines = if (isExpanded) Int.MAX_VALUE else 1,
                    // Composable 大小的动画效果
                    modifier = Modifier.animateContentSize()
                )
            }
        }
    }
}

现在我们已经能够完成每个卡片的检测了,让我们继续使用 isExpanded 来做点其他的事情吧!比如改变卡片的颜色

    // 创建一个能够根据 isExpanded 变量值而改变颜色的变量
    val surfaceColor by animateColorAsState(
        targetValue = if (isExpanded) Color(0xFFCCCCCC) else MaterialTheme.colors.surface
    )
​
    Surface(
        shape = MaterialTheme.shapes.medium,
        elevation = 5.dp,
        modifier = Modifier
            .padding(all = 8.dp)
            .clickable {
                isExpanded = !isExpanded
            },
        color = surfaceColor
    ) {
        ...
        ...
    }

加载全部内容

相关教程
猜你喜欢
用户评论