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

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.

Ввод стиля с помощью 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

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

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