Cómo controlar la visibilidad del método de entrada

Cuando el enfoque de entrada se mueve dentro o fuera de un campo de texto editable, Android muestra o oculta la entrada (como el teclado en pantalla) como lo que sea apropiado. El sistema también decide cómo aparecen tu IU y el campo de texto arriba. el método de entrada. Por ejemplo, cuando el espacio vertical en la pantalla está restringido, el campo de texto podría rellenar todo el espacio por encima del método de entrada.

Para la mayoría de las apps, estos comportamientos predeterminados son todo lo que se necesita. En algunos casos, pero tal vez quieras tener más control sobre la visibilidad del método de entrada y cómo influye en el diseño. Esta lección explica cómo controlar y responder a la visibilidad del método de entrada.

Mostrar el teclado en pantalla cuando comienza la actividad

Si bien Android enfoca el primer campo de texto de tu diseño cuando antes de comenzar la actividad, esta no muestra el teclado en pantalla. Este comportamiento es apropiado ya que ingresar texto podría no ser la tarea principal en la actividad. Sin embargo, si ingresar texto es la tarea principal, por ejemplo, en una pantalla de acceso, entonces es probable que quieras que el teclado en pantalla aparezca de forma predeterminada.

Para mostrar el método de entrada cuando comienza tu actividad, agrega la el atributo android:windowSoftInputMode al elemento <activity> con el valor "stateVisible". Por ejemplo:

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

Especifica cómo debe responder tu IU

Cuando el teclado en pantalla aparece en la pantalla, se reduce la cantidad de espacio disponibles para la IU de tu app. El sistema decide cómo ajustar el flujo visible de la IU, pero es posible que no funcione correctamente. Para garantizar el mejor comportamiento para tu app, especifica cómo quieres que el sistema muestre tu IU en la espacio restante.

Para declarar tu tratamiento preferido en una actividad, usa la El atributo android:windowSoftInputMode en el elemento <activity> de tu manifiesto con uno de los comandos de salida.

Por ejemplo, para asegurarte de que el sistema cambie el tamaño de tu diseño a los servicios espacio, que mantiene accesible todo el contenido del diseño, incluso si requiere desplazamiento; usa "adjustResize":

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

Puedes combinar la especificación de ajuste con el teclado en pantalla inicial. visibilidad de la sección anterior:

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

Especificar "adjustResize" es importante si tu IU incluye controles que el el usuario podría necesitar acceder inmediatamente después o mientras realiza una entrada de texto. Para Por ejemplo, si usas un diseño relativo para colocar una barra de botones en la parte inferior de la pantalla, con "adjustResize", se cambia el tamaño del diseño para que aparezca la barra de botones. sobre el teclado en pantalla.

Muestra el teclado en pantalla a pedido

Si hay un método en el ciclo de vida de tu actividad en el que quieras asegurarte de que el método de entrada es visible, puedes usar InputMethodManager para mostrarla.

Por ejemplo, el siguiente método toma un View en el que se espera que el usuario escribe algo, llama requestFocus() para otorgarlo enfoque y, luego, llama a showSoftInput() para abrir el método de entrada:

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);
   }
}

Cómo mostrar el teclado en pantalla de manera confiable

Hay ciertas situaciones, como cuando se inicia una actividad, en las que usar InputMethodManager.showSoftInput() para mostrar el teclado en pantalla es posible que el usuario no pueda ver el teclado en pantalla.

La visibilidad del teclado en pantalla cuando se usa showSoftInput() depende de según las siguientes condiciones:

  • La vista ya debe estar conectada al teclado en pantalla. (Esto, a su vez, requiere que se enfoque la ventana y que el editor vista para solicitar el foco de la vista con View.requestFocus()).

  • La visibilidad también puede verse afectada por el android:windowSoftInputMode y las marcas que usa showSoftInput().

En algunos casos de uso, como cuando se inicia una actividad, algunos de estos si no se cumplen las condiciones necesarias. El sistema no considera la vista como conectado al teclado en pantalla, ignora la llamada showSoftInput(), y el teclado en pantalla no es visible para el usuario.

Para asegurarte de que el teclado en pantalla se muestre de manera confiable, puedes usar el siguiente alternativas:

  • Usa WindowInsetsControllerCompat(recomendado). Este objeto muestra el teclado en pantalla durante Activity.onCreate(), como se indica en el siguiente fragmento de código. Se garantiza que la llamada se programará después del período establecido. está enfocado.

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);
      });
    }
  }
}

Maneja cuidadosamente las marcas de visibilidad del tiempo de ejecución

