Настроить текстовые поля

TextField позволяет пользователям вводить и изменять текст. Существует два типа текстовых полей, которые вы можете использовать: текстовые поля на основе состояния и текстовые поля на основе значения . Выберите тип, для которого вы хотите отобразить содержимое:

Мы рекомендуем использовать текстовые поля на основе состояния, поскольку они обеспечивают более полный и надежный подход к управлению состоянием TextField . В следующей таблице описываются различия между этими типами текстовых полей и указаны основные преимущества текстовых полей на основе состояния:

Особенность

Текстовые поля на основе значений

Текстовые поля, зависящие от состояния

Государственное пособие

Государственное управление

Обновляет состояние текстового поля с помощью обратного вызова onValueChange . Вы несете ответственность за обновление value в своем собственном состоянии на основе изменений, сообщаемых onValueChange .

Явно использует объект TextFieldState для управления состоянием ввода текста (значение, выбор, композиция). Это состояние можно запомнить и поделиться.

  • Обратный вызов onValueChange был удален, что не позволяет вам вводить асинхронное поведение.
  • Государство переживает перестройку, конфигурацию и смерть процесса.

Визуальная трансформация

Использует VisualTransformation для изменения того, как выглядит отображаемый текст. Обычно это обрабатывает как входное, так и выходное форматирование за один шаг.

Использует InputTransformation для изменения ввода пользователя до его фиксации в состоянии и OutputTransformation для форматирования содержимого текстового поля без изменения базовых данных состояния.

  • Вам больше не нужно указывать смещение между исходным необработанным текстом и преобразованным текстом с помощью OutputTransformation .

Лимиты линии

Принимает singleLine: Boolean, maxLines: Int и minLines: Int для управления количеством строк.

Использует lineLimits: TextFieldLineLimits для настройки минимального и максимального количества строк, которые может занимать текстовое поле.

  • Устраняет неоднозначность при настройке ограничений строк путем предоставления параметра lineLimits типа TextFieldLineLimits .

Защищенное текстовое поле

Н/Д

SecureTextField — это компонуемый объект, созданный на основе текстовых полей с учетом состояния для записи поля пароля.

  • Позволяет оптимизировать безопасность изнутри и поставляется с предопределенным пользовательским интерфейсом с textObfuscationMode .

На этой странице описывается, как реализовать TextField , задать стиль ввода TextField и настроить другие параметры TextField , такие как параметры клавиатуры и визуальное преобразование пользовательского ввода.

Выберите реализацию TextField

Существует два уровня реализации TextField :

  1. TextField — это реализация Material Design. Мы рекомендуем вам выбрать эту реализацию, поскольку она соответствует принципам Material Design :
  2. BasicTextField позволяет пользователям редактировать текст с помощью аппаратной или программной клавиатуры, но не предоставляет никаких дополнительных элементов, таких как подсказки или заполнители.

TextField(
    state = rememberTextFieldState(initialText = "Hello"),
    label = { Text("Label") }
)

Редактируемое текстовое поле, содержащее слово

OutlinedTextField(
    state = rememberTextFieldState(),
    label = { Text("Label") }
)

Редактируемое текстовое поле с фиолетовой рамкой и меткой.

Стиль TextField

TextField и BasicTextField имеют много общих параметров для настройки. Полный список для TextField доступен в исходном коде TextField . Это неполный список некоторых полезных параметров:

  • textStyle
  • lineLimits

TextField(
    state = rememberTextFieldState("Hello\nWorld\nInvisible"),
    lineLimits = TextFieldLineLimits.MultiLine(maxHeightInLines = 2),
    placeholder = { Text("") },
    textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold),
    label = { Text("Enter text") },
    modifier = Modifier.padding(20.dp)
)

Многострочное текстовое поле с двумя редактируемыми строками и меткой

Мы рекомендуем TextField вместо BasicTextField , когда ваш дизайн требует Material TextField или OutlinedTextField . Однако BasicTextField следует использовать при создании дизайнов, которым не нужны украшения из спецификации Material.

Ввод стиля с помощью API-интерфейса Brush

Вы можете использовать API Brush для более продвинутого стиля в вашем TextField . В следующем разделе описывается, как можно использовать Brush для добавления цветного градиента к вводу TextField .

Дополнительную информацию об использовании API-интерфейса Brush для стилизации текста см. в разделе Включение расширенного стиля с помощью API-интерфейса Brush .

Реализуйте цветные градиенты с помощью TextStyle

Чтобы реализовать цветной градиент при вводе текста в TextField , установите кисть по вашему выбору в качестве TextStyle для вашего TextField . В этом примере мы используем встроенную кисть с linearGradient для просмотра эффекта радужного градиента при вводе текста в TextField .

val brush = remember {
    Brush.linearGradient(
        colors = listOf(Color.Red, Color.Yellow, Color.Green, Color.Blue, Color.Magenta)
    )
}
TextField(
    state = rememberTextFieldState(), textStyle = TextStyle(brush = brush)
)

