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

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.

Настройка ограничений линии

Компоненты TextField поддерживают прокрутку вдоль одной оси. Поведение прокрутки определяется параметром lineLimits . Для TextField горизонтальная прокрутка одной строки, а для многострочных TextField — вертикальная.

Используйте TextFieldLineLimits , чтобы выбрать подходящую конфигурацию строк для вашего TextField :

TextField(
    state = rememberTextFieldState(),
    lineLimits = TextFieldLineLimits.SingleLine
)

Текстовое поле в одну строку с текстом.

Конфигурация SingleLine обладает следующими характеристиками:

  • Текст никогда не переносится на следующую строку и не допускает переноса строк.
  • TextField всегда имеет фиксированную высоту.
  • Если текст выходит за пределы видимой части экрана, он прокручивается по горизонтали.

TextField(
    state = rememberTextFieldState("Hello\nWorld\nHello\nWorld"),
    lineLimits = TextFieldLineLimits.MultiLine(1, 4)
)

Многострочное текстовое поле с текстом

Конфигурация MultiLine обладает следующими характеристиками:

  • Принимает два параметра: minHeightInLines и maxHeightInLines .
  • Высота текстового поля должна быть не менее minHeightInLines .
  • Если текст выходит за пределы допустимых областей, он будет перенесен на следующую строку.
  • Если тексту требуется больше строк, поле увеличивается до высоты maxHeightInLines и прокручивается вертикально.

Ввод стиля с помощью Brush API

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

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

Реализуйте цветные градиенты с помощью 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)
)

В текстовом поле вводится текст, который отображается с эффектом радужного градиента.
Рисунок 1. Эффект радужного градиента для содержимого TextField .

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

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

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

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

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

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

Параметр rememberTextFieldState может быть пустым или иметь начальное значение, представляющее значение текста при инициализации. Если при последующем пересоставлении передается другое значение, значение состояния не обновляется. Чтобы обновить состояние после инициализации, вызовите методы edit для объекта 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("1234567890")

TextField(
    state = phoneNumberState,
    keyboardOptions = KeyboardOptions(
        keyboardType = KeyboardType.Phone
    ),
    inputTransformation = InputTransformation.maxLength(10).then {
        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 и другие.

    // Initial textFieldState text passed in is "I love Android"
    // textFieldState.text : I love Android
    // textFieldState.selection: TextRange(14, 14)
    textFieldState.edit { insert(14, "!") }
    // textFieldState.text : I love Android!
    // textFieldState.selection: TextRange(15, 15)
    textFieldState.edit { replace(7, 14, "Compose") }
    // textFieldState.text : I love Compose!
    // textFieldState.selection: TextRange(15, 15)
    textFieldState.edit { append("!!!") }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(18, 18)
    textFieldState.edit { selectAll() }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(0, 18)

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

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

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

    textFieldState.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 (!asCharSequence().isDigitsOnly()) {
            revertAllChanges()
        }
    }
}

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

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

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() {
    }
}

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

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

В класс KeyboardOptions теперь добавлен новый логический параметр showKeyboardOnFocus , который используется специально для компонентов TextField , интегрированных с TextFieldState . Этот параметр определяет поведение программной клавиатуры, когда TextField получает фокус иными способами, помимо прямого взаимодействия с пользователем (например, программно).

Если KeyboardOptions.showKeyboardOnFocus установлен в значение true, программная клавиатура не появляется автоматически, если TextField получает фокус косвенным образом. В таких случаях пользователю необходимо явно коснуться самого TextField , чтобы отобразить клавиатуру.

Определите логику взаимодействия с клавиатурой.

Кнопка действия на программной клавиатуре Android позволяет осуществлять интерактивные действия внутри вашего приложения. Для получения дополнительной информации о настройке кнопки действия см. раздел «Настройка параметров клавиатуры» .

Кнопка действия программной клавиатуры (значок галочки), обведенная красным кругом.
Рисунок 5. Кнопка действия программной клавиатуры.

Чтобы определить, что происходит при нажатии пользователем этой кнопки действия, используйте параметр onKeyboardAction . Этот параметр принимает необязательный функциональный интерфейс с именем KeyboardActionHandler . Интерфейс KeyboardActionHandler содержит единственный метод onKeyboardAction(performDefaultAction: () -> Unit) . Предоставив реализацию для этого метода onKeyboardAction , вы можете ввести собственную логику, которая выполняется при нажатии пользователем кнопки действия на клавиатуре.

Некоторые стандартные типы действий клавиатуры имеют встроенное поведение по умолчанию. Например, выбор ImeAction.Next или ImeAction.Previous в качестве типа действия по умолчанию перенесет фокус на последующее или предыдущее поле ввода соответственно. Аналогично, кнопка действия, установленная на ImeAction.Done , обычно закрывает программную клавиатуру. Эти функции по умолчанию выполняются автоматически и не требуют указания KeyboardActionHandler .

Помимо этих действий по умолчанию, вы также можете реализовать собственное поведение. Когда вы предоставляете свой KeyboardActionHandler , его метод onKeyboardAction получает функцию performDefaultAction . Вы можете вызвать эту функцию performDefaultAction() в любой точке вашей пользовательской логики, чтобы также запустить стандартное поведение по умолчанию, связанное с текущим действием IME.

TextField(
    state = textFieldViewModel.usernameState,
    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
    onKeyboardAction = { performDefaultAction ->
        textFieldViewModel.validateUsername()
        performDefaultAction()
    }
)

Этот фрагмент кода иллюстрирует распространенный сценарий использования на экране регистрации, где есть поле для имени пользователя. Для этого поля в качестве кнопки действия клавиатуры выбрано ImeAction.Next . Такой выбор обеспечивает быструю и беспрепятственную навигацию к следующему полю для ввода пароля.

В дополнение к стандартной навигации, необходимо инициировать фоновый процесс проверки имени пользователя по мере ввода им пароля. Чтобы гарантировать сохранение стандартного поведения переключения фокуса, присущего ImeAction.Next , наряду с этой пользовательской логикой проверки, вызывается функция performDefaultAction() . Вызов performDefaultAction() неявно запускает базовую систему управления фокусом для перемещения фокуса к следующему соответствующему элементу пользовательского интерфейса, сохраняя ожидаемый поток навигации.

Создайте защищенное поле для ввода пароля.

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

SecureTextField имеет textObfuscationMode , который управляет тем, как пользователь видит вводимые символы. textObfuscationMode имеет следующие возможности:

  • Hidden : Скрывает все поля ввода. Поведение по умолчанию на настольных платформах.

    Защищенное текстовое поле, в котором набранные символы скрываются.

  • Visible : Отображает все введенные данные.

    Защищенное текстовое поле, в котором отображаются набранные символы.

  • RevealLastTyped : Скрывает все поля ввода, кроме последнего символа. Поведение по умолчанию на мобильных устройствах.

    Защищенное текстовое поле, в котором на короткое время отображается только последний введенный символ.

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

{% verbatim %} {% endverbatim %} {% verbatim %} {% endverbatim %}