Konfigurowanie pól tekstowych

TextField umożliwia użytkownikom wpisywanie i modyfikowanie tekstu. Możesz używać 2 rodzajów pól tekstowych: pól tekstowych opartych na stanie i pól tekstowych opartych na wartości. Wybierz typ treści, które chcesz wyświetlać:

Zalecamy używanie pól tekstowych opartych na stanie, ponieważ zapewniają one bardziej kompletne i niezawodne podejście do zarządzania stanem elementu TextField. W poniższej tabeli przedstawiono różnice między tymi typami pól tekstowych oraz najważniejsze zalety pól tekstowych opartych na stanie:

Funkcja

Pola tekstowe oparte na wartościach

Pola tekstowe zależne od stanu

Świadczenia stanowe

Zarządzanie stanem

Aktualizuje stan pola tekstowego za pomocą wywołania zwrotnego onValueChange. Odpowiadasz za aktualizowanie value w swoim stanie na podstawie zmian zgłoszonych przez onValueChange.

wyraźnie używa obiektu TextFieldState do zarządzania stanem wprowadzania tekstu (wartość, zaznaczenie i kompozycja); Ten stan można zapamiętać i udostępnić.

  • Wywołanie zwrotne onValueChange zostało usunięte, co uniemożliwia wprowadzanie zachowań asynchronicznych.
  • Stan jest zachowywany podczas rekompozycji, konfiguracji i śmierci procesu.

Przekształcenie wizualne

Używa VisualTransformation do modyfikowania wyglądu wyświetlanego tekstu. Zwykle obsługuje to zarówno formatowanie danych wejściowych, jak i wyjściowych w jednym kroku.

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

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

Limity linii

Akceptuje wartości singleLine: Boolean, maxLines: Int i minLines: Int, aby kontrolować liczbę wierszy.

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

  • Usuwa niejednoznaczność podczas konfigurowania limitów wierszy przez podanie parametru lineLimits typu TextFieldLineLimits.

Bezpieczne pole tekstowe

Nie dotyczy

SecureTextField to element kompozycyjny oparty na polach tekstowych opartych na stanie, który służy do tworzenia pola hasła.

  • Umożliwia optymalizację pod kątem bezpieczeństwa i zawiera wstępnie zdefiniowany interfejs z textObfuscationMode.

Na tej stronie opisujemy, jak wdrożyć TextField, dostosować styl danych wejściowych TextField i skonfigurować inne opcje TextField, takie jak opcje klawiatury i wizualne przekształcanie danych wejściowych użytkownika.

Wybierz implementację TextField

Istnieją 2 poziomy implementacji TextField:

  1. TextField to implementacja Material Design. Zalecamy wybranie tej implementacji, ponieważ jest ona zgodna ze wskazówkami dotyczącymi Material Design:
  2. BasicTextField umożliwia użytkownikom edytowanie tekstu za pomocą klawiatury sprzętowej lub klawiatury ekranowej, ale nie udostępnia żadnych elementów dekoracyjnych, takich jak podpowiedź czy obiekt zastępczy.

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ą edytowania, z fioletowym obramowaniem i etykietą.

Styl TextField

TextField i BasicTextField mają wiele wspólnych parametrów dostosowywania. Pełna lista dla 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)
)

Pole tekstowe z linią łamaną, z 2 wierszami do edycji i etykietą

Zalecamy używanie TextField zamiast BasicTextField, gdy projekt wymaga TextField lub OutlinedTextField Material. Jednak BasicTextField należy używać podczas tworzenia projektów, które nie wymagają dekoracji ze specyfikacji Material.

Konfigurowanie limitów linii

Komponenty TextField obsługują przewijanie wzdłuż jednej osi. Sposób przewijania określa parametr lineLimits. TextField skonfigurowane jako jednoliniowe przewijają się poziomo, a wielolinioweTextField – pionowo.

Użyj TextFieldLineLimits, aby wybrać odpowiednią konfigurację linii dla TextField:

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

Jednowierszowe pole tekstowe z tekstem

