web-dev-qa-db-fra.com

Numéros de formatage en composant Textfield

J'essaie de créer un composant numérique réutilisable:

@Composable
fun NumberField(
  value: Number?,
  onNumberChange: (Number) -> Unit,
) {
  TextField(
    value = value?.toString() ?: "",
    onValueChange = {
      it.toDoubleOrNull()?.let { value ->
        if (value % 1.0 == 0.0) {
          onNumberChange(value.toInt())
        } else {
          onNumberChange(value)
        }
      }
    },
    singleLine = true,
    keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
  )
}

Pour être utilisé comme:

@Composable
fun NumberContent() {
  val number = remember { mutableStateOf<Number?>(null) }

  NumberField(value = number.value) {
    number.value = it
  }
}

J'aimerais que le nombre soit un intégrole ou double selon ce que l'utilisateur tape. Ce que j'ai ci-dessus fonctionne jusqu'à ce que vous essayiez d'entrer un nombre décimal, comme il semble "5.", n'utilise pas de double. Je veux permettre à l'utilisateur de taper 5. puis de remplir le repos. En tant que tel, je ne veux pas ajouter de zéro après décimal automatiquement car cela pourrait ne pas être le prochain nombre qu'ils veulent entrer. Est-ce le meilleur moyen d'y aller? Je sais que je peux simplement accepter n'importe quel texte, puis essayer de formater le texte qu'ils ont saisi ultérieurement en tant que Int ou double et leur permettent de le réparer, il suffit de penser qu'il serait agréable de tout replier dans la composition.

7

Voici une implémentation qui gère toutes les conditions énoncées tout en exposant également l'État aux parents.

@Composable
fun NumberField(
    value: Number?,
    onNumberChange: (Number?) -> Unit,
) {
    val number = remember { mutableStateOf(value) }
    val textValue = remember(value != number.value) {
        number.value = value
        mutableStateOf(value?.toDouble()?.let {
            if (it % 1.0 == 0.0) {
                it.toInt().toString()
            } else {
                it.toString()
            }
        } ?: "")
    }

    val numberRegex = remember { "[-]?[\\d]*[.]?[\\d]*".toRegex() }
    // for no negative numbers use "[\d]*[.]?[\d]*"

    TextField(
        value = textValue.value,
        onValueChange = {
            if (numberRegex.matches(it)) {
                textValue.value = it
                number.value = it.toDoubleOrNull()
                onNumberChange(number.value)
            }
        },
        singleLine = true,
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
    )
}

Un exemple d'utilisation est présenté ci-dessous.

@Composable
fun DemoUsage() {
    Column {
        val number = remember { mutableStateOf<Number?>(null) }
        
        NumberField(value = number.value) {
            number.value = it
        }

        Button(onClick = { number.value = number.value?.toDouble()?.plus(1) }) {
            Text("Increment")
        }
    }
}
0
Om Kumar