Obsługa widoczności metody wprowadzania

Gdy zaznaczenie zostanie przeniesione do edytowalnego pola tekstowego lub poza nim, Android wyświetli lub ukryje dane wejściowe (np. klawiaturę ekranową) odpowiednio do potrzeb. System decyduje też, w jaki sposób interfejs i pole tekstowe mają się wyświetlać nad metodą wprowadzania. Jeśli na przykład przestrzeń pionowa na ekranie jest ograniczona, pole tekstowe może wypełnić całą przestrzeń nad metodą wprowadzania.

W przypadku większości aplikacji potrzeba tylko tych domyślnych działań. W niektórych przypadkach możesz jednak potrzebować większej kontroli nad widocznością metody wprowadzania i jej wpływem na układ. Z tej lekcji dowiesz się, jak kontrolować widoczność metody wprowadzania i reagować na nią.

Pokazuj klawiaturę programową po rozpoczęciu aktywności

Chociaż Android w momencie rozpoczęcia aktywności podświetla pierwsze pole tekstowe w układzie, nie pojawia się klawiatura programowa. Takie działanie jest odpowiednie, bo wpisywanie tekstu może nie być głównym zadaniem w aktywności. Jeśli jednak wprowadzanie tekstu jest rzeczywiście głównym zadaniem, na przykład na ekranie logowania, prawdopodobnie chcesz, by klawiatura programowa była wyświetlana domyślnie.

Aby wyświetlić metodę wprowadzania po rozpoczęciu aktywności, dodaj atrybut android:windowSoftInputMode do elementu <activity> z wartością "stateVisible". Na przykład:

<application ... >
    <activity
        android:windowSoftInputMode="stateVisible" ... >
        ...
    </activity>
   ...
</application>

Określ, jak powinien reagować interfejs użytkownika

Gdy na ekranie pojawia się klawiatura programowa, zmniejsza się ilość miejsca dostępnego w interfejsie aplikacji. System decyduje, jak dostosować widoczną część UI, ale może to nie zadziałać. Aby zapewnić najlepsze działanie aplikacji, określ, jak system ma wyświetlać interfejs w pozostałej przestrzeni.

Aby zadeklarować preferowane traktowanie w aktywności, użyj atrybutu android:windowSoftInputMode w elemencie <activity> pliku manifestu z jedną z wartości dostosowania.

Aby na przykład system mógł zmienić rozmiar układu do dostępnego miejsca – dzięki czemu wszystkie treści układu będą dostępne, nawet jeśli wymagane jest przewijanie – użyj "adjustResize":

<application ... >
   <activity
       android:windowSoftInputMode="adjustResize" ... >
       ...
   </activity>
   ...
</application>

Specyfikację dostosowania możesz połączyć ze specyfikacją wstępnej widoczności klawiatury programowej z poprzedniej sekcji:

<activity
    android:windowSoftInputMode="stateVisible|adjustResize" ... >
    ...
</activity>

Określenie "adjustResize" jest ważne, jeśli interfejs zawiera elementy sterujące, do których użytkownik może potrzebować dostępu bezpośrednio po wprowadzeniu tekstu lub w trakcie jego wykonywania. Jeśli na przykład użyjesz układu względnego, aby umieścić pasek przycisków u dołu ekranu, użycie "adjustResize" zmieni rozmiar układu, tak aby pasek przycisków był widoczny nad klawiaturą programową.

Pokaż klawiaturę ekranową na żądanie

Jeśli w cyklu życia aktywności występuje metoda, która sprawia, że ta metoda jest widoczna, możesz ją pokazać za pomocą metody InputMethodManager.

Na przykład ta metoda pobiera obiekt View, w którym użytkownik powinien coś wpisać, wywołuje metodę requestFocus(), by aktywować metodę wprowadzania, a następnie showSoftInput() otwiera metodę:

Kotlin

