如何在 TextField 中 add/remove 个字符?

How to add/remove characters inside TextField?

我有一个 Room 数据库,其中 table 用于保存用户。每个用户都有一个 ID 和一个名称。我的目标是根据 ID 更改用户的名称。这是我尝试过的。

我有一个 UsersScreen,其中包含一个显示所有用户的 LazyColumn。它工作正常。每行由一个用户表示。在用户单击时,我通过传递用户 ID 向前导航到 UpdateUserNameScreen。在此屏幕中,我正在调用 getUser(id) 函数来 return 所需的用户。这是我的代码:

fun UpdateUserNameScreen(
    userId: Int,
    viewModel: UserViewModel = hiltViewModel()
) {
    var name by remember { mutableStateOf("") }

    Scaffold(
        topBar = {
            //TopBar content
        },
        content = {
            viewModel.getUser(userId) //Get the user.

            TextField(
                value = viewModel.userState.value.name, //Set user name.
                onValueChange = { name = it },
            )
            Button(
                onClick = {
                    val user = User(userId, name)
                    viewModel.updateUser(user)
                    navController.popBackStack()
                }
            ) {
                Text("Save")
            }
        }
    )
}

当我打开此屏幕时,我看到在 TextField 中添加了用户名,这很好。但是,当我尝试添加更改名称时,无法添加或删除任何字符。如何更改 TextField 中的用户名?

TextField 触发 onValueChange 之后,您应该修改传递给 value 的值。

如果你想编辑你的视图模型属性,你可以这样做,期望User是一个数据class:

onValueChange = { viewModel.userState.value = viewModel.userState.value.copy(name = it) },

通常你不想直接编辑视图模型状态,你可以像这样创建一个setter:

// view model
var userState by mutableStateOf(User(0, ""))
    private set

fun updateUserName(name: String) {
    userState = userState.copy(name = name)
    // e.g. add validation
}
// view
onValueChange = viewModel::updateUserName

另一种选择是您实际上想要编辑一个局部变量,该变量应该使用用户名进行初始化 - 这样您就可以使用新名称发出请求,并且仅在请求成功时更新用户值。

在这种情况下,您可以使用用户名初始化 name,并为 valuesetValue 使用 name

class VM: ViewModel() {
    var userState by mutableStateOf(User(0, ""))
        private set
}

@Composable
fun TestScreen() {
    val viewModel = viewModel<VM>()
    val (name, setName) = remember(viewModel.userState.name) { mutableStateOf(viewModel.userState.name) }
    TextField(
        value = name,
        onValueChange = setName
    )
}