Использование buildAnnotatedString и SpanStyle, а также linearGradient, для настройки только фрагмента текста.
Рисунок 1. Эффект радужного градиента для содержимого TextField .

Управление состоянием текстового поля

TextField использует выделенный класс-держатель состояния, называемый TextFieldState , для своего содержимого и текущего выбора. TextFieldState разработан для подъема в любом месте вашей архитектуры. TextFieldState предоставляет 2 основных свойства:

  • initialText : Содержимое TextField .
  • initialSelection : Указывает, где в данный момент находится курсор или выделение.

Что отличает TextFieldState от других подходов, таких как обратный вызов onValueChange , так это то, что TextFieldState полностью инкапсулирует весь поток ввода. Это включает использование правильных структур данных поддержки, встраивание фильтров и форматировщиков, а также синхронизацию всех правок, поступающих из разных источников.

Вы можете использовать TextFieldState() для подъема состояния в TextField . Для этого мы рекомендуем использовать функцию rememberTextFieldState() . rememberTextFieldState() создает экземпляр TextFieldState в вашем компонуемом объекте, обеспечивает запоминание объекта состояния и предоставляет встроенную функциональность сохранения и восстановления:

val usernameState = rememberTextFieldState()
TextField(
    state = usernameState,
    lineLimits = TextFieldLineLimits.SingleLine,
    placeholder = { Text("Enter Username") }
)

rememberTextFieldState может иметь пустой параметр или начальное значение, переданное для представления значения текста при инициализации. Если при последующей перекомпозиции передается другое значение, значение состояния не обновляется. Чтобы обновить состояние после его инициализации, вызовите методы редактирования для TextFieldState .

TextField(
    state = rememberTextFieldState(initialText = "Username"),
    lineLimits = TextFieldLineLimits.SingleLine,
)

Текстовое поле с текстом «Имя пользователя», отображаемым внутри текстового поля.
Рисунок 2. TextField с «Именем пользователя» в качестве начального текста.

Изменение текста с помощью TextFieldBuffer

TextFieldBuffer служит редактируемым текстовым контейнером, по функциям похожим на StringBuilder . Он содержит как текстовое содержимое, так и информацию о текущем выборе.

Вы часто сталкиваетесь TextFieldBuffer как с областью действия приемника в таких функциях, как TextFieldState.edit , InputTransformation.transformInput или OutputTransformation.transformOutput . В этих функциях вы можете читать или обновлять TextFieldBuffer по мере необходимости. После этого эти изменения либо фиксируются в TextFieldState , либо передаются в конвейер рендеринга в случае OutputTransformation .

Вы можете использовать стандартные функции редактирования, такие как append , insert , replace или delete чтобы изменить содержимое буфера. Чтобы изменить состояние выделения, либо напрямую задайте его переменную selection: TextRange , либо используйте служебные функции, такие как placeCursorAtEnd или selectAll . Сама выборка представлена TextRange , где начальный индекс является включающим, а конечный индекс — исключающим. TextRange с идентичными начальными и конечными значениями, например (3, 3) , обозначает позицию курсора, в которой в данный момент не выбрано ни одного символа.

val phoneNumberState = rememberTextFieldState()

LaunchedEffect(phoneNumberState) {
    phoneNumberState.edit { // TextFieldBuffer scope
        append("123456789")
    }
}

TextField(
    state = phoneNumberState,
    inputTransformation = InputTransformation { // TextFieldBuffer scope
        if (asCharSequence().isDigitsOnly()) {
            revertAllChanges()
        }
    },
    outputTransformation = OutputTransformation {
        if (length > 0) insert(0, "(")
        if (length > 4) insert(4, ")")
        if (length > 8) insert(8, "-")
    }
)

Редактировать текст в TextFieldState

Существует несколько методов, которые позволяют редактировать состояние напрямую через переменную состояния:

  • edit : позволяет редактировать содержимое состояния и предоставляет функции TextFieldBuffer , чтобы вы могли использовать такие методы, как insert , replace , append и другие.

    val usernameState = rememberTextFieldState("I love Android")
    // textFieldState.text : I love Android
    // textFieldState.selection: TextRange(14, 14)
    usernameState.edit { insert(14, "!") }
    // textFieldState.text : I love Android!
    // textFieldState.selection: TextRange(15, 15)
    usernameState.edit { replace(7, 14, "Compose") }
    // textFieldState.text : I love Compose!
    // textFieldState.selection: TextRange(15, 15)
    usernameState.edit { append("!!!") }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(18, 18)
    usernameState.edit { selectAll() }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(0, 18)

  • setTextAndPlaceCursorAtEnd : очищает текущий текст, заменяет его заданным текстом и устанавливает курсор в конец.

    usernameState.setTextAndPlaceCursorAtEnd("I really love Android")
    // textFieldState.text : I really love Android
    // textFieldState.selection : TextRange(21, 21)

  • clearText : Очищает весь текст.

    usernameState.clearText()
    // textFieldState.text :
    // textFieldState.selection : TextRange(0, 0)