fun showSoftKeyboard(view: View) {
   if (view.requestFocus()) {
       val imm = getSystemService(InputMethodManager::class.java)
       imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)
   }
}

Java

public void showSoftKeyboard(View view) {
   if (view.requestFocus()) {
       InputMethodManager imm = getSystemService(InputMethodManager.class);
       imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
   }
}

Niezawodne wyświetlanie klawiatury programowej

W pewnych sytuacjach, na przykład po rozpoczęciu aktywności, użycie klawiatury programowej InputMethodManager.showSoftInput() może spowodować, że klawiatura programowa nie będzie widoczna dla użytkownika.

Widoczność klawiatury programowej w przypadku korzystania z showSoftInput() zależy od tych warunków:

  • Widok musi być już połączony z klawiaturą programową. To z kolei wymaga zaznaczenia okna i żądania zaznaczenia widoku edytora za pomocą View.requestFocus().

  • Na widoczność mogą też wpływać atrybuty android:windowSoftInputMode i flagi używane przez showSoftInput().

W pewnych przypadkach użycia, na przykład przy rozpoczęciu działania, wymagane warunki nie są spełnione. System nie uznaje widoku za połączony z klawiaturą programową, ignoruje wywołanie showSoftInput(), a klawiatura programowa nie jest widoczna dla użytkownika.

Aby upewnić się, że klawiatura programowa jest prawidłowo wyświetlana, możesz skorzystać z tych rozwiązań:

  • (Zalecane) Użyj aplikacji WindowInsetsControllerCompat. Ten obiekt wyświetla klawiaturę programową w trakcie Activity.onCreate(), jak widać w tym fragmencie kodu. Połączenie z pewnością zostanie zaplanowane po zaznaczeniu okna.

Kotlin

editText.requestFocus()
WindowCompat.getInsetsController(window, editText)!!.show(WindowInsetsCompat.Type.ime())

Java

editText.requestFocus();
WindowCompat.getInsetsController(getWindow(), editText).show(WindowInsetsCompat.Type.ime());

Kotlin

class MyEditText : EditText() {
  ...
  override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
    if (hasWindowFocus) {
      requestFocus()
      post {
        val imm: InputMethodManager = getSystemService(InputMethodManager::class.java)
        imm.showSoftInput(this, 0)
      }
    }
  }
}

Java

public class MyEditText extends EditText {
  ...
  @Override
  public void onWindowFocusChanged(boolean hasWindowFocus) {
    if (hasWindowFocus) {
      requestFocus();
      post(() -> {
        InputMethodManager imm = getSystemService(InputMethodManager.class);
        imm.showSoftInput(this, 0);
      });
    }
  }
}

Ostrożnie obchodź się z flagami widoczności w czasie działania aplikacji

Gdy przełączasz widoczność klawiatury programowej w czasie działania, uważaj, by nie przekazywać niektórych wartości flag do tych metod. Jeśli na przykład aplikacja oczekuje, że podczas uruchamiania działania Activity.onCreate() wyświetli się klawiatura programowa, programiści powinni uważać, by nie ustawiać flag SOFT_INPUT_STATE_HIDDEN ani SOFT_INPUT_STATE_ALWAYS_HIDDEN podczas pierwszego uruchomienia – na wypadek niespodziewanego ukrycia klawiatury programowej.View.getWindowInsetsController().show(ime())

System zwykle automatycznie ukrywa klawiaturę programową

W większości przypadków system ukrywa klawiaturę programową. Może to być dowolny z tych przypadków:

  • Użytkownik kończy zadanie w polu tekstowym.
  • Użytkownik naciska klawisz Wstecz lub gesty przesuwania w ramach nawigacji Wstecz.
  • Użytkownik przechodzi do innej aplikacji, która ustawi flagi SOFT_INPUT_STATE_HIDDEN lub SOFT_INPUT_STATE_ALWAYS_HIDDEN, gdy dany widok zyskuje fokus.

Ukryj klawiaturę programową ręcznie na podstawie poprzedniego działania systemu

