Regex для TextField не работает должным образом в Котлине?

Мне нужны определенные ограничения в моем проекте, особенно в регулярном выражении, чтобы ограничить ввод пользователя и отформатировать его соответствующим образом. Эти правила предназначены для реализации в компоненте TextField моего проекта Jetpack Compose.

Правила:

  • Ноль и точка не могут быть в начале.
  • Точка может быть только одна.
  • После точки могут быть только две цифры, а перед точкой могут быть только четыре цифры.
  • Если пользователь не вводит точку, он может ввести только четыре цифры. Если они введут точку, они могут добавить после нее две цифры.

Примеры: (Эти примеры приведены только в справочных целях.)

  • 8956.32 -> Действителен
  • 45 -> Действителен
  • 562.2 -> Действителен
  • 0655 -> Неверно
  • 0356.00 -> Недействительно
  • .003 -> Неверно

Я попробовал код Belwo, но он не работает должным образом.

var text by remember { mutableStateOf("") }
val regex = remember { Regex("^(?!0|\\.)(?!.*\\.\\.)\\d{1,4}(\\.\\d{1,2})?$") }

TextField(
                label = R.string.label_days,
                value = text,
                keyboardOptions = KeyboardOptions(
                    keyboardType = KeyboardType.Number
                ),
                onValueChange = { days ->
                    if (days.isEmpty() || regex.matches(days)){
                     text = days
                    }
                })

Как следует обрабатывать конечную точку?

Leviathan 26.03.2024 10:46

Если вы не разрешите конечную точку, ее будет сложно ввести, даже если пользователь впоследствии намеревается добавить дополнительные цифры. Это у тебя проблема?

Leviathan 26.03.2024 11:19

Хорошо, разрешите конечную точку. Вы всегда можете удалить его впоследствии при обработке значения. Однако это необходимо разрешить в TextField. Чтобы разрешить точку, используйте это регулярное выражение "^[1-9]\\d{0,3}(\\.\\d{0,2})?$"

Leviathan 26.03.2024 11:36

@Leviathan Пробовал это, но после применения этого даже не набрал ни одного текста в текстовом поле.

CODAR747 26.03.2024 11:39

Вам удалось избежать всех трех обратных косых черт?

Leviathan 26.03.2024 11:47

@Leviathan Да, я сделал это

CODAR747 26.03.2024 11:57

Что ж, ваш точный код с заменой регулярного выражения тем, которое я предоставил, у меня работает отлично, я не могу воспроизвести описанную вами проблему.

Leviathan 26.03.2024 12:04
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
76
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ниже код будет работать для вашего требования

    var text by remember { mutableStateOf("") }
    val regex = remember { Regex("^(?!0)(?!.*\\.\\..*|\\.$)\\d{0,4}(\\.\\d{0,2})?\$") }
    TextField(
        label = {
            Text(text = "Days")
        },
        value = text,
        keyboardOptions = KeyboardOptions(
            keyboardType = KeyboardType.Number
        ),
        onValueChange = { days ->
            if (days.isEmpty() || days.matches(regex)) {
                text = days
            }
        }
    )

Привет, как создать регулярное выражение, где я могу научиться? Также можете ли вы предоставить другое регулярное выражение, где десятичное число не переписывается, требуется только 4-значное число, начинающееся не с нуля

CODAR747 28.03.2024 09:09

Здесь у вас есть 2 варианта:

  • Разрешить только допустимый ввод. В этом случае вам также необходимо разрешить и обработать конечную точку. Также лучше использовать вариант TextFieldValueTextField, чтобы предотвратить перемещение курсора при недопустимом вводе.
  • Разрешить любой ввод, но указать, когда ввод недействителен, и принимать только в том случае, если он верен. В этом случае вам не нужно допускать конечную точку.

С шаблоном регулярного выражения @Leviathan это будет выглядеть так:

Опция 1:

val regex = remember { Regex("^[1-9]\\d{0,3}(\\.\\d{0,2})?$") }
var text by rememberSaveable(stateSaver = TextFieldValue.Saver) {
    mutableStateOf(TextFieldValue(""))
}
Row {
    TextField(
//        label = R.string.label_days,
        label = { Text("Days") },
        value = text,
        keyboardOptions = KeyboardOptions(
            keyboardType = KeyboardType.Number
        ),
        onValueChange = { days: TextFieldValue ->
            if (days.text.isEmpty() || regex.matches(days.text)) {
                text = days
            }
        }
    )
    Button(
        onClick = {},
    ) {
        Text("Always OK")
    }
}

Вариант 2:

val regex = remember { Regex("^[1-9]\\d{0,3}(\\.\\d{1,2})?$") }
var text by remember { mutableStateOf("") }
var isValid by remember { mutableStateOf(true) }

Row {
    TextField(
//        label = R.string.label_days,
        label = { Text("Days") },
        value = text,
        keyboardOptions = KeyboardOptions(
            keyboardType = KeyboardType.Number
        ),
        supportingText = {
            if (!isValid) {
                Text("Invalid input")
            }
        },
        isError = !isValid,
        onValueChange = { days: String ->
            isValid = (days.isEmpty() || regex.matches(days))
            text = days
        }
    )
    Button(
        onClick = {},
        enabled = isValid,
    ) {
        Text("OK")
    }
}

Действительно оцените свои усилия здесь. Ваш ответ работает для меня. Но я хочу, чтобы все было просто, и ответ, предоставленный РавиШармой, сработал. Так что просто любопытно узнать, что-то не так с ответом РавиШармы, потому что с его ответом я добился того же поведения, что и ваш вопрос.

CODAR747 26.03.2024 13:43

Ничего особенного: использование TextFieldValue предотвратит перемещение курсора, если регулярное выражение не соответствует. В версии String попробуйте ввести полное число с точкой, например «1234,56», затем поместите курсор в начало и введите что-нибудь. Курсор будет перемещаться без изменения текста. @ CODAR747

Jan Itor 26.03.2024 13:57

Другие вопросы по теме