Konfigurowanie pól tekstowych

TextField pozwala użytkownikom wpisywać i modyfikować tekst. Dostępne są 2 typy pól tekstowych: pola tekstowe zależne od stanu i pola tekstowe zależne od wartości. Wybierz typ treści, które chcesz wyświetlać:

Zalecamy używanie pól tekstowych zależnych od stanu, ponieważ zapewniają one bardziej kompletne i niezawodne podejście do zarządzania stanem TextField. W tabeli poniżej opisano różnice między tymi typami pól tekstowych oraz podano najważniejsze zalety pól tekstowych zależnych od stanu:

Funkcja

Pola tekstowe na podstawie wartości

Pola tekstowe zależne od stanu

Korzyści zależne od stanu

Zarządzanie stanem

Aktualizuje stan pola tekstowego za pomocą wywołania zwrotnego onValueChange. Użytkownik jest odpowiedzialny za aktualizowanie pliku value w swoim stanie na podstawie zmian zgłoszonych przez plik onValueChange.

Wyraźnie używa obiektu TextFieldState do zarządzania stanem wprowadzania tekstu (wartość, wybór, kompozycja). Stan ten można zapamiętać i udostępnić.

  • Funkcja onValueChange callback została usunięta, co uniemożliwia wprowadzenie asynchronicznych zachowań.
  • Stan przetrwa ponowne skompilowanie, konfigurację i zakończenie procesu.

Przekształcenie wizualne

Używa VisualTransformation do modyfikowania wyglądu wyświetlanego tekstu. Zwykle formatowanie danych wejściowych i wyjściowych odbywa się w jednym kroku.

Używa InputTransformation do modyfikowania danych wejściowych użytkownika przed ich zapisaniem w stanie, a także OutputTransformation do formatowania zawartości pola tekstowego bez zmiany danych stanu.

  • Nie musisz już podawać mapowania przesunięcia między oryginalnym tekstem surowym a przekształconym tekstem za pomocą OutputTransformation.

Limity linii

Akceptuje singleLine: Boolean, maxLines: Int i minLines: Int do sterowania liczbą wierszy.

Używa parametru lineLimits: TextFieldLineLimits do skonfigurowania minimalnej i maksymalnej liczby wierszy, które może zajmować pole tekstowe.

  • Usuwa niejednoznaczność podczas konfigurowania limitów linii, podając parametr lineLimits typu TextFieldLineLimits.

Bezpieczne pole tekstowe

Nie dotyczy

SecureTextField to komponent utworzony na podstawie pól tekstowych zależnych od stanu, służących do wpisywania hasła.

  • Umożliwia optymalizację pod kątem bezpieczeństwa, a także korzystanie z wstępnie zdefiniowanego interfejsu textObfuscationMode.

Na tej stronie opisano, jak zaimplementować TextField, stylizować dane wejściowe TextField i konfigurować inne opcje TextField, takie jak opcje klawiatury i wizualna zmiana danych wejściowych użytkownika.

Wybierz implementację TextField

Istnieją 2 poziomy wdrażania TextField:

  1. TextField to implementacja Material Design. Zalecamy wybranie tej implementacji, ponieważ jest ona zgodna z wytycznymi dotyczącymi Material Design:
  2. BasicTextField umożliwia użytkownikom edytowanie tekstu za pomocą klawiatury sprzętowej lub programowej, ale nie zawiera żadnych elementów dekoracyjnych, takich jak podpowiedź czy placeholder.

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

pole tekstowe z możliwością edytowania zawierające słowo;

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

Pole tekstowe z możliwością edycji, z fioletowym obramowaniem i etykietą.

Styl TextField

TextFieldBasicTextField mają wiele wspólnych parametrów do dostosowywania. Pełna lista TextField jest dostępna w kodzie źródłowym TextField. Oto niepełna lista przydatnych parametrów:

  • 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)
)

Wielowierszowe pole tekstowe z 2 wierszami do edycji i etykietą

Jeśli Twój projekt wymaga użycia materiału TextField lub OutlinedTextField, zalecamy użycie TextField zamiast BasicTextField. Jednak BasicTextField należy używać podczas tworzenia projektów, które nie wymagają dekoracji ze specyfikacji Material.

Stylizowanie za pomocą interfejsu Brush API

Aby uzyskać bardziej zaawansowane efekty stylizacji w TextField, możesz użyć interfejsu Brush API. W tej sekcji opisaliśmy, jak za pomocą pędzla dodać kolorowy gradient do wejścia TextField.