Konfiguracja SingleLine ma te cechy:

  • Tekst nigdy nie jest zawijany i nie można wstawiać nowych wierszy.
  • TextField zawsze ma stałą wysokość.
  • Jeśli tekst się nie mieści, jest przewijany w poziomie.

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

Pole tekstowe z linią łamaną i tekstem

Konfiguracja MultiLine ma te cechy:

  • Akceptuje 2 parametry: minHeightInLines i maxHeightInLines.
  • Pole tekstowe ma co najmniej minHeightInLines wysokości.
  • Jeśli tekst się nie mieści, zostanie zawinięty.
  • Jeśli tekst wymaga więcej wierszy, pole powiększa się do wysokości maxHeightInLines i przewija się w pionie.

Stylizowanie danych wejściowych za pomocą interfejsu Brush API

Aby uzyskać bardziej zaawansowane opcje stylizacji w TextField, możesz użyć interfejsu Brush API. W sekcji poniżej opisano, jak za pomocą pędzla dodać kolorowy gradient do danych wejściowych TextField.

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

Zaimplementuj gradienty kolorów za pomocą TextStyle

Aby podczas pisania w elemencie TextField wyświetlał się gradient koloru, ustaw wybrany pędzel jako TextStyle dla elementu 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)
)

Tekst wpisywany w polu tekstowym z efektem gradientu tęczowego.
Rysunek 1. Efekt tęczowego gradientu dla treści TextField.

Zarządzanie stanem pola tekstowego

TextField używa dedykowanej klasy zmiennej stanu o nazwie TextFieldState do obsługi treści i wyboru. TextFieldState można umieścić w dowolnym miejscu architektury. TextFieldState udostępnia 2 główne właściwości:

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

Tym, co odróżnia TextFieldState od innych metod, takich jak wywołanie zwrotne onValueChange, jest to, że TextFieldState w pełni obejmuje cały proces wprowadzania danych. Obejmuje to używanie prawidłowych struktur danych, wbudowanych filtrów i formaterów, a także synchronizowanie wszystkich zmian pochodzących z różnych źródeł.

Możesz użyć TextFieldState(), aby podnieść stan w TextField. W tym celu zalecamy użycie funkcji rememberTextFieldState(). rememberTextFieldState() tworzy instancję TextFieldState w funkcji kompozycyjnej, dba o zapamiętanie obiektu stanu i zapewnia wbudowane funkcje zapisywania i przywracania:

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

rememberTextFieldState może mieć pusty parametr lub wartość początkową przekazaną do reprezentowania wartości tekstu podczas inicjowania. Jeśli w kolejnej rekompozycji 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” wyświetlanym wewnątrz pola.
Rysunek 2. TextField z tekstem początkowym „Nazwa użytkownika”.

Modyfikowanie tekstu za pomocą TextFieldBuffer

TextFieldBuffer służy jako kontener tekstu z możliwością edycji, podobnie jak StringBuilder. Zawiera zarówno treść tekstową, jak i informacje o zaznaczeniu.

TextFieldBuffer często występuje jako zakres odbiorcy w funkcjach takich jak TextFieldState.edit, InputTransformation.transformInput czy OutputTransformation.transformOutput. W tych funkcjach możesz w razie potrzeby odczytywać lub aktualizować TextFieldBuffer. Następnie zmiany te są zatwierdzane w TextFieldState lub przekazywane do potoku renderowania w przypadku OutputTransformation.

Aby zmodyfikować zawartość bufora, możesz użyć standardowych funkcji edycji, takich jak append, insert, replace lub delete. Aby zmienić stan wyboru, ustaw bezpośrednio zmienną selection: TextRange lub użyj funkcji użytkowych, takich jak placeCursorAtEnd lub selectAll. Zaznaczenie jest reprezentowane przez obiekt TextRange, w którym indeks początkowy jest uwzględniany, a indeks końcowy jest wykluczany. TextRange z identycznymi wartościami początkowymi i końcowymi, np. (3, 3), oznacza pozycję kursora bez zaznaczonych znaków.

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

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 udostępnia funkcje TextFieldBuffer, dzięki czemu możesz używać metod takich jak insert, replace, append i inne.

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

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

  • clearText: usuwa cały tekst.

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