Cuando actives la visibilidad del teclado en pantalla durante el tiempo de ejecución, ten cuidado de no pasar ciertas marcar valores en estos métodos. Por ejemplo, si la aplicación espera que el teclado en pantalla aparece cuando llamas View.getWindowInsetsController().show(ime()) en Activity.onCreate() durante se inicia la actividad, los desarrolladores de la aplicación deben tener cuidado de no establecer Marcas SOFT_INPUT_STATE_HIDDEN o SOFT_INPUT_STATE_ALWAYS_HIDDEN durante el lanzamiento inicial, en caso de que el teclado en pantalla se oculte de forma inesperada.

Por lo general, el sistema oculta el teclado en pantalla automáticamente

En la mayoría de las situaciones, el sistema se encarga de ocultar el teclado en pantalla. Esta puede ser cualquiera de los siguientes casos:

  • El usuario finaliza la tarea en el campo de texto.
  • El usuario presiona la tecla de retroceso o los gestos de deslizamiento con la navegación hacia atrás.
  • El usuario navega a otra app y esa otra app configuró Marcas SOFT_INPUT_STATE_HIDDEN o SOFT_INPUT_STATE_ALWAYS_HIDDEN cuando la vista se enfoca.

Ocultar el teclado en pantalla manualmente según el comportamiento anterior del sistema

Tu app debe ocultar el teclado en pantalla de forma manual en algunas situaciones (por ejemplo, ejemplo, cuando el campo de texto pierde el foco en View.OnFocusChangeListener.onFocusChange Usa esta técnica con cuidado. ; cerrar el teclado en pantalla de forma inesperada afecta la experiencia del usuario.

Si tu app oculta el teclado en pantalla de forma manual, debes saber si El teclado en pantalla se mostró explícitamente o implícita:

  • Se considera que el teclado en pantalla se mostró de forma explícita después de una llamada a showSoftInput().

  • Por el contrario, se considera que el teclado en pantalla se mostró implícitamente en cualquiera de las siguientes condiciones:

Por lo general, hideSoftInputFromWindow() oculta el teclado en pantalla, independientemente de la cómo se solicitó, pero con HIDE_IMPLICIT_ONLY puede limitarse a descartar únicamente un teclado en pantalla solicitado implícitamente.

Mostrar un diálogo o una vista superpuesta sobre el teclado en pantalla

En algunos casos, es posible que la actividad del editor deba crear un archivo de diálogo o de superposición en la parte superior del teclado en pantalla.

Tu app tiene algunas opciones que se describen en las siguientes secciones.

En resumen, asegúrate de manejar correctamente las funciones experimentales de las ventanas del teclado en pantalla segmentar la ventana para satisfacer las siguientes expectativas con respecto al orden vertical (capa z):

  • Sin marcas (caso normal): Está detrás de la capa del teclado en pantalla y puede recibir texto.
  • FLAG_NOT_FOCUSABLE : Se encuentra sobre la capa del teclado en pantalla, pero no puede recibir texto.
  • FLAG_ALT_FOCUSABLE_IM : Encima de la capa del teclado en pantalla, puede enfocarse, pero no está conectado al teclado en pantalla. También bloquea todas las vistas inferiores para que no se conecten al teclado en pantalla. Esto es útil para mostrar un diálogo de la app que no usa texto. entrada por encima de la capa del teclado en pantalla.
  • FLAG_NOT_FOCUSABLE y FLAG_ALT_FOCUSABLE_IM : Está detrás de la capa del teclado en pantalla, pero no puede recibir texto.
  • FLAG_NOT_FOCUSABLE y FLAG_NOT_TOUCH_MODAL : Se ubica en la parte superior del teclado en pantalla, y permite que se realicen los eventos táctiles. la ventana al teclado en pantalla.

Crea un diálogo

Usa la FLAG_ALT_FOCUSABLE_IM. marca de ventana de diálogo para mantener el diálogo sobre el teclado en pantalla y para evita que el teclado en pantalla se enfoque:

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();

Cómo crear una vista superpuesta

Crea una vista superpuesta que especifique TYPE_APPLICATION_OVERLAY. tipo de ventana y FLAG_ALT_FOCUSABLE_IM de ventana por la actividad objetivo del teclado en pantalla.

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

Mostrar un diálogo o una vista debajo del teclado en pantalla

Es posible que tu app necesite crear un diálogo o una ventana con la siguientes propiedades:

  • Aparece debajo del teclado en pantalla solicitado por una actividad del editor de manera que no se vea afectada por la entrada de texto.
  • Permanece al tanto de los cambios en los cambios de tamaño de inserción del teclado en pantalla a ajustar el diseño del diálogo o la ventana.

En este caso, tu app tiene varias opciones. Las siguientes secciones describir estas opciones.

Crea un diálogo

Para crear un diálogo, configura FLAG_NOT_FOCUSABLE marca de ventana y FLAG_ALT_FOCUSABLE_IM marca de ventana:

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();

Cómo crear una vista superpuesta

Para crear una vista de superposición, configura FLAG_NOT_FOCUSABLE marca de ventana y FLAG_ALT_FOCUSABLE_IM marca de ventana:

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