Więcej informacji o używaniu interfejsu Brush API do stylizacji tekstu znajdziesz w artykule Włączanie zaawansowanego stylizowania za pomocą interfejsu Brush API.

Implementowanie kolorowych gradientów za pomocą TextStyle

Aby zastosować kolorowy gradient podczas pisania w polu TextField, ustaw wybrany przez siebie pędzel jako TextStyle dla pola TextField. W tym przykładzie używamy wbudowanego pędzla z linearGradient, aby wyświetlić efekt gradientu tęczy podczas wpisywania tekstu w 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)
)

Użycie metody buildAnnotatedString i SpanStyle razem z linearGradient do dostosowania tylko części tekstu.
Rysunek 1. Efekt gradientu tęczy w przypadku treści TextField.

Zarządzanie stanem pola tekstowego

TextField używa dedykowanej klasy TextFieldState do przechowywania treści i bieżącego wyboru. TextFieldState jest przeznaczony do podnoszenia w dowolnym miejscu w ramach Twojej architektury. TextFieldState udostępnia 2 główne właściwości:

  • initialText: zawartość TextField.
  • initialSelection: wskazuje, gdzie znajduje się kursor lub zaznaczony obszar.

Różnica między TextFieldState a innymi metodami, takimi jak onValueChange callback, polega na tym, że TextFieldState obejmuje cały przepływ danych wejściowych. Obejmuje to używanie prawidłowych struktur danych pomocniczych, wstawianie filtrów i formaterów, a także synchronizowanie wszystkich zmian pochodzących z różnych źródeł.

Możesz użyć elementu TextFieldState(), aby podać stan w elementach TextField. W tym celu zalecamy użycie funkcji rememberTextFieldState(). rememberTextFieldState() tworzy instancję TextFieldState w komponowalnym komponencie, zapewnia pamiętanie obiektu stanu i wbudowaną funkcję zapisywania i przywracania:

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

rememberTextFieldState może mieć pusty parametr lub przekazaną wartość początkową, która reprezentuje wartość tekstu podczas inicjalizacji. Jeśli w kolejnych składaniach zostanie przekazana inna wartość, wartość stanu nie zostanie zaktualizowana. Aby zaktualizować stan po jego zainicjowaniu, wywołaj metody edycji w obiekcie TextFieldState.

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

Pole tekstowe z tekstem „Nazwa użytkownika” w polu tekstowym.
Rysunek 2. TextField z tekstem początkowym „Nazwa użytkownika”.

Modyfikowanie tekstu za pomocą TextFieldBuffer

Element TextFieldBuffer to edytowalny kontener tekstowy o funkcjonalności podobnej do elementu StringBuilder. Zawiera on zarówno treść tekstową, jak i informacje o bieżącym zaznaczeniu.

Często spotyka się TextFieldBuffer jako zakres odbiorczy w funkcjach takich jak TextFieldState.edit, InputTransformation.transformInput lub OutputTransformation.transformOutput. W tych funkcjach możesz odczytać lub zaktualizować zmienną TextFieldBuffer w razie potrzeby. Następnie te zmiany są zapisywane w TextFieldState lub przekazywane do ścieżki renderowania w przypadku OutputTransformation.

Zawartość bufora możesz modyfikować za pomocą standardowych funkcji edycji, takich jak append, insert, replace lub delete. Aby zmienić stan wyboru, ustaw bezpośrednio zmienną selection: TextRange lub użyj funkcji pomocniczych, takich jak placeCursorAtEnd lub selectAll. Samą selekcję reprezentuje elementTextRange, gdzie indeks początkowy jest traktowany włącznie, a indeks końcowy wyłącznie. TextRange z identycznymi wartościami początkową i końcową, np. (3, 3), oznacza pozycję kursora bez zaznaczonych znaków.

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, "-")
    }
)

Edytuj tekst w aplikacji TextFieldState

Istnieje kilka metod, które umożliwiają edytowanie stanu bezpośrednio za pomocą zmiennej stanu:

  • edit: umożliwia edytowanie zawartości stanu i uzyskiwanie dostępu do funkcji TextFieldBuffer, dzięki którym można używać metod takich jak insert, replace, append i innych.

    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: czyści bieżący tekst, zastępuje go podanym tekstem i ustawia kursor na końcu.

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

  • clearText: czyści cały tekst.

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

