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

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 кисти для более сложного оформления TextField . В следующем разделе описывается, как использовать кисть для добавления цветного градиента к 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 предоставляет два основных свойства:

  • 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 %}