Android compose测试数据双向绑定

之前测试过dataBinding绑定数据,再试下compose绑定数据。

Kotlin 复制代码
package com.example.testcompose1

import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TextField
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            todoJobList()
        }
    }
}

@Preview
@Composable
fun todoJobList() { // 显示待办事项
    val context = LocalContext.current

    // 使用 remember 和 mutableStateOf 保存输入框的文本
    var text by remember { mutableStateOf("") }
    // 使用 mutableStateListOf 保存待办项列表
    val todoItems = remember { mutableStateListOf<String>() }

    Column(modifier = Modifier.padding(16.dp)) {
        // 文本输入框
        TextField(
            value = text,
            onValueChange = { text = it }, // 反向绑定,视图变化--> 数据变化
            label = { Text("输入待办事项") },
            modifier = Modifier.fillMaxWidth()
        )
        // 添加按钮
        Button(
            onClick = {
                if (text.isNotBlank()) {
                    println("添加:$text")
                    Toast.makeText(context, "添加:$text", Toast.LENGTH_SHORT).show()
                    todoItems.add(text)  // 添加到列表
                    text = ""            // 清空输入. 测试正向绑定,数据状态变化--> 视图变化
                }
            },
            modifier = Modifier.padding(top = 8.dp)
        ) {
            Text("添加")
        }

        // 显示待办列表
        Spacer(modifier = Modifier.height(16.dp))
        Text("待办列表", style = MaterialTheme.typography.titleMedium)
        LazyColumn {
            items(items = todoItems) { item ->
                TodoItem(item = item)
            }
        }
    }
}

@Composable
fun TodoItem(item: String) {
    Text(
        text = item,
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 8.dp)
    )
}

运行:

可以随便输入点什么点击添加,会添加到下面的列表中:

ok. mutableStateOf能创建可观察状态的数据,值变化的时候重组刷新页面。remember能让状态重组时记住之前的值,不被重置。

每一条数据旁再添加个删除按钮。

修改下TodoItem函数,增加一个删除按钮,删除函数由onDelete参数传入:

Kotlin 复制代码
@Composable
fun TodoItem(item: String, onDelete: () -> Unit  // 添加删除回调,删除逻辑放在上层。即把回调传给里面的按钮。
 ) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 8.dp),
        horizontalArrangement = Arrangement.SpaceBetween // 横向布局子元素两端对齐,剩余空白空间平均分配到子元素之间
    ) {
        Text(text = item)
        IconButton(onClick = onDelete) {
            Icon(Icons.Default.Delete, contentDescription = "删除")
        }
    }
}

再修改下todoJoblist函数,将删除函数传给子组件:

修改完完整代码:

Kotlin 复制代码
package com.example.testcompose1

import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TextField
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            todoJobList()
        }
    }
}

@Preview
@Composable
fun todoJobList() {
    val context = LocalContext.current

    // 使用 remember 和 mutableStateOf 保存输入框的文本
    var text by remember { mutableStateOf("") }
    // 使用 mutableStateListOf 保存待办项列表
    val todoItems = remember { mutableStateListOf<String>() }

    Column(modifier = Modifier.padding(16.dp)) {
        // 文本输入框
        TextField(
            value = text,
            onValueChange = { text = it }, // 反向绑定,视图变化--> 数据变化
            label = { Text("输入待办事项") },
            modifier = Modifier.fillMaxWidth()
        )
        // 添加按钮
        Button(
            onClick = {
                if (text.isNotBlank()) {
                    println("添加:$text")
                    Toast.makeText(context, "添加:$text", Toast.LENGTH_SHORT).show()
                    todoItems.add(text)  // 添加到列表
                    text = ""            // 清空输入. 测试正向绑定,数据状态变化--> 视图变化
                }
            },
            modifier = Modifier.padding(top = 8.dp)
        ) {
            Text("添加")
        }

        // 显示待办列表
        Spacer(modifier = Modifier.height(16.dp))
        Text("待办列表", style = MaterialTheme.typography.titleMedium)
        LazyColumn {
            items(items = todoItems) { item ->
                TodoItem(item = item
                    , onDelete = { todoItems.remove(item) })  // 点击时从列表中删除
            }
        }
    }
}

@Composable
fun TodoItem(item: String, onDelete: () -> Unit  // 添加删除回调,删除逻辑放在上层。即把回调传给里面的按钮。
 ) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 8.dp),
        horizontalArrangement = Arrangement.SpaceBetween // 横向布局子元素两端对齐,剩余空白空间平均分配到子元素之间
    ) {
        Text(text = item)
        IconButton(onClick = onDelete) {
            Icon(Icons.Default.Delete, contentDescription = "删除")
        }
    }
}

测试下,添加几条数据:

删除一个:

ok. 状态管理没问题。

相关推荐
BoomHe21 小时前
Android AOSP13 原生 Launcher3 壁纸获取方式
android
Digitally1 天前
如何将联系人从 Android 转移到 Android
android
李小枫1 天前
webflux接收application/x-www-form-urlencoded参数
android·java·开发语言
爱丽_1 天前
MySQL `EXPLAIN`:看懂执行计划、判断索引是否生效与排错套路
android·数据库·mysql
NPE~1 天前
[App逆向]环境搭建下篇 — — 逆向源码+hook实战
android·javascript·python·教程·逆向·hook·逆向分析
yewq-cn1 天前
AOSP 下载
android
cch89181 天前
Laravel vs ThinkPHP:PHP框架终极对决
android·php·laravel
米码收割机1 天前
【Android】基于安卓app的汽车租赁管理系统(源码+部署方式+论文)[独一无二]
android·汽车
流星雨在线1 天前
安卓使用 Startup 管理三方 SDK 初始化
android·startup
jwn9991 天前
Laravel3.x:PHP框架的经典里程碑
android