使用 Jetpack Compose 实现动态展开效果:管理 Android 应用中的 State

在这里插入图片描述

本文将学习如何在 Android 应用中使用 Jetpack Compose 管理 State

在前面两篇文章里我们已经创建了一个包含列表名称和按钮的简单布局。在每个列表项中添加按钮后,我们会进一步添加点击交互。

当用户点击按钮时,列表项会展开(expanded),同时按钮的文本将从“See More”变为“See Less”。

在此过程中,我们需要两个变量:extraPaddingexpandedextraPadding 用于控制列表项的宽度,expanded 则用于标识列表项的状态,即是否展开。

@Composable
fun Greeting(name: String) {
    var expanded = false
    val extraPadding = if (expanded) 48.dp else 8.dp

    Surface(
        color = MaterialTheme.colorScheme.primary,
        modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)
    ) {
        Row(
            modifier = Modifier.padding(24.dp)
        ) {
            Column(
                modifier = Modifier
                    .weight(1f)
                    .padding(bottom = extraPadding)
            ) {
                Text(text = "Hello, ")
                Text(text = name)
            }
            ElevatedButton(
                onClick = { expanded = !expanded }
            ) {
                Text(text = if (expanded) "Show Less" else "Show More")
            }
        }
    }
}

此外,还需更改 MyList() 函数的调用:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeAppTheme {
                MyList(names)
            }
        }
    }
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    ComposeAppTheme {
        MyList(names)
    }
}

运行应用,注意到当点击按钮时,UI 没有任何变化。原因是 State 没有被 Compose 读取,因为 expanded 变量是普通的布尔值。

管理 State

为了让 Compose 能够检测 expanded 的变化,我们需要使用 mutableStateOf() 来定义 expanded 变量。

var expanded = mutableStateOf(false)

还需要为 Greeting() Composable 添加注解:

@SuppressLint("UnrememberedMutableState")
@Composable
fun Greeting(name: String) {
    // 代码暂时没有变化
}

并且修改代码中的如下部分:

val extraPadding = if (expanded.value) 48.dp else 8.dp

同样修改按钮点击操作中的 expanded 变量:

ElevatedButton(
  onClick = { expanded.value = !expanded.value }
) {
    Text(text = if (expanded.value) "Show Less" else "Show More")
}

在这里插入图片描述

再次运行应用,尽管点击按钮仍未触发 UI 变化,但 expandedState 已被 Compose 读取。

Recomposition(重构)

Recomposition 是指当某个 State 发生变化时,Compose 会重新调用 Composable 函数来触发 UI 更新。

在上面的代码中,虽然 State 已经被读取并发生了变化,但 expanded 的值并未保存在内存中,因此每次重构后,它又恢复为 false
在这里插入图片描述

为了解决这个问题,我们可以使用 rememberexpanded 的值保存在内存中:

var expanded = remember { mutableStateOf(false) }

去掉 SuppressLint 注解,代码如下:

@Composable
fun Greeting(name: String) {
    // 代码暂时没有变化
}

再次运行应用,expanded 的值现在已经存储在内存中,因此 UI 能够根据状态变化正常更新。

使用 Kotlin 委托属性简化代码

为了减少样板代码(boilerplate)并让代码更加简洁,我们可以使用 Kotlin 的委托属性(delegated properties):

var expanded by remember { mutableStateOf(false) }

最终的 Greeting() Composable 函数代码如下:

@Composable
fun Greeting(name: String) {
    var expanded by remember { mutableStateOf(false) }
    val extraPadding = if (expanded) 48.dp else 8.dp

    Surface(
        color = MaterialTheme.colorScheme.primary,
        modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)
    ) {
        Row(
            modifier = Modifier.padding(24.dp)
        ) {
            Column(
                modifier = Modifier
                    .weight(1f)
                    .padding(bottom = extraPadding)
            ) {
                Text(text = "Hello, ")
                Text(text = name)
            }
            ElevatedButton(
                onClick = { expanded = !expanded }
            ) {
                Text(text = if (expanded) "Show Less" else "Show More")
            }
        }
    }
}

至此,应用的 State 管理和 UI 响应已经实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值