Edytor metody wprowadzania (IME) to element sterujący, który pozwala użytkownikom wpisywać tekst. Android udostępnia rozszerzalne środowisko metody wprowadzania, które umożliwia aplikacjom udostępnianie użytkownikom alternatywnych metod wprowadzania, takich jak klawiatura ekranowa lub rozpoznawanie mowy. Po zainstalowaniu IME użytkownik może wybrać go w ustawieniach systemu i używać w całym systemie. Można włączyć tylko jeden edytor IME naraz.
Aby dodać metodę IME do systemu Androida, 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ż zdefiniować interfejs ustawień wyświetlany w ramach ustawień systemu.
Na tej stronie znajdziesz informacje na te tematy:
- Cykl życia IME
- Deklarowanie komponentów IME w pliku manifestu aplikacji
- Interfejs IME API
- Projektowanie interfejsu IME
- Wysyłanie tekstu z klawiatury IME do aplikacji
- Praca z podtypami IME
- Inne kwestie związane z 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 interfejsu IME:
W następnych sekcjach opisujemy, jak zaimplementować interfejs użytkownika i kod powiązany z IME, który przestrzega tego cyklu życia.
Deklarowanie komponentów IME w pliku manifestu
W systemie Android interfejs IME to aplikacja na Androida zawierająca specjalną usługę IME. Plik manifestu aplikacji musi deklarować usługę, prosić o wymagane uprawnienia, podawać filtr intencji pasujący do działania action.view.InputMethod
oraz metadane określające cechy IME. Aby zapewnić użytkownikowi interfejs ustawień, który umożliwia modyfikowanie działania IME, możesz zdefiniować aktywność „ustawienia”, którą można uruchomić z Ustawień systemu.
Poniższy fragment kodu deklaruje usługę IME. Usługa prosi o uprawnienie
BIND_INPUT_METHOD
do umożliwienia połączenia usługi z IME z systemem, konfiguruje filtr intencji dopasowujący się do działania
android.view.InputMethod
i definiuje metadane 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 kodu deklaruje aktywność ustawień dla IME. Zawiera ona filtr intencji ACTION_MAIN
, który wskazuje, że ta aktywność jest głównym punktem wejścia do 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 przeznaczone do IME znajdziesz w pakietach android.inputmethodservice
i android.view.inputmethod
. Klasa KeyEvent
jest ważna do obsługi znaków na klawiaturze.
Centralną częścią IME jest komponent usługi – klasa, która rozszerza InputMethodService
. Oprócz implementowania normalnego cyklu życia usługi ta klasa zawiera metody wywołania zwrotnego, które umożliwiają wyświetlanie interfejsu użytkownika IME, obsługę danych wejściowych użytkownika i przekazywanie tekstu do pola, które ma fokus. 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.
Te zajęcia są też ważne:
BaseInputConnection
- Określa kanał komunikacji z poziomu
InputMethod
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 wyświetla klawiaturę i reaguje na zdarzenia wejściowe użytkownika. Układ klawiatury jest określony za pomocą instancjiKeyboard
, którą można zdefiniować w pliku XML.
Projektowanie UI metody wprowadzania
W przypadku IME są 2 główne elementy wizualne: widok wejściowy i widok kandydatów. Musisz zaimplementować tylko te elementy, które są istotne dla projektowanej metody wprowadzania danych.
Widok danych wejściowych
Widok wprowadzania danych to interfejs, w którym użytkownik wprowadza tekst w postaci kliknięć klawiszy, pisma odręcznego lub gestów. Gdy interfejs IME jest wyświetlany po raz pierwszy, system wywołuje funkcję onCreateInputView()
. W ramach implementacji tej metody utwórz układ, który ma być wyświetlany w oknie IME, i zwróć go do systemu. Ten fragment kodu pokazuje 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
jest instancją niestandardowej implementacji funkcji KeyboardView
, która renderuje element Keyboard
.
Widok kandydatów
Widok kandydatów to interfejs, w którym IME wyświetla potencjalne poprawki lub sugestie słów do wybrania przez użytkownika. W cyklu życia IME system wywołuje funkcję onCreateCandidatesView()
, gdy jest gotowy do wyświetlenia widoku kandydatów. W implementacji tej metody zwracaj układ, który wyświetla sugestie słów, lub zwracaj null, jeśli nie chcesz wyświetlać niczego. Domyślną wartością jest odpowiedź null, więc nie musisz jej implementować, jeśli nie podajesz żadnych sugestii.
Uwagi dotyczące projektowania interfejsu użytkownika
W tej sekcji opisano niektóre kwestie związane z projektowaniem interfejsu użytkownika w przypadku interfejsów IME.
Obsługa wielu rozmiarów ekranu
Interfejs IME musi się skalować do różnych rozmiarów ekranu i działać w orientacji poziomej i pionowej. 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łnego ekranu w IME nie ma tego problemu.
Obsługa różnych typów danych wejściowych
Pola tekstowe na Androidzie umożliwiają ustawienie konkretnego typu danych, np. tekstu, liczb, adresów URL, adresów e-mail i ciągów wyszukiwania. Podczas implementowania nowego IME wykryj typ danych w każdym polu i zapewnij odpowiedni interfejs. Nie musisz jednak konfigurować IME, aby sprawdzić, czy użytkownik wpisuje prawidłowy tekst dla danego typu danych wejściowych. Jest to odpowiedzialność aplikacji, która jest właścicielem pola tekstowego.
Oto na przykład interfejs, który zapewnia układ klawiatury łacińskiej na platformie Android do wprowadzania tekstu:
A oto interfejs udostępniany przez Latin IME do wprowadzania liczbowych danych na platformie Androida:
Gdy pole tekstowe zostanie zaznaczone i uruchomiony zostanie IME, system wywołuje funkcję onStartInputView()
, przekazując obiekt EditorInfo
, który zawiera informacje o typie danych i innych atrybutach pola tekstowego. W tym obiekcie pole inputType
zawiera typ danych pola tekstowego.
Pole inputType
to int
, które zawiera wzorce bitów dla różnych ustawień typu danych wejściowych. Aby przetestować typ danych pola tekstowego, zamaskuj go za pomocą stałej TYPE_MASK_CLASS
, na przykład:
Kotlin
inputType and InputType.TYPE_MASK_CLASS
Java
inputType & InputType.TYPE_MASK_CLASS
Wzór bitów typu danych wejściowych może mieć jedną z tych wartości:
TYPE_CLASS_NUMBER
- Pole tekstowe do wpisywania liczb. Jak widać na rysunku 3, w przypadku pól tego typu klawiatura łacińska wyświetla blok numeryczny.
TYPE_CLASS_DATETIME
- Pole tekstowe do wpisania daty i godziny.
TYPE_CLASS_PHONE
- Pole tekstowe do wpisywania numerów telefonów.
TYPE_CLASS_TEXT
- Pole tekstowe do wpisywania dowolnych obsługiwanych znaków.
Te stałe są opisane bardziej szczegółowo w dokumentacji referencyjnej dotyczącej InputType
.
Pole inputType
może zawierać inne bity wskazujące wariant typu pola tekstowego, takie jak:
TYPE_TEXT_VARIATION_PASSWORD
- Wariant pola
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
TYPE_CLASS_TEXT
służący do wprowadzania tekstu, który aplikacja automatycznie uzupełnia na podstawie słownika, wyszukiwania lub innej funkcji.
Podczas testowania tych wariantów maskuj inputType
za pomocą odpowiedniej stałej. Dostępne stałe maski są wymienione w dokumentacji referencyjnej InputType
.
Wysyłanie tekstu do aplikacji
Gdy użytkownik wprowadza tekst za pomocą IME, możesz wysyłać tekst do aplikacji, wysyłając pojedyncze zdarzenia naciśnięcia klawisza lub edytując tekst wokół kursora w polu tekstowym aplikacji. W obu przypadkach do przesyłania tekstu użyj instancji InputConnection
. Aby uzyskać tę instancję, zadzwoń pod numer
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
zawierający liczbę żądanych znaków po bieżącej pozycji kursora. -
deleteSurroundingText()
- Usuwa określoną liczbę znaków przed bieżącą pozycją kursora i po niej.
-
commitText()
- Zapisuje
CharSequence
w polu tekstowym i ustala 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 Twój system IME przewiduje tekst lub wymaga kilku kroków do ułożenia znaku lub słowa, możesz wyświetlać postęp w polu tekstowym, dopóki użytkownik nie zapisze słowa, a potem zastąpić częściową kompozycję pełnym 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 ma wyraźnego punktu skupienia, jako pierwsze odbiera zdarzenia związane z klawiszami sprzętowymi i może je przetwarzać lub przekazywać do aplikacji. Możesz na przykład używać klawiszy kierunkowych do poruszania się po interfejsie podczas tworzenia kompozycji. Możesz też przechwycić klawisz Wstecz, aby zamknąć wszystkie okna dialogowe pochodzące z okna metody wprowadzania.
Aby przechwycić klucze sprzętowe, zastąpij je kluczami onKeyDown()
i onKeyUp()
.
Wywołuj metodę super()
w przypadku kluczy, którymi nie chcesz się zajmować samodzielnie.
Tworzenie podtypu IME
Podtypy umożliwiają IME udostępnianie wielu trybów wprowadzania i języków obsługiwanych przez IME. Podtyp może reprezentować:
- język, np. pl_PL lub en_US;
- tryb wprowadzania, np. głos, klawiatura lub pismo odręczne;
- inne style, formaty lub właściwości związane z IME, takie jak układy klawiatur 10-klawiszowych lub QWERTY;
Tryb może być dowolnym tekstem, np. „klawiatura” lub „głos”. Podtyp może też zawierać kombinację tych typów.
Informacje o podtypie są używane w oknie przełącznika IME dostępnym na pasku powiadomień oraz w ustawieniach IME. Informacje te umożliwiają też frameworkowi wyświetlenie konkretnego podtypu IME bezpośrednio. 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.
Definiowanie podtypów w jednym z plików zasobu XML metody wprowadzania za pomocą elementu <subtype>
. Ten fragment kodu definiuje IME z 2 podtypami: podtyp klawiatury dla lokalizacji angielskiej (amerykańskiej) i inny podtyp klawiatury dla lokalizacji francuskiej we Francji:
<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 opisane w interfejsie, użyj parametru „%s”, aby uzyskać etykietę podtypu, która jest taka sama jak etykieta lokalizacji podtypu. Pokazuje to 2 kolejne fragmenty kodu. Pierwszy fragment kodu pokazuje część pliku XML metody wprowadzania:
<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 tekstowego label_subtype_generic
, który jest używany przez definicję interfejsu metody wprowadzania do ustawienia 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 języka. Na przykład w przypadku dowolnej wersji językowej angielskiego wyświetlana nazwa to „English (United States)”.
Wybieranie podtypów metody wprowadzania za pomocą okna powiadomień
System Android zarządza wszystkimi podtypami udostępnianymi przez wszystkie 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 dostępnych podtypów IME, jak pokazano na tym rysunku:
Wybieranie podtypów IME w ustawieniach systemu
Użytkownik może też kontrolować sposób używania podtypów w panelu ustawień Język i wprowadzanie w ustawieniach systemu:
przełączać się między typami IME,
Możesz umożliwić użytkownikom łatwe przełączanie się między typami IME, udostępniając klawisz przełączania, np. ikonę języka w kształcie kuli ziemskiej na klawiaturze. Ułatwia to korzystanie z klawiatury i jest wygodne dla użytkownika. Aby włączyć tę funkcję, wykonaj te czynności:
- Zadeklaruj
supportsSwitchingToNextInputMethod = "true"
w plikach zasobów XML metody wprowadzania. 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 zwróci wartość true, 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 wskazuje, że system ma traktować wszystkie podtypy w ten sam sposób, niezależnie od tego, do jakiego IME należą. Ustawienie wartości „true” (prawda) wymaga, aby system przełączał się między podtypami w bieżącym edytorze IME.
Ogólne uwagi dotyczące IME
Oto inne kwestie, które warto wziąć pod uwagę podczas wdrażania IME:
- Umożliw użytkownikom ustawianie opcji bezpośrednio w interfejsie IME.
- Zapewnij użytkownikom możliwość przełączenia się na inną metodę wprowadzania bezpośrednio w interfejsie metody wprowadzania, ponieważ na urządzeniu może być zainstalowanych kilka metod.
- Szybkie wyświetlanie interfejsu IME. Wstępne wczytywanie lub wczytywanie na żądanie dużych zasobów, aby użytkownicy widzieli IME, gdy tylko klikną pole tekstowe. Zapisywanie w pamięci podręcznej zasobów i widoków na potrzeby kolejnych wywołań metody wprowadzania.
- 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, aby zwolnić zasoby, jeśli IME jest ukryty przez kilka sekund.
- Upewnij się, że użytkownicy mogą wpisywać jak najwięcej znaków w języku lub regionie powiązanym z IME. Użytkownicy mogą używać znaków interpunkcyjnych w hasłach lub nazwach użytkowników, dlatego Twoja metoda wprowadzania musi zawierać wiele różnych znaków, aby umożliwić użytkownikom wpisywanie hasła i dostęp do urządzenia.