BasicTextField 的 onValueChange 在将值设置为 TextFieldValue(“”) 时不会触发。

huangapple go评论59阅读模式
英文:

onValueChange of BasicTextField is not triggered on setting value to TextFieldValue("") in Jetpack Compose

问题

I want to execute some code when the value of BasicTextField changes in Jetpack Compose.

Everything works fine in 2 conditions:

  • for any value change.
  • if all the textfield value is cleared using the device keyboard

But,
When I try to change the state value to empty text on click of a button, using this code:

textfieldstate.value = TextFieldValue("")

onValueChange is not triggered.

Although if I set it to any other value, onValueChange is triggered.

textfieldstate.value = TextFieldValue("FOO")

Code of Button/Icon click:

Icon(modifier = Modifier.clickable {
              textfieldstate.value = TextFieldValue("")
 }) {.....}

Is there a way to trigger onValueChange of BasicTextField when the value of the field is cleared from an external button click event?

英文:

I want to execute some code when the value of BasicTextfield changes in Jetpack Compose.

Everything works fine in 2 conditions:

  • for any value change.
  • if all the textfield value is cleared using the device keyboard

But,
When I try to change the state value to empty text on click of a button, using this code :

textfieldstate.value = TextFIeldValue("")

onValueChange is not triggered.

Although if I set it to any other value, onValueChange is triggered.

textfieldstate.value = TextFIeldValue("FOO")

Code of Button/Icon click:

Icon(modifier = Modifier.clickable {
              textfieldstate.value = TextFieldValue("")
 }) {.....}

Is there a way to trigger onValueChange of BasicTextField when value of the field is cleared from an external button click event??

答案1

得分: 1

以下是您要翻译的代码部分:

如果您想一次完成所有操作如更推荐的方式我会这样做

@Composable
fun AppContent(
  viewModel: MyViewModel
) {
  val state by viewModel.uiState.collectAsState()
  MyPanel(
    state = MyViewModel,
    onValueChange = viewModel::onValueChange,
    onClickButton = viewModel::onClickButton
  )
}

@Composable
fun MyPanel(
  state: MyTextFieldState,
  onValueChange: (String) -> Unit,
  onClickButton: () -> Unit
) {
   TextField(
    value = state.text,
    onValueChange = onValueChange
   )
   Button(
    onClick = { onClickButton() }
   ) {
    ...
   }
}

class MyViewModel: ViewModel() {
  private val _uiState = MutableStateFlow(MyUiState())
  val uiState = _uiState.asStateFlow()

  fun onValueChange(str: String) {
    _uiState.value = _uiState.value.copy(text = str)
  }

  fun onClickButton() {
    _uiState.value = _uiState.value.copy(text = "")
  }
}

data class MyUiState(
  val text: String = ""
)

代码上述主要提升了TextField的状态,处理了viewModel中的所有事务,并使用一个数据类封装了UI状态的一层。如果有其他要求,您也可以添加不同的参数,例如,如果TextField中有错误,可以这样写:

data class MyUiState(
  val text: String = "",
  val isTextError: Boolean = false
)
英文:

If you want to do it all at once as is more recommended, I would do this:

@Composable
fun AppContent(
  viewModel: MyViewModel
) {
  val state by viewModel.uiState.collectAsState()
  MyPanel(
    state = MyViewModel,
    onValueChange = viewModel::onValueChange,
    onClickButton = viewModel::onClickButton
  )
}

@Composable
fun MyPanel(
  state: MyTextFieldState,
  onValueChange: (String) -> Unit,
  onClickButton: () -> Unit
) {
   TextField(
    value = state.text,
    onValueChange = onValueChange
   )
   Button(
    onClick = { onClickButton() }
   ) {
    ...
   }
}

class MyViewModel: ViewModel() {
  private val _uiState = MutableStateFlow(MyUiState())
  val uiState = _uiState.asStateFlow()

  fun onValueChange(str: String) {
    _uiState.value = _uiState.value.copy(text = str)
  }

  fun onClickButton() {
    _uiState.value = _uiState.value.copy(text = "")
  }
}

data class MyUiState(
  val text: String = ""
)

The code above mainly elevates the state of the TextField, processes all things in the viewModel, and wraps a layer of UI state with a data class. If there are other requirements, you can also add different parameters, for example, if there is an error in the TextField, it can be written as:

data class MyUiState(
  val text: String = "",
  val isTextError: Boolean = false
)

答案2

得分: 1

The onValueChange回调用于通知用户输入的文本的最新状态非常有用。
如果您希望在(textFieldValue)的状态更改时触发某些操作,可以使用类似LaunchedEffect的副作用。

类似这样:

var textFieldValue by remember() {
    mutableStateOf(TextFieldValue("test"))
}

LaunchedEffect(textFieldValue) {
    // 进行某些操作
}

BasicTextField(
    value = textFieldValue,
    onValueChange = {
        textFieldValue = it
    }
)

OutlinedButton(
    onClick = { textFieldValue = textFieldValue.copy("") }
) {
    Text(text = "Button")
}
英文:

The onValueChange callback is useful to be informed about the latest state of the text input by users.
If you want to trigger some action when the state of (textFieldValue) changes, you can use a side effect like LaunchedEffect.

Something like:

var textFieldValue by remember() {
    mutableStateOf(TextFieldValue("test" ))
}

LaunchedEffect(textFieldValue) {
    //doSomething()
}

BasicTextField(
    value = textFieldValue,
    onValueChange = {
        textFieldValue = it
    }
  )

OutlinedButton(
    onClick = { textFieldValue = textFieldValue.copy("") }
) {
    Text(text = "Button")
}

huangapple
  • 本文由 发表于 2023年2月6日 20:39:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75361430.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定