Inne funkcje TextFieldState znajdziesz w dokumentacji funkcji TextFieldState.

Modyfikowanie danych wejściowych użytkownika

W następnych sekcjach opisujemy, jak modyfikować dane wejściowe użytkownika. Przekształcenie danych wejściowych umożliwia filtrowanie danych wejściowych TextField w trakcie ich wpisywania przez użytkownika, a przekształcenie danych wyjściowych formatuje dane wejściowe przed ich wyświetleniem na ekranie.

Filtrowanie danych wejściowych użytkownika za pomocą przekształceń danych wejściowych

Przekształcenie danych wejściowych umożliwia filtrowanie danych wejściowych od użytkownika. Jeśli na przykład TextField przyjmuje amerykański numer telefonu, możesz zaakceptować tylko 10 cyfr. Wyniki InputTransformation są zapisywane w pliku TextFieldState.

Do typowych zastosowań InputTransformation dostępne są wbudowane filtry. Aby ograniczyć długość, zadzwoń pod numer InputTransformation.maxLength():

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

Niestandardowe przekształcenia danych wejściowych

InputTransformation to interfejs jednej funkcji. Podczas implementowania niestandardowego InputTransformation musisz zastąpić:TextFieldBuffer.transformInput

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

W przypadku numeru telefonu dodaj niestandardową transformację danych wejściowych, która zezwala na wpisywanie tylko cyfr w polu TextField:

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

Łańcuchowe transformacje danych wejściowych

Aby dodać do tekstu wiele filtrów, połącz InputTransformation za pomocą funkcji rozszerzenia then. Filtry są wykonywane kolejno. Zalecamy najpierw stosować najbardziej selektywne filtry, aby uniknąć niepotrzebnych przekształceń danych, które ostatecznie zostaną odfiltrowane.

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

Po dodaniu przekształceń danych wejściowych dane wejściowe TextField mogą zawierać maksymalnie 10 cyfr.

Formatowanie danych wejściowych przed ich wyświetleniem

OutputTransformation umożliwiają formatowanie danych wejściowych użytkownika przed ich renderowaniem na ekranie. W przeciwieństwie do InputTransformation formatowanie wprowadzone za pomocą funkcji OutputTransformation nie jest zapisywane w TextFieldState. W przypadku poprzedniego przykładu numeru telefonu musisz w odpowiednich miejscach dodać nawiasy i kreski:

Amerykański numer telefonu w właściwym formacie z nawiasami, myślnikami i odpowiednimi indeksami.
Rysunek 3. amerykański numer telefonu w odpowiednim formacie i z odpowiednimi indeksami;

Jest to zaktualizowany sposób obsługi VisualTransformation w elementach TextField opartych na wartościach. Główną różnicą jest to, że nie musisz obliczać ich mapowań przesunięć.

OutputTransformation to pojedynczy abstrakcyjny interfejs metody. Aby zaimplementować niestandardową funkcję OutputTransformation, musisz zastąpić metodę transformOutput:

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

Aby sformatować numer telefonu, dodaj nawias otwierający w indeksie 0, nawias zamykający w indeksie 4 i kreskę w indeksie 8 do OutputTransformation:

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

Następnie dodaj OutputTransformation do TextField:

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

Jak działają przekształcenia

Poniższy diagram przedstawia przepływ danych od tekstu wejściowego do jego przekształcenia i wyjścia:

Wizualizacja tego, jak tekst wejściowy przechodzi przez przekształcenia, zanim stanie się tekstem wyjściowym.
Rysunek 4. Diagram pokazujący, jak tekst wejściowy przechodzi przez przekształcenia, zanim stanie się tekstem wyjściowym.
  1. Dane wejściowe są otrzymywane ze źródła sygnału.
  2. Dane wejściowe są filtrowane przez funkcję InputTransformation, która jest zapisywana w stanie TextFieldState.
  3. Dane wejściowe są przekazywane przez OutputTransformation w celu sformatowania.
  4. Dane wejściowe są wyświetlane w TextField.

Ustawianie opcji klawiatury

TextField umożliwia konfigurowanie opcji klawiatury, takich jak układ klawiatury, lub włączanie autokorekty, jeśli jest obsługiwana przez klawiaturę. Niektóre opcje mogą nie być dostępne, jeśli klawiatura programowa nie jest zgodna z opcjami podanymi tutaj. Oto lista obsługiwanych opcji klawiatury:

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

Dodatkowe materiały