Inne funkcje TextFieldState znajdziesz w dokumentacji TextFieldState.

Modyfikowanie danych wejściowych użytkownika

W sekcjach poniżej opisujemy, jak modyfikować dane wejściowe użytkownika. Przekształcanie danych wejściowych umożliwia filtrowanie danych wejściowych TextField podczas pisania przez użytkownika, a przekształcanie danych wyjściowych formatuje dane wejściowe użytkownika, zanim zostaną wyświetlone 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, chcesz akceptować tylko 10 cyfr. Wyniki InputTransformation są zapisywane w TextFieldState.

Dostępne są wbudowane filtry do typowych przypadków użycia InputTransformation. Aby ograniczyć długość, wywołaj InputTransformation.maxLength():

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

Niestandardowe przekształcenia danych wejściowych

InputTransformation to interfejs z jedną funkcją. Podczas implementowania niestandardowego elementu InputTransformation musisz zastąpić element TextFieldBuffer.transformInput:

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

W przypadku numeru telefonu dodaj niestandardowe przekształcenie danych wejściowych, które zezwala na wpisywanie w polu TextField tylko cyfr:

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

Przekształcenia danych wejściowych łańcucha

Aby dodać wiele filtrów do danych wejściowych, połącz InputTransformation za pomocą funkcji rozszerzenia then. Filtry są wykonywane po kolei. Zgodnie ze sprawdzoną metodą najpierw zastosuj 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 pole TextField akceptuje maksymalnie 10 cyfr.

Formatowanie danych wejściowych przed ich wyświetleniem

OutputTransformation umożliwiają formatowanie danych wejściowych użytkownika przed ich wyświetleniem na ekranie. W przeciwieństwie do InputTransformation formatowanie wykonane za pomocą OutputTransformation nie jest zapisywane w TextFieldState. Wracając do poprzedniego przykładu z numerem telefonu, musisz dodać nawiasy i myślniki w odpowiednich miejscach:

Amerykański numer telefonu, prawidłowo sformatowany z nawiasami, myślnikami i odpowiednimi indeksami.
Rysunek 3. Amerykański numer telefonu z odpowiednim formatowaniem i odpowiednimi indeksami.

To zaktualizowany sposób obsługi VisualTransformation w TextField opartych na wartościach. Główna różnica polega na tym, że nie musisz obliczać ich mapowań przesunięcia.

OutputTransformation to interfejs z jedną metodą abstrakcyjną. Aby wdrożyć niestandardowy element 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 myślnik 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 przekształcenia ze sobą współpracują

Poniższy diagram przedstawia przepływ od tekstu wejściowego przez przekształcenie do danych wyjściowych:

Wizualizacja sposobu, w jaki 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ą odbierane ze źródła danych wejściowych.
  2. Dane wejściowe są filtrowane przez InputTransformation, który jest zapisywany w TextFieldState.
  3. Dane wejściowe są przekazywane do OutputTransformation w celu sformatowania.
  4. Dane wejściowe są prezentowane w TextField.

Ustawianie opcji klawiatury

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

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

Klasa KeyboardOptions zawiera teraz nowy parametr logiczny showKeyboardOnFocus, którego używasz specjalnie w przypadku komponentów TextField zintegrowanych z TextFieldState. Ta opcja określa zachowanie klawiatury ekranowej, gdy element TextField zostanie zaznaczony w inny sposób niż przez bezpośrednią interakcję użytkownika (np. automatycznie).

Gdy właściwość KeyboardOptions.showKeyboardOnFocus ma wartość „true”, klawiatura ekranowa nie pojawia się automatycznie, jeśli element TextField uzyskuje zaznaczenie pośrednio. W takich przypadkach użytkownik musi kliknąć TextField, aby wyświetlić klawiaturę.

Definiowanie logiki interakcji z klawiaturą

