Edytor metody wprowadzania (IME) to element sterujący, który umożliwia użytkownikowi wpisywanie tekstu. Android udostępnia rozszerzalną platformę metod wprowadzania, dzięki której aplikacje mogą udostępniać użytkownikom alternatywne metody wprowadzania, np. klawiaturę ekranową lub wprowadzanie głosowe. Po zainstalowaniu edytorów IME użytkownik może je wybrać w ustawieniach systemu i używać w całym systemie. Można włączyć tylko jeden edytor IME naraz.
Aby dodać edytor IME do systemu Android, utwórz aplikację na Androida zawierającą klasę rozszerzającą InputMethodService
.
Poza tym zwykle tworzysz „ustawienia” działania, które przekazuje opcje do usługi IME. Możesz też określić interfejs ustawień, który będzie się wyświetlać w ramach ustawień systemu.
Na tej stronie znajdują się następujące tematy:
- Cykl życia IME
- Deklarowanie komponentów IME w pliku manifestu aplikacji
- Interfejs API IME
- Projektowanie UI IME
- Wysyłanie tekstu z edytora IME do aplikacji
- Praca z podtypami IME
- Inne uwagi na temat IME
Jeśli nie znasz jeszcze edytorów IME, przeczytaj najpierw artykuł wprowadzający Metody wprowadzania na ekranie.
Cykl życia IME
Poniższy diagram przedstawia cykl życia IME:
W poniższych sekcjach znajdziesz informacje o tym, jak wdrożyć interfejs i kod powiązany z edytorem IME, który jest zgodny z tym cyklem życia.
Zadeklaruj komponenty IME w pliku manifestu
W systemie Android jest to aplikacja na Androida zawierająca specjalną usługę IME. Plik manifestu aplikacji musi deklarować usługę, prosić o niezbędne uprawnienia, zawierać filtr intencji pasujący do działania action.view.InputMethod
i zawierać metadane określające cechy edytora IME. Aby udostępnić interfejs ustawień, który pozwala użytkownikowi modyfikować działanie IME, możesz zdefiniować działanie „ustawień”, które można uruchamiać w Ustawieniach systemu.
Ten fragment deklaruje usługę IME. Żąda uprawnienia BIND_INPUT_METHOD
umożliwiające usłudze połączenie IME z systemem, konfiguruje filtr intencji pasujący do działania android.view.InputMethod
i określa metadane dla IME:
<!-- Declares the input method service. --> <service android:name="FastInputIME" android:label="@string/fast_input_label" android:permission="android.permission.BIND_INPUT_METHOD"> <intent-filter> <action android:name="android.view.InputMethod" /> </intent-filter> <meta-data android:name="android.view.im" android:resource="@xml/method" /> </service>
Następny fragment deklaruje aktywność związaną z ustawieniami dla IME. Zawiera filtr intencji ACTION_MAIN
, który wskazuje, że to działanie jest głównym punktem wejścia aplikacji IME:
<!-- Optional: an activity for controlling the IME settings. --> <activity android:name="FastInputIMESettings" android:label="@string/fast_input_settings"> <intent-filter> <action android:name="android.intent.action.MAIN"/> </intent-filter> </activity>
Możesz też przyznać dostęp do ustawień IME bezpośrednio z jego interfejsu.
Interfejs API metody wprowadzania
Klasy specyficzne dla IME znajdują się w pakietach android.inputmethodservice
i android.view.inputmethod
. Klasa KeyEvent
jest ważna przy obsłudze znaków z klawiatury.
Centralną częścią IME jest komponent usługi – klasa, która rozszerza InputMethodService
. Oprócz wdrożenia normalnego cyklu życia usługi ta klasa zawiera wywołania zwrotne do udostępniania interfejsu IME, obsługi danych wejściowych użytkownika i dostarczania tekstu do wyróżnionego pola. Domyślnie klasa InputMethodService
zapewnia większość implementacji do zarządzania stanem i widocznością IME oraz komunikowania się z bieżącym polem do wprowadzania danych.
Ważne są również te klasy:
BaseInputConnection
-
Określa kanał komunikacji od
InputMethod
z powrotem do aplikacji, która otrzymuje dane wejściowe. Umożliwia on odczytywanie tekstu wokół kursora, zatwierdzanie tekstu w polu tekstowym i wysyłanie nieprzetworzonych kluczowych zdarzeń do aplikacji. Aplikacje muszą rozszerzać tę klasę, a nie implementować interfejsu podstawowegoInputConnection
. KeyboardView
- Rozszerzenie
View
, które renderuje klawiaturę i reaguje na zdarzenia wejściowe użytkownika. Układ klawiatury jest określany przez instancjęKeyboard
, którą można zdefiniować w pliku XML.
Projektowanie UI metody wprowadzania
W przypadku IME są 2 główne elementy wizualne: widok input i widok kandydatów. Musisz wdrożyć tylko te elementy, które pasują do projektowanej metody wprowadzania.
Widok danych wejściowych
Widok danych wejściowych to interfejs, w którym użytkownik wpisuje tekst, stosując kliknięcia klawiszy, pismo odręczne lub gesty. Po pierwszym wyświetleniu edytora IME system wywołuje wywołanie zwrotne onCreateInputView()
. W ramach implementacji tej metody utwórz układ, który chcesz wyświetlić w oknie IME, a potem wróć do systemu. Ten fragment kodu zawiera przykład implementacji metody onCreateInputView()
:
Kotlin
override fun onCreateInputView(): View { return layoutInflater.inflate(R.layout.input, null).apply { if (this is MyKeyboardView) { setOnKeyboardActionListener(this@MyInputMethod) keyboard = latinKeyboard } } }
Java
@Override public View onCreateInputView() { MyKeyboardView inputView = (MyKeyboardView) getLayoutInflater().inflate(R.layout.input, null); inputView.setOnKeyboardActionListener(this); inputView.setKeyboard(latinKeyboard); return inputView; }
W tym przykładzie MyKeyboardView
to instancja niestandardowej implementacji obiektu KeyboardView
, która renderuje żądanie Keyboard
.
Widok kandydatów
Widok kandydatów to interfejs, w którym IME wyświetla potencjalne poprawki słów lub sugestie do wyboru przez użytkownika. W cyklu życia IME system wywołuje onCreateCandidatesView()
, gdy wszystko jest gotowe do wyświetlenia widoku kandydatów. W implementacji tej metody zwracaj układ z sugestiami słów lub zwracaj wartość null, jeśli nie chcesz niczego wyświetlać. Odpowiedź o wartości null jest zachowaniem domyślnym, więc nie musisz jej wdrażać, jeśli nie podasz sugestii.
Uwagi na temat projektowania interfejsu
W tej sekcji opisujemy wybrane aspekty projektowania UI w edytorach IME.
Obsługa różnych rozmiarów ekranu
Interfejs użytkownika edytora IME musi być w stanie skalować się do różnych rozmiarów ekranu oraz obsługiwać zarówno orientację poziomą, jak i pionową. W trybie niepełnoekranowym należy zostawić w aplikacji wystarczającą ilość miejsca na wyświetlenie pola tekstowego i powiązanego z nim kontekstu, tak aby edytor nie zajmował więcej niż połowę ekranu. W trybie pełnoekranowym nie jest to problemem.
Obsługa różnych typów danych wejściowych
Pola tekstowe Androida umożliwiają ustawienie określonego typu danych wejściowych, np. dowolnego tekstu, liczb, adresów URL, adresów e-mail i wyszukiwanych ciągów znaków. Przy wdrażaniu nowego edytora IME wykrywaj typ danych wejściowych w każdym polu i udostępniaj dla niego odpowiedni interfejs. Nie musisz jednak konfigurować edytora IME, aby sprawdzać, czy użytkownik wpisuje prawidłowy tekst dla danego typu danych wejściowych. Odpowiada to aplikacji, do której należy pole tekstowe.
Tak na przykład interfejs udostępniany przez edytor IME dla języka łacińskiego do wprowadzania tekstu na platformie Androida:
A oto interfejs udostępniany przez Latin IME do wprowadzania liczbowych danych na platformie Androida:
Gdy pole do wprowadzania danych zostanie zaznaczone, a edytor IME uruchomi się, system wywoła onStartInputView()
, przesyłając obiekt EditorInfo
zawierający informacje o typie danych wejściowych i inne atrybuty pola tekstowego. W tym obiekcie pole inputType
zawiera typ danych wejściowych pola tekstowego.
Pole inputType
to pole int
, które zawiera wzorce bitowe dla różnych ustawień typów danych wejściowych. Aby przetestować go pod kątem typu danych wejściowych pola tekstowego, zamaskuj go za pomocą stałej TYPE_MASK_CLASS
w ten sposób:
Kotlin
inputType and InputType.TYPE_MASK_CLASS
Java
inputType & InputType.TYPE_MASK_CLASS
Wzorzec bitowy typu wejściowego może mieć jedną z kilku wartości, w tym:
TYPE_CLASS_NUMBER
- Pole tekstowe do wpisywania numerów. Jak widać na ilustracji 3, edytor IME dla alfabetów łacińskich wyświetla w polach tego typu klawiaturę numeryczną.
TYPE_CLASS_DATETIME
- Pole tekstowe do wpisania daty i godziny.
TYPE_CLASS_PHONE
- Pole tekstowe do wpisania numerów telefonów.
TYPE_CLASS_TEXT
- Pole tekstowe do wpisania obsługiwanych znaków.
Bardziej szczegółowe informacje o tych stałych znajdziesz w dokumentacji referencyjnej InputType
.
Pole inputType
może zawierać inne bity wskazujące wariant typu pola tekstowego, na przykład:
TYPE_TEXT_VARIATION_PASSWORD
- Wariant
TYPE_CLASS_TEXT
do wpisywania haseł. Metoda wprowadzania zamiast tekstu powoduje wyświetlanie znaków dingbatów. TYPE_TEXT_VARIATION_URI
- Wariant
TYPE_CLASS_TEXT
do wpisywania adresów URL i innych identyfikatorów URI. TYPE_TEXT_FLAG_AUTO_COMPLETE
- Wariant funkcji
TYPE_CLASS_TEXT
do wpisywania tekstu, który aplikacja automatycznie uzupełnia w słowniku, wyszukiwarce lub innej usłudze.
Podczas testowania tych wariantów maskuj inputType
za pomocą odpowiedniej stałej. Dostępne stałe maski znajdziesz w dokumentacji referencyjnej InputType
.
Wyślij tekst do aplikacji
Kiedy użytkownik wpisuje tekst za pomocą IME, możesz wysyłać go do aplikacji, wysyłając poszczególne kluczowe zdarzenia lub edytując tekst wokół kursora w polu tekstowym aplikacji. W obu przypadkach użyj instancji InputConnection
, aby przekazać tekst. Aby pobrać tę instancję, wywołaj InputMethodService.getCurrentInputConnection()
.
Edytowanie tekstu wokół kursora
Gdy edytujesz dotychczasowy tekst, możesz w BaseInputConnection
stosować te metody:
-
getTextBeforeCursor()
- Zwraca
CharSequence
, który zawiera liczbę żądanych znaków przed bieżącą pozycją kursora. -
getTextAfterCursor()
- Zwraca
CharSequence
, który zawiera liczbę żądanych znaków następujących po bieżącej pozycji kursora. -
deleteSurroundingText()
- Usuwa określoną liczbę znaków przed bieżącą pozycją kursora i po niej.
-
commitText()
- Przypisuje element
CharSequence
do pola tekstowego i ustawia nową pozycję kursora.
Na przykład ten fragment kodu pokazuje, jak zamienić cztery znaki po lewej stronie kursora tekstem „Hello!”:
Kotlin
currentInputConnection.also { ic: InputConnection -> ic.deleteSurroundingText(4, 0) ic.commitText("Hello", 1) ic.commitText("!", 1) }
Java
InputConnection ic = getCurrentInputConnection(); ic.deleteSurroundingText(4, 0); ic.commitText("Hello", 1); ic.commitText("!", 1);
Ułatw tworzenie tekstu przed zatwierdzeniem
Jeśli edytor IME przewiduje tekst lub wymaga wielu kroków, by utworzyć glif lub słowo, możesz pokazywać postęp w polu tekstowym, dopóki użytkownik nie zapisze danego słowa. Dzięki temu możesz zastąpić fragment tekstu gotowym tekstem. Możesz nadać tekstowi specjalne podejście, dodając do niego span, gdy przekazujesz go do funkcji setComposingText()
.
Ten fragment kodu pokazuje, jak wyświetlić postęp w polu tekstowym:
Kotlin
currentInputConnection.also { ic: InputConnection -> ic.setComposingText("Composi", 1) ic.setComposingText("Composin", 1) ic.commitText("Composing ", 1) }
Java
InputConnection ic = getCurrentInputConnection(); ic.setComposingText("Composi", 1); ic.setComposingText("Composin", 1); ic.commitText("Composing ", 1);
Przechwytywanie kluczowych zdarzeń dotyczących sprzętu
Mimo że okno metody wprowadzania nie jest wyraźnie zaznaczone, otrzymuje najpierw kluczowe zdarzenia sprzętowe i może je wykorzystać lub przekazać do aplikacji. Możesz na przykład używać klawiszy strzałek, aby poruszać się po interfejsie w celu wyboru kandydatów podczas tworzenia kompozycji. Możesz też przechwycić klawisz Wstecz, aby zamknąć wszystkie okna dialogowe pochodzące z okna metody wprowadzania.
Aby przechwytywać klucze sprzętowe, zastąp ustawienia onKeyDown()
i onKeyUp()
.
Wywołaj metodę super()
w przypadku kluczy, których nie chcesz obsługiwać samodzielnie.
Tworzenie podtypu IME
Dzięki podtypom edytor IME może wyświetlać wiele trybów wprowadzania i języków obsługiwanych przez dany edytor. Podtyp może obejmować:
- Region, np. pl_PL lub fr_FR
- trybu wprowadzania danych, takiego jak głos, klawiatura lub pismo odręczne;
- inne style, formularze lub właściwości specyficzne dla IME, np. 10-klawiszowy lub QWERTY układ klawiatury
Tryb może zawierać dowolny tekst, np. „klawiatura” lub „głos”. Podtyp może też ujawniać ich kombinację.
Informacje o podtypie są używane w oknie przełączania IME, które jest dostępne na pasku powiadomień oraz w ustawieniach IME. Te informacje umożliwiają też platformie bezpośrednie wywołanie określonego podtypu IME. Podczas tworzenia edytora IME używaj podtypu lokalizacji, ponieważ ułatwia on użytkownikowi rozpoznawanie różnych języków i trybów IME oraz przełączanie się między nimi.
Zdefiniuj podtypy w jednym z plików zasobów XML metody wejściowej za pomocą elementu <subtype>
. Ten fragment kodu definiuje edytor IME z 2 podtypami: podtypem klawiatury dla języka angielskiego (USA) i podtypem klawiatury dla języka francuskiego (Francja):
<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="com.example.softkeyboard.Settings" android:icon="@drawable/ime_icon"> <subtype android:name="@string/display_name_english_keyboard_ime" android:icon="@drawable/subtype_icon_english_keyboard_ime" android:languageTag="en-US" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="somePrivateOption=true" /> <subtype android:name="@string/display_name_french_keyboard_ime" android:icon="@drawable/subtype_icon_french_keyboard_ime" android:languageTag="fr-FR" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="someVariable=30,someInternalOption=false" /> <subtype android:name="@string/display_name_german_keyboard_ime" ... /> </input-method>
Aby mieć pewność, że podtypy są prawidłowo oznaczone w interfejsie użytkownika, użyj parametru „%s”, aby uzyskać etykietę podtypu, która jest taka sama jak etykieta języka podtypu. Dowiesz się o tym w kolejnych 2 kolejnych fragmentach kodu. Pierwszy fragment kodu pokazuje część pliku XML metody przesyłania:
<subtype android:label="@string/label_subtype_generic" android:imeSubtypeLocale="en_US" android:icon="@drawable/icon_en_us" android:imeSubtypeMode="keyboard" />
Następny fragment jest częścią pliku strings.xml
IME. Zasób ciągu znaków label_subtype_generic
, który jest używany w definicji interfejsu użytkownika metody wprowadzania do ustawiania etykiety podtypu, jest zdefiniowany w ten sposób:
<string name="label_subtype_generic">%s</string>
To ustawienie powoduje, że wyświetlana nazwa podtypu jest zgodna z ustawieniem lokalnym. Na przykład w każdym języku polskim wyświetlana nazwa to „English (Stany Zjednoczone)”.
Wybierz podtypy IME na pasku powiadomień
System Android zarządza wszystkimi podtypami udostępnianymi przez wszystkie edytory IME. Podtypy IME są traktowane jako tryby IME, do których należą. Użytkownik może przejść z paska powiadomień lub aplikacji Ustawienia do menu z dostępnymi podtypami IME, jak pokazano na tym rysunku:
Wybierz podtypy IME w ustawieniach systemu
Użytkownik może też określić sposób używania podtypów w panelu Język i wprowadzanie tekstu w ustawieniach systemowych:
Przełączanie między podtypami IME
Aby ułatwić użytkownikom przełączanie się między podtypami IME, możesz ustawić klawisz przełączania, np. ikonę języka w kształcie kuli ziemskiej na klawiaturze. Zwiększa to użyteczność klawiatury i jest wygodniejsze dla użytkownika. Aby włączyć tę funkcję, wykonaj te czynności:
- Zadeklaruj
supportsSwitchingToNextInputMethod = "true"
w plikach zasobów XML metody wprowadzania. Twoja deklaracja musi wyglądać podobnie do tego fragmentu kodu:<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="com.example.softkeyboard.Settings" android:icon="@drawable/ime_icon" android:supportsSwitchingToNextInputMethod="true">
- Wywołaj metodę
shouldOfferSwitchingToNextInputMethod()
. - Jeśli metoda zwraca wartość „prawda”, wyświetl klucz przełączania.
- Gdy użytkownik naciśnie klawisz przełączania, wywoła polecenie
switchToNextInputMethod()
, przekazując wartość fałsz. Wartość fałsz informuje system, że wszystkie podtypy są traktowane jednakowo niezależnie od tego, do którego IME należą. Ustawienie wartości „true” (prawda) wymaga, aby system przełączał się między podtypami w bieżącym edytorze IME.
Ogólne uwagi na temat IME
Oto co jeszcze musisz wziąć pod uwagę podczas implementacji IME:
- Zapewnij użytkownikom możliwość ustawiania opcji bezpośrednio w interfejsie IME.
- Zapewnij użytkownikom możliwość przełączania się na inny edytor IME bezpośrednio z interfejsu metody wprowadzania, ponieważ na urządzeniu może być zainstalowanych wiele IME.
- Szybko wyświetl interfejs IME. Wstępnie ładuj lub wczytuj na żądanie duże zasoby, by użytkownicy mogli zobaczyć edytor IME zaraz po kliknięciu pola tekstowego. Buforuj zasoby i widoki na potrzeby kolejnych wywołań metody wejściowej.
- Zwolnij duże przydziały pamięci natychmiast po ukryciu okna metody wprowadzania, aby aplikacje miały wystarczającą ilość pamięci do działania. Użyj opóźnionej wiadomości do zwolnienia zasobów, jeśli edytor IME jest ukryty na kilka sekund.
- Użytkownicy powinni wpisać jak najwięcej znaków dla języka lub regionu powiązanego z IME. Użytkownicy mogą stosować znaki interpunkcyjne w hasłach lub nazwach użytkowników, dlatego edytor IME musi zawierać wiele różnych znaków, aby umożliwić użytkownikom wpisanie hasła i uzyskanie dostępu do urządzenia.