W niektórych sytuacjach klawiatura programowa musi być ręcznie ukrywana przez aplikację, na przykład gdy pole tekstowe przestanie być aktywne w View.OnFocusChangeListener.onFocusChange. Tę metodę należy stosować rozważnie. Zamknięcie klawiatury programowej może nieoczekiwanie negatywnie wpłynąć na wrażenia użytkownika.

Jeśli aplikacja ręcznie ukrywa klawiaturę programową, musisz sprawdzić, czy została ona wyświetlona wyraźnie, czy niejasno:

  • Uznaje się, że klawiatura programowa została wyświetlona wyraźnie po wywołaniu funkcji showSoftInput().

  • I na odwrót, uznaje się, że klawiatura programowa została niejawnie pokazana w jednym z tych warunków:

    • Podczas stosowania klawisza android:windowSoftInputMode system pokazywał klawiaturę programową.
    • Twoja aplikacja przeszła SHOW_IMPLICIT do showSoftInput().

Normalnie hideSoftInputFromWindow() ukrywa klawiaturę programową niezależnie od jej żądania, ale w przypadku HIDE_IMPLICIT_ONLY może ograniczać się tylko do zamknięcia klawiatury programowej, o którą prosisz.

Pokaż widok okna lub nakładki na klawiaturze programowej

W niektórych przypadkach działanie edytora może wymagać utworzenia na górze klawiatury programowej nieedytowalnego okna lub nakładki.

Aplikacja ma kilka opcji, które opisujemy w sekcjach poniżej.

Podsumowując, zadbaj o prawidłową obsługę flag okna kierowanego na okno klawiatury programowej, tak by spełniała ona te oczekiwania co do kolejności w pionie (warstwa Z):

  • Brak flag (normalne wielkość liter): znajduje się za warstwą klawiatury programowej, ale umożliwia odbieranie tekstu.
  • FLAG_NOT_FOCUSABLE: znajduje się nad warstwą klawiatury programowej, ale nie może odbierać tekstu.
  • FLAG_ALT_FOCUSABLE_IM: użytkownik może zaznaczyć obszar, na którym znajduje się klawiatura programowa, ale nie jest podłączony do klawiatury programowej. Blokuje też wszystkie widoki pod nim, tak aby nie można było ich połączyć z klawiaturą programową. Przydaje się to do pokazywania okna aplikacji, w którym nad warstwą klawiatury programowej nie jest używane wprowadzanie tekstu.
  • FLAG_NOT_FOCUSABLE i FLAG_ALT_FOCUSABLE_IM: znajduje się za warstwą klawiatury programowej, ale nie może odbierać tekstu.
  • FLAG_NOT_FOCUSABLE i FLAG_NOT_TOUCH_MODAL: góra ekranu klawiatury programowej i zezwól na przechodzenie zdarzeń dotyku przez okno do klawiatury programowej.

Utwórz okno

Użyj flagi okna dialogowego FLAG_ALT_FOCUSABLE_IM, aby ułożyć okno nad klawiaturą programową i uniemożliwić jej zaznaczanie:

Kotlin

val content = TextView(this)
content.text = "Non-editable dialog on top of soft keyboard"
content.gravity = Gravity.CENTER
val builder = AlertDialog.Builder(this)
  .setTitle("Soft keyboard layering demo")
  .setView(content)
mDialog = builder.create()
mDialog!!.window!!
  .addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM)
mDialog!!.show()

Java

TextView content = new TextView(this);
content.setText("Non-editable dialog on top of soft keyboard");
content.setGravity(Gravity.CENTER);
final AlertDialog.Builder builder = new AlertDialog.Builder(this)
    .setTitle("Soft keyboard layering demo")
    .setView(content);
mDialog = builder.create();
mDialog.getWindow().addFlags(FLAG_ALT_FOCUSABLE_IM);
mDialog.show();

Tworzenie widoku nakładki