Przycisk polecenia na klawiaturze ekranowej Androida umożliwia interaktywne odpowiedzi w aplikacji. Więcej informacji o konfigurowaniu przycisku polecenia znajdziesz w sekcji Ustawianie opcji klawiatury.

Przycisk polecenia na klawiaturze ekranowej (ikona znacznika wyboru) zakreślony na czerwono.
Rysunek 5. Przycisk polecenia klawiatury ekranowej.

Aby określić, co się stanie, gdy użytkownik kliknie ten przycisk polecenia, użyj parametru onKeyboardAction. Ten parametr akceptuje opcjonalny interfejs funkcjonalny o nazwie KeyboardActionHandler. Interfejs KeyboardActionHandler zawiera jedną metodę: onKeyboardAction(performDefaultAction: () -> Unit). Dzięki implementacji tej metody onKeyboardAction możesz wprowadzić niestandardową logikę, która będzie wykonywana, gdy użytkownik naciśnie przycisk polecenia na klawiaturze.

Kilka standardowych typów działań klawiatury ma wbudowane działania domyślne. Na przykład wybranie ImeAction.Next lub ImeAction.Previous jako typu działania spowoduje domyślnie przeniesienie zaznaczenia odpowiednio do następnego lub poprzedniego pola do wprowadzania danych. Podobnie przycisk polecenia ustawiony na ImeAction.Done zwykle zamyka klawiaturę ekranową. Te domyślne funkcje są wykonywane automatycznie i nie wymagają podania KeyboardActionHandler.

Oprócz tych działań domyślnych możesz też wdrożyć niestandardowe zachowanie. Gdy podasz KeyboardActionHandler, jego metoda onKeyboardAction otrzyma funkcję performDefaultAction. Możesz wywołać tę funkcję performDefaultAction() w dowolnym momencie w niestandardowej logice, aby aktywować standardowe działanie domyślne powiązane z bieżącym działaniem edytora IME.

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

Ten fragment kodu ilustruje typowy przypadek użycia na ekranie rejestracji z polem nazwy użytkownika. W tym polu jako przycisk polecenia klawiatury wybrano ImeAction.Next. Dzięki temu możesz szybko i płynnie przejść do kolejnego pola hasła.

Oprócz tej standardowej nawigacji wymagane jest zainicjowanie procesu weryfikacji nazwy użytkownika w tle, gdy użytkownik wpisuje hasło. Aby mieć pewność, że domyślne zachowanie przełączania fokusu właściwe dla ImeAction.Next zostanie zachowane wraz z tą logiką walidacji niestandardowej, wywoływana jest funkcja performDefaultAction(). Wywołanie performDefaultAction() niejawnie aktywuje podstawowy system zarządzania fokusem, aby przenieść fokus na następny odpowiedni element interfejsu, zachowując oczekiwany przepływ nawigacji.

Tworzenie bezpiecznego pola hasła

SecureTextField to element kompozycyjny oparty na polach tekstowych opartych na stanie, który służy do tworzenia pola hasła. Zalecamy używanie SecureTextField do tworzenia pól tekstowych haseł, ponieważ domyślnie ukrywa ono wprowadzane znaki i wyłącza działania wycinania i kopiowania.

SecureTextField ma textObfuscationMode, który określa, jak użytkownik widzi wprowadzane znaki. textObfuscationMode ma te opcje:

  • Hidden: ukrywa wszystkie dane wejściowe. Działanie domyślne na platformach komputerowych.

    Bezpieczne pole tekstowe, w którym wpisywane znaki są ukryte.

  • Visible: pokazuje wszystkie dane wejściowe.

    Bezpieczne pole tekstowe, w którym wpisywane znaki są widoczne.

  • RevealLastTyped: ukrywa wszystkie wpisane znaki oprócz ostatniego. Domyślne działanie na urządzeniach mobilnych.

    Bezpieczne pole tekstowe, w którym przez chwilę wyświetlany jest tylko ostatni wpisany znak.

Dodatkowe materiały