Информацию о других функциях TextFieldState см. в справочнике TextFieldState .

Изменить вводимые пользователем данные

В следующих разделах описывается, как изменить пользовательский ввод. Преобразование ввода позволяет фильтровать ввод TextField , пока пользователь печатает, в то время как преобразование вывода форматирует пользовательский ввод до его отображения на экране.

Фильтрация пользовательского ввода с помощью входных преобразований

Преобразование ввода позволяет фильтровать вводимые пользователем данные. Например, если ваш TextField принимает американский номер телефона, вы хотите принимать только 10 цифр. Результаты InputTransformation сохраняются в TextFieldState .

Существуют встроенные фильтры для общих случаев использования InputTransformation . Чтобы ограничить длину, вызовите InputTransformation.maxLength() :

TextField(
    state = rememberTextFieldState(),
    lineLimits = TextFieldLineLimits.SingleLine,
    inputTransformation = InputTransformation.maxLength(10)
)

Пользовательские преобразования входных данных

InputTransformation — это интерфейс с одной функцией. При реализации вашего собственного InputTransformation вам необходимо переопределить TextFieldBuffer.transformInput :

class CustomInputTransformation : InputTransformation {
    override fun TextFieldBuffer.transformInput() {
    }
}

Для номера телефона добавьте пользовательское преобразование ввода, которое позволяет вводить в TextField только цифры:

class DigitOnlyInputTransformation : InputTransformation {
    override fun TextFieldBuffer.transformInput() {
        if (!TextUtils.isDigitsOnly(asCharSequence())) {
            revertAllChanges()
        }
    }
}

Цепочка входных преобразований

Чтобы добавить несколько фильтров к текстовому вводу, соедините InputTransformation с помощью функции расширения then . Фильтры выполняются последовательно. Рекомендуется сначала применять наиболее селективные фильтры, чтобы избежать ненужных преобразований данных, которые в конечном итоге будут отфильтрованы.

TextField(
    state = rememberTextFieldState(),
    inputTransformation = InputTransformation.maxLength(6)
        .then(CustomInputTransformation()),
)

После добавления входных преобразований входное поле TextField принимает максимум 10 цифр.

Форматируйте ввод перед его отображением

OutputTransformation позволяют вам форматировать пользовательский ввод до того, как он будет отображен на экране. В отличие от InputTransformation , форматирование, выполненное через OutputTransformation , не сохраняется в TextFieldState . Основываясь на предыдущем примере с номером телефона, вам нужно добавить скобки и тире в соответствующих местах:

Американский номер телефона, правильно отформатированный с использованием скобок, тире и соответствующих индексов.
Рисунок 3. Американский номер телефона с правильным форматированием и соответствующими индексами.

Это обновленный способ обработки VisualTransformation в TextField на основе значений, ключевым отличием которого является то, что вам не нужно вычислять их сопоставления смещений.

OutputTransformation — это интерфейс одного абстрактного метода. Чтобы реализовать пользовательский OutputTransformation , вам нужно переопределить метод transformOutput :

class CustomOutputTransformation : OutputTransformation {
    override fun TextFieldBuffer.transformOutput() {
    }
}

Чтобы отформатировать номер телефона, добавьте открывающую скобку в индексе 0, закрывающую скобку в индексе 4 и тире в индексе 8 в OutputTransformation :

class PhoneNumberOutputTransformation : OutputTransformation {
    override fun TextFieldBuffer.transformOutput() {
        if (length > 0) insert(0, "(")
        if (length > 4) insert(4, ")")
        if (length > 8) insert(8, "-")
    }
}

Далее добавьте OutputTransformation в TextField :

TextField(
    state = rememberTextFieldState(),
    outputTransformation = PhoneNumberOutputTransformation()
)

Как преобразования работают вместе

На следующей диаграмме показан поток от ввода текста до преобразования и вывода:

Визуализация того, как вводимый текст проходит преобразования, прежде чем он становится выводимым текстом.
Рисунок 4. Диаграмма, показывающая, как вводимый текст проходит через преобразования, прежде чем он становится выводимым текстом.
  1. Входные данные поступают от источника входных данных.
  2. Ввод фильтруется с помощью InputTransformation , который сохраняется в TextFieldState.
  3. Входные данные передаются через OutputTransformation для форматирования.
  4. Ввод представлен в TextField .

Установить параметры клавиатуры

TextField позволяет вам устанавливать параметры конфигурации клавиатуры, такие как раскладка клавиатуры, или включать автокоррекцию, если она поддерживается клавиатурой. Некоторые параметры не могут быть гарантированы, если программная клавиатура не соответствует параметрам, представленным здесь. Вот список поддерживаемых параметров клавиатуры :

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

Дополнительные ресурсы

{% дословно %} {% endverbatim %} {% дословно %} {% endverbatim %}