Utwórz widok nakładki, określając typ okna TYPE_APPLICATION_OVERLAY i flagę okna FLAG_ALT_FOCUSABLE_IM według działania kierowanego z klawiatury programowej.

Kotlin

val params = WindowManager.LayoutParams(
  width,  /* Overlay window width */
  height,  /* Overlay window height */
  WindowManager.LayoutParams.TYPE_APPLICATION, /* Overlay window type */
  WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM /* No need to allow for text input on top of the soft keyboard */
    or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,  /* Allow touch event send to soft keyboard behind the overlay */
  PixelFormat.TRANSLUCENT
)
params.title = "Overlay window"
mOverlayView!!.layoutParams = params
windowManager.addView(mOverlayView, params)

Java

WindowManager.LayoutParams params = new WindowManager.LayoutParams(
    width, /* Overlay window width */
    height, /* Overlay window height */
    TYPE_APPLICATION, /* Overlay window type */
    FLAG_ALT_FOCUSABLE_IM /* No need to allow for text input on top of the soft keyboard */
        | FLAG_NOT_TOUCH_MODAL, /* Allow touch event send to soft keyboard behind the overlay */
    PixelFormat.TRANSLUCENT);
params.setTitle("Overlay window");
mOverlayView.setLayoutParams(params);
getWindowManager().addView(mOverlayView, params);

Pokaż okno lub widok pod klawiaturą programową

W aplikacji może być konieczne utworzenie okna lub okna z tymi właściwościami:

  • Wyświetla się pod klawiaturą programową żądaną przez działanie edytora, dzięki czemu wprowadzanie tekstu nie ma na niego wpływu.
  • Użytkownik pamięta o zmianach rozmiaru klawiatury programowej w celu dostosowania układu okna lub okna.

W takim przypadku aplikacja ma kilka opcji. Opisy tych opcji znajdziesz w sekcjach poniżej.

Utwórz okno

Utwórz okno, ustawiając flagę okna FLAG_NOT_FOCUSABLE i flagę okna FLAG_ALT_FOCUSABLE_IM:

Kotlin

val content = TextView(this)
content.text = "Non-editable dialog behind soft keyboard"
content.gravity = Gravity.CENTER
val builder = AlertDialog.Builder(this)
  .setTitle("Soft keyboard layering demo")
  .setView(content)
mDialog = builder.create()
mDialog!!.window!!
  .addFlags(FLAG_NOT_FOCUSABLE or FLAG_ALT_FOCUSABLE_IM)
mDialog!!.show()

Java

TextView content = new TextView(this);
content.setText("Non-editable dialog behind soft keyboard");
content.setGravity(Gravity.CENTER);
final AlertDialog.Builder builder = new AlertDialog.Builder(this)
    .setTitle("Soft keyboard layering demo")
    .setView(content);

mDialog = builder.create();
mDialog.getWindow()
    .addFlags(FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);
mDialog.show();

Tworzenie widoku nakładki

Utwórz widok nakładki, ustawiając flagę okna FLAG_NOT_FOCUSABLE i flagę okna FLAG_ALT_FOCUSABLE_IM:

Kotlin

val params = WindowManager.LayoutParams(
  width,  /* Overlay window width */
  height,  /* Overlay window height */
  WindowManager.LayoutParams.TYPE_APPLICATION,  /* Overlay window type */
  WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
      or WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
  PixelFormat.TRANSLUCENT
)
params.title = "Overlay window"
mOverlayView!!.layoutParams = params
windowManager.addView(mOverlayView, params)

Java

WindowManager.LayoutParams params = new WindowManager.LayoutParams(
    width, /* Overlay window width */
    height, /* Overlay window height */
    TYPE_APPLICATION, /* Overlay window type */
    FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM,
    PixelFormat.TRANSLUCENT);
params.setTitle("Overlay window");
mOverlayView.setLayoutParams(params);
getWindowManager().addView(mOverlayView, params);