Cómo agregar compatibilidad con el teclado, el mouse, el panel táctil y la pluma stylus con Jetpack Compose

1. Introducción

Tu app está disponible para dispositivos de pantalla grande (como tablets, plegables y dispositivos ChromeOS) cuando está disponible en teléfonos estándar.

Los usuarios esperan que tu app brinde una experiencia de usuario en pantallas grandes que sea igual o mejor que la UX en pantallas pequeñas.

También es más probable que los usuarios utilicen tu app con un teclado físico y un dispositivo apuntador (como un mouse o un panel táctil) en dispositivos con pantalla grande. Algunos dispositivos de pantalla grande, como las Chromebooks, incluyen un teclado físico y un dispositivo apuntador. Otras se conectan a teclados y dispositivos apuntadores USB o Bluetooth. Los usuarios esperan poder realizar las mismas tareas cuando usan tu app con un dispositivo apuntador y teclado físico que las que realizan con pantallas táctiles.

Requisitos previos

  • Experiencia en el desarrollo de apps con Compose
  • Conocimientos básicos de Kotlin, incluidas lambdas y corrutinas

Qué crearás

Agregarás compatibilidad con el mouse y los teclados físicos a una app basada en Jetpack Compose. Para ello, completarás los siguientes pasos:

  1. Verificar la app con los criterios definidos en los lineamientos de calidad de las apps para pantallas grandes
  2. Revisar el resultado de la auditoría y, luego, identificar los problemas relacionados con la compatibilidad con el mouse y teclado físicos
  3. Solucionar los problemas

Específicamente, actualizarás la app de ejemplo con lo siguiente:

  • Navegación con el teclado
  • Combinación de teclas para desplazarse hacia arriba y hacia abajo
  • Asistente de combinaciones de teclas

Qué aprenderás

  • Cómo auditar tu app para verificar la compatibilidad con dispositivos virtuales
  • Cómo administrar la navegación con el teclado con Compose
  • Cómo agregar combinaciones de teclas con Compose

Requisitos

  • Android Studio Hedgehog o una versión más reciente
  • Cualquiera de los siguientes dispositivos para ejecutar la app de ejemplo:
  • Un dispositivo de pantalla grande con un mouse y un teclado físicos
  • Un dispositivo virtual de Android con un perfil en la categoría de definición de dispositivo de escritorio

2. Configuración

  1. Clona el repositorio de GitHub de codelabs de pantallas grandes:
git clone https://github.com/android/large-screen-codelabs

Otra opción es descargar y desarchivar el archivo ZIP de codelabs de pantallas grandes:

Descargar código fuente

  1. Navega a la carpeta add-keyboard-and-mouse-support-with-compose.
  2. En Android Studio, abre el proyecto. La carpeta add-keyboard-and-cursor-support-with-compose contiene un proyecto.
  3. Si no tienes dispositivos plegables o una tablet Android, o bien un dispositivo ChromeOS con un teclado y mouse físicos, abre Device Manager en Android Studio y, luego, crea cualquiera de los dispositivos virtuales en la categoría de computadora de escritorio.

Dispositivos virtuales en la categoría Computadora de escritorio

3. Explora la app

La app de ejemplo muestra una lista de artículos. Los usuarios pueden leer un artículo seleccionado de la lista.

La app actualiza el diseño de manera adaptable según el ancho de la ventana de la app. Hay tres clases de ventanas para categorizar el ancho de la ventana de la app: compacta, mediana y expandida.

Clases de tamaño de ventana en el ancho de la ventana: compacta, mediana y expandida. Si la ventana de la app es menor de 600 dp, el ancho de la ventana se clasifica como compacto. El ancho de la ventana se categoriza como expandido cuando es mayor o igual que 640 dp. Si la ventana no pertenece a la clase compacta o expandida, el tamaño de la ventana es mediano.

Diseño para las clases de tamaño de ventana compacto y mediano

La app usa un diseño de panel único. En la pantalla principal, la app muestra una lista de artículos. Cuando el usuario selecciona un artículo de la lista, se produce una transición de pantalla y se muestra el artículo.

La navegación global se implementa con un panel lateral de navegación.

La app se está ejecutando en un emulador de computadora de escritorio, en una ventana compacta. Se muestra la lista de artículos.

Diseño para la clase de tamaño de ventana expandido

La app usa un diseño de lista-detalles. En el panel de lista, se muestra una lista de artículos. En el panel de detalles, se muestra el artículo seleccionado.

La navegación global se implementa con un riel de navegación.

La app se está ejecutando en un emulador de computadora de escritorio en la clase de tamaño de ventana expandido.

4. Información general

Compose proporciona una variedad de APIs para ayudar a tu app a controlar eventos desde el mouse y el teclado físicos. Algunas de las APIs permiten un control de eventos desde el teclado y mouse que es similar al control de eventos táctiles. Como resultado, para muchos casos de uso, tu app admite el teclado y mouse físicos sin necesidad de realizar ningún esfuerzo durante el desarrollo.

Un ejemplo típico es el modificador clickable, que permite la detección de clics. Se detecta una presión con el dedo como un clic. Un clic del mouse y presionar la tecla Enter también se detectan como clics. Tu app permite que los usuarios interactúen con los componentes, independientemente del dispositivo de entrada si la app detecta clics con el modificador clickable.

Sin embargo, a pesar del alto nivel de compatibilidad de APIs, igualmente se requiere cierto esfuerzo de desarrollo para la compatibilidad con el teclado y mouse físicos. Una de las razones es que necesitas probar tu app para descubrir los casos límite. También se requiere cierto esfuerzo para reducir la fricción del usuario que proviene de las características de los dispositivos, como los siguientes:

  • Los usuarios no entienden en qué componentes pueden hacer clic.
  • Los usuarios no pueden mover el enfoque del teclado como esperaban.
  • Los usuarios no pueden desplazarse hacia arriba ni hacia abajo cuando usan el teclado físico.

Enfoque del teclado

El enfoque del teclado es la diferencia principal entre la interacción con el teclado físico y los toques en la pantalla. Los usuarios pueden presionar cualquier componente en la pantalla, independientemente de la posición del componente que tocaron anteriormente. En cambio, con los teclados, los usuarios deben seleccionar el componente con el que interactuarán antes de que comience la interacción real. La selección se llama enfoque del teclado.

Los usuarios pueden mover el enfoque del teclado con la tecla Tab y las teclas de dirección (o flechas). El enfoque del teclado se mueve solo a los componentes vecinos de forma predeterminada.

La mayor parte de la fricción del teclado físico está relacionada con el enfoque del teclado. En la siguiente lista, se muestran los problemas típicos:

  • Los usuarios no pueden mover el enfoque del teclado al componente con el que quieren interactuar.
  • El componente no detecta clics cuando los usuarios presionan la tecla Enter.
  • El enfoque del teclado se mueve de manera diferente a las expectativas del usuario.
  • Los usuarios deben presionar muchas teclas para mover el enfoque del teclado al componente con el que desean interactuar después de las transiciones de pantalla.
  • Los usuarios no pueden determinar qué componente tiene el enfoque del teclado, ya que no hay señales visuales que lo indiquen.
  • Los usuarios no pueden determinar el componente predeterminado que tiene el enfoque cuando navegan a una pantalla nueva.

La indicación visual del enfoque del teclado es importante; de lo contrario, los usuarios pueden perderse en tu app y no entenderán lo que sucede cuando presionan la tecla Enter. El resaltado es una indicación visual típica para indicar el enfoque del teclado. Los usuarios pueden ver que el botón de la tarjeta de la derecha tiene el enfoque del teclado porque el botón está destacado.

53ee7662b764f2dd.png

Combinaciones de teclas

Los usuarios esperan poder usar combinaciones de teclas comunes cuando usan tu app con un teclado físico. Algunos componentes habilitan las combinaciones de teclas estándar de forma predeterminada. BasicTextField es un ejemplo típico. Permite que los usuarios usen combinaciones de teclas estándar para editar texto, incluidas las siguientes:

Combinación de teclas

Función

Ctrl+C

Copiar

Ctrl+X

Cortar

Ctrl+V

Pegar

Ctrl+Z

Deshacer

Ctrl+Y

Rehacer

Tu app puede agregar combinaciones de teclas controlando eventos de tecla. El modificador onKeyEvent y el modificador onPreviewKeyEvent te permiten supervisar los eventos de tecla.

Dispositivos apuntadores: Mouse, panel táctil y pluma stylus

Tu app puede controlar el mouse, el panel táctil y la pluma stylus de la misma manera. Cuando se presiona el panel táctil, se detecta un clic con el modificador clickable. Un toque con la pluma stylus también se detecta como un clic.

Es importante que los usuarios puedan comprender visualmente si pueden hacer clic en un componente o no. Por eso el estado de desplazamiento se menciona en los lineamientos de calidad de las apps para pantallas grandes.

Los componentes de Material 3 admiten el estado de desplazamiento del cursor de forma predeterminada. Material 3 ofrece el efecto visual para el estado de desplazamiento. Puedes aplicarlo a tu componente interactivo con el modificador indication.

Desplazamientos

Los contenedores desplazables admiten el desplazamiento de la rueda del mouse, los gestos de desplazamiento en el panel táctil y el desplazamiento con las teclas Page up y Page down de forma predeterminada.

Para el desplazamiento horizontal, tu app sería muy fácil de usar si mostrara los botones de flecha hacia la izquierda y la derecha en el estado de desplazamiento para que los usuarios puedan desplazarse por el contenido haciendo clic en los botones.

17feb4d3bf08831e.png

Cambios de configuración por conexión y desconexión de dispositivos

Los usuarios pueden conectar o desconectar un teclado y mouse mientras se ejecuta tu app. Los usuarios pueden conectar un teclado físico cuando ven un campo de texto para ingresar una gran cantidad de texto. Un mouse conectado por Bluetooth se desconecta cuando entra en modo de suspensión. Es posible que un teclado conectado por USB se desconecte por accidente.

La conexión o desconexión de hardware periférico activa cambios de configuración. Tu app debe conservar su estado durante los cambios de configuración. Para obtener más información, consulta Cómo guardar estados de la IU.

5. Verifica la app de ejemplo con el teclado y mouse

Para comenzar el esfuerzo de desarrollo para la compatibilidad con el teclado y mouse físicos, inicia la app de ejemplo y confirma lo siguiente:

  • Los usuarios deben poder mover el enfoque del teclado a todos los componentes interactivos.
  • Los usuarios deben poder "hacer clic" en el componente enfocado con la tecla Enter.
  • Los componentes interactivos deben mostrar una indicación cuando tienen el enfoque del teclado.
  • El enfoque del teclado se mueve como esperan los usuarios (es decir, según las convenciones establecidas) con la tecla Tab, Shift+Tab y las teclas direccionales (flechas).
  • Los componentes interactivos deben tener un estado de desplazamiento.
  • Los usuarios deben poder hacer clic en los componentes interactivos.
  • El menú contextual aparece haciendo clic con el botón derecho (clic con el botón secundario) en los componentes adecuados, como aquellos en los que el menú contextual aparece con un toque largo o una selección de texto.

Debes revisar todos los elementos dos veces en este codelab: una vez para el diseño de panel único y otra para el diseño de lista-detalles.

Problemas que se deben corregir en este codelab

Deberías encontrar problemas. En este codelab, corregirás lo siguiente:

  • Los usuarios no pueden leer el artículo completo solo con el teclado físico porque no pueden desplazarse hacia abajo por el artículo.
  • Los usuarios no pueden determinar si el panel de detalles tiene el enfoque del teclado o no.

6. Permite que los usuarios lean el artículo completo en el panel de detalles

En el panel de detalles, se muestra el artículo seleccionado. Algunos artículos son demasiado largos para leerlos por completo sin desplazarse. Sin embargo, los usuarios no pueden desplazarse hacia arriba ni hacia abajo por el artículo solo con el teclado físico.

4627289223e5cfbc.gif

Los contenedores desplazables, como LazyColumn, permiten a los usuarios desplazarse hacia abajo con la tecla Page down. La causa raíz del problema es que los usuarios no pueden mover el enfoque del teclado al panel de detalles.

El componente debe poder obtener el enfoque del teclado para recibir un evento de teclado. El modificador focusable permite que el componente modificado obtenga el enfoque del teclado.

Para solucionar el problema, completa los siguientes pasos:

  1. Accede a la función de componibilidad PostContent en el archivo ui/article/PostContent.kt.
  2. Modifica la función de componibilidad LazyColumn con el modificador focusable.
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PostContent(
    post: Post,
    modifier: Modifier = Modifier,
    contentPadding: PaddingValues = PaddingValues(0.dp),
    state: LazyListState = rememberLazyListState(),
    coroutineScope: CoroutineScope = rememberCoroutineScope(),
    focusRequester: FocusRequester = remember { FocusRequester() },
    header: (@Composable () -> Unit)? = null
) {
    LazyColumn(
        contentPadding = contentPadding,
        modifier = modifier
            .padding(horizontal = defaultSpacerSize)
            .focusable(),
        state = state,
    ) {
      // Code to layout the selected article.
    }
}

Indica que el artículo tiene el enfoque del teclado

Ahora los usuarios pueden leer el artículo completo desplazándose hacia abajo con la tecla Page down. Sin embargo, es difícil para ellos comprender si el componente PostContent tiene enfoque del teclado o no, ya que no lo indica ningún efecto visual.

Tu app puede indicar visualmente el enfoque del teclado si se asocia un Indication con los componentes. Una indicación crea un objeto para renderizar efectos visuales según las interacciones. Por ejemplo, la indicación predeterminada de Material 3 destaca el componente cuando tiene el enfoque del teclado.

La app de ejemplo tiene un Indication llamado BorderIndication. La indicación muestra una línea junto al componente que tiene el enfoque del teclado (como en la siguiente captura de pantalla). El código se almacena en el archivo ui/components/BorderIndication.kt.

Se muestra una línea gris clara al costado del artículo cuando este tiene el enfoque del teclado.

Para hacer que el elemento PostConent componible muestre el elemento BorderIndication cuando tiene el enfoque del teclado, completa los siguientes pasos:

  1. Accede a la función de componibilidad PostContent en el archivo ui/article/PostContent.kt.
  2. Declara el valor interactionSource que está asociado con el valor que se muestra de la función remember().
  3. Llama a la función MutableInteractionSource() en la función remember() para que el objeto MutableInteractionSource creado se asocie con el valor interactionSource.
  4. Pasa el valor interactionSource al modificador focusable con el parámetro interactionSource.
  5. Cambia el modificador del elemento PostContent componible para llamar al modificador focusable después de invocar al modificador indication.
  6. Pasa el valor interactionSource y el valor que se muestra de la función BorderIndication al modificador de la indicación.
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PostContent(
    post: Post,
    modifier: Modifier = Modifier,
    contentPadding: PaddingValues = PaddingValues(0.dp),
    state: LazyListState = rememberLazyListState(),
    coroutineScope: CoroutineScope = rememberCoroutineScope(),
    focusRequester: FocusRequester = remember { FocusRequester() },
    header: (@Composable () -> Unit)? = null
) {
    val interactionSource = remember { MutableInteractionSource() }

    LazyColumn(
        contentPadding = contentPadding,
        modifier = modifier
            .padding(horizontal = defaultSpacerSize)
            .indication(interactionSource, BorderIndication())
            .focusable(interactionSource = interactionSource),
        state = state,
    ) {
      // Code to layout the selected article.
    }
}

Agrega combinaciones de teclas para desplazarte hacia arriba y abajo

Es una función común que permite a los usuarios desplazarse hacia arriba y hacia abajo con el Spacebar. Tu app puede implementar la función agregando una combinación de teclas como las de la siguiente tabla:

Combinación de teclas

Función

Spacebar

Desplazarse hacia abajo en el artículo

Shift + Spacebar

Desplazarse hacia arriba en el artículo

El modificador onKeyEvent permite que tu app controle eventos de teclas que ocurren en un componente modificado. El modificador toma una expresión lambda que se llama con un objeto KeyEvent que describe el evento de tecla. La lambda debe mostrar un valor Boolean que indique si se consume el evento de tecla.

La posición de desplazamiento de un LazyColumn y LazyRow se captura en un objeto LazyListState. Tu app puede activar el desplazamiento llamando al método de suspensión animateScrollBy() en el objeto LazyListState. El método se desplaza por LazyColumn hacia abajo según la cantidad de píxeles especificada. Cuando se llama a la función de suspensión con un valor flotante negativo, la función se desplaza hacia arriba en LazyColumn.

Para implementar esas combinaciones de teclas, completa los siguientes pasos:

  1. Accede a la función de componibilidad PostContent en el archivo ui/article/PostContent.kt.
  2. Modifica la función de componibilidad LazyColumn con el modificador onKeyEvent.
  3. Agrega una expresión if a la expresión lambda pasada al modificador onKeyEvent de la siguiente manera:
  • Se muestra true si se cumplen las siguientes condiciones:
  • Se presiona Spacebar. Para detectarlo, prueba si el atributo type es KeyType.KeyDown y el atributo key es Key.Spacebar
  • El atributo isCtrlPressed es falso para garantizar que no se presione la tecla Ctrl
  • El atributo isAltPressed es falso para garantizar que no se presione la tecla Alt
  • El atributo isMetaPressed es falso para garantizar que no se presione la tecla Meta (consulta la nota)
  • De lo contrario, se mostrará false
  1. Determina el desplazamiento con la cantidad de Spacebar de la siguiente manera:
  • -0.4f cuando se presiona la tecla Shift, que describe el atributo isShiftPressed del objeto KeyEvent determinado
  • De lo contrario, 0.4f
  1. Llama al método launch() por medio de coroutineScope, que es un parámetro de la función de componibilidad PostContent
  2. Para calcular la cantidad real del desplazamiento, multiplica el importe de desplazamiento relativo calculado en el paso anterior y el atributo state.layoutInfo.viewportSize.height en el parámetro lambda del método launch. El atributo representa la altura de la LazyColumn que se llama en la función de componibilidad PostContent.
  3. Llama al método state.animateScrollBy() en la expresión lambda para que el método launch() active el desplazamiento vertical
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PostContent(
    post: Post,
    modifier: Modifier = Modifier,
    contentPadding: PaddingValues = PaddingValues(0.dp),
    state: LazyListState = rememberLazyListState(),
    coroutineScope: CoroutineScope = rememberCoroutineScope(),
    focusRequester: FocusRequester = remember { FocusRequester() },
    header: (@Composable () -> Unit)? = null
) {
    val interactionSource = remember { MutableInteractionSource() }

    LazyColumn(
        contentPadding = contentPadding,
        modifier = modifier
            .padding(horizontal = defaultSpacerSize)
            .onKeyEvent {
                if (
                    it.type == KeyEventType.KeyDown &&
                    it.key == Key.Spacebar &&
                    !it.isCtrlPressed &&
                    !it.isAltPressed &&
                    !it.isMetaPressed
                ) {

                    val relativeAmount = if (it.isShiftPressed) {
                        -0.4f
                    } else {
                        0.4f
                    }
                    coroutineScope.launch {
                        state.animateScrollBy(relativeAmount * state.layoutInfo.viewportSize.height)
                    }
                    true
                } else {
                    false
                }
            }
            .indication(interactionSource, BorderIndication())
            .focusable(interactionSource = interactionSource),
        state = state,
    ) {
      // Code to layout the selected article.
    }
}

Informa a los usuarios las combinaciones de teclas

Los usuarios no pueden aprovechar al máximo el teclado agregado, a menos que conozcan las combinaciones de teclas. Tu app puede permitir que los usuarios conozcan las combinaciones de teclas disponibles con el asistente de combinaciones de teclas, que forma parte de la IU del sistema Android. Los usuarios pueden abrir el asistente de combinaciones de teclas con Meta+/.

El asistente de combinaciones de teclas muestra las combinaciones que se agregaron en la sección anterior.

Tu app anula el método onProvideKeyboardShortcuts() en la actividad principal de la app para proporcionar una lista de combinaciones al asistente de combinaciones de teclas.

Más concretamente, tu app proporciona varios objetos KeyboardShortcutGroup agregándolos a la lista mutable que se pasó a onProvideKeyboardShortcuts(). Cada KeyboardShortcutGroup representa una categoría con nombre de combinaciones de teclas, que permite que tu app agrupe las combinaciones de teclas disponibles por propósito o contexto.

La app de ejemplo tiene dos combinaciones de teclas: Spacebar y Shift+Spacebar.

Para que esas dos combinaciones de teclas estén disponibles en el asistente de combinaciones de teclas, completa los siguientes pasos:

  1. Abre el archivo MainActivity.kt.
  2. Anula el método onProvideKeyboardShortcuts() en MainActivity.
  3. Asegúrate de que la versión del SDK de Android sea Android 7.0 (nivel de API 24) o una versión posterior para que el asistente de combinaciones de teclas esté disponible.
  4. Confirma que el primer parámetro del método no sea null.
  5. Crea un objeto KeyboardShortcutInfo para la tecla Spacebar con los siguientes parámetros:
  • Texto descriptivo
  • android.view.KeyEvent.KEYCODE_SPACE
  • 0 (indica que no hay modificadores)
  1. Crea otra KeyboardShortcutInfo para Shift+Spacebar con los siguientes parámetros:
  • Texto descriptivo
  • android.view.KeyEvent.KEYCODE_SPACE
  • android.view.KeyEvent.META_SHIFT_ON
  1. Crea una lista inmutable que contiene los dos objetos KeyboardShortcutInfo.
  2. Crea un objeto KeyboardShortcutGroup con los siguientes parámetros:
  • Nombre del grupo en texto
  • La lista inmutable del paso anterior
  1. Agrega el objeto KeyboardShortcutGroup a la lista mutable que se pasó como el primer parámetro del método onProvideKeyboardShortcuts().

El método anulado se ve de la siguiente manera:

   override fun onProvideKeyboardShortcuts(
        data: MutableList<KeyboardShortcutGroup>?,
        menu: Menu?,
        deviceId: Int
    ) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && data != null) {
            val shortcutGroup = KeyboardShortcutGroup(
                "To read articles",
                listOf(
                    KeyboardShortcutInfo("Scroll down", KeyEvent.KEYCODE_SPACE, 0), // 0 means no modifier key is pressed
                    KeyboardShortcutInfo("Scroll up", KeyEvent.KEYCODE_SPACE, KeyEvent.META_SHIFT_ON),
                )
            )
            data.add(shortcutGroup)
        }
    }

Ejecución

Ahora los usuarios pueden leer el artículo completo, incluso si se desplazan por el artículo con Spacebar. Para intentarlo, mueve el enfoque del teclado al artículo con la tecla Tab o las teclas de dirección. Puedes ver el mensaje que te anima a presionar el ícono Spacebar.

El asistente de combinaciones de teclas muestra las dos combinaciones de teclas que agregaste (presiona Meta+/). Las combinaciones de teclas agregadas se muestran en la pestaña App actual.

7. Acelera la navegación con el teclado en el panel de detalles

Los usuarios deben presionar la tecla Tab varias veces para mover el enfoque del teclado al panel de detalles cuando la app se ejecuta en la clase de tamaño de ventana expandido. Con la tecla direccional derecha, los usuarios pueden mover el enfoque del teclado de la lista de artículos al artículo con una sola acción, pero igual deben mover el enfoque del teclado. El enfoque inicial no admite el objetivo principal del usuario de leer los artículos.

Tu app puede solicitar mover el enfoque del teclado al componente específico con un objeto FocusRequester. El modificador focusRequester asocia un objeto FocusRequester con el componente modificado. Tu app puede enviar la solicitud real del movimiento del enfoque llamando al método requestFocus() del objeto FocusRequester.

Enviar una solicitud para mover el enfoque del teclado es un efecto secundario del componente. Tu app debe llamar al método de la manera correcta con la función LaunchedEffect.

Si deseas configurar el elemento PostContent componible para obtener el enfoque del teclado cuando los usuarios seleccionan un artículo de la lista, sigue estos pasos:

  1. Accede a la función de componibilidad PostContent en el archivo PostContent.kt de ui/article/.
  2. Asocia el valor focusRequester con la función de componibilidad LazyColumn con el modificador focusRequester. El valor FocusRequester se especifica como parámetro opcional de la función de componibilidad PostContent.
  3. Llama a LaunchedEffect con post, el primer parámetro de la función de componibilidad PostContent, para que se llame a la lambda pasada cuando el usuario selecciona un artículo.
  4. Llama al método focusRequester.requestFocus() en la lambda pasada a la función LaunchedEffect.

El elemento componible PostContent actualizado se ve de la siguiente manera:

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PostContent(
    post: Post,
    modifier: Modifier = Modifier,
    contentPadding: PaddingValues = PaddingValues(0.dp),
    state: LazyListState = rememberLazyListState(),
    coroutineScope: CoroutineScope = rememberCoroutineScope(),
    focusRequester: FocusRequester = remember { FocusRequester() },
    header: (@Composable () -> Unit)? = null
) {
    val interactionSource = remember { MutableInteractionSource() }

    LaunchedEffect(post) {
        focusRequester.requestFocus()
    }

    LazyColumn(
        contentPadding = contentPadding,
        modifier = modifier
            .padding(horizontal = defaultSpacerSize)
            .onKeyEvent {
                if (it.type == KeyEventType.KeyDown && it.key == Key.Spacebar) {
                    val relativeAmount = if (it.isShiftPressed) {
                        -0.4f
                    } else {
                        0.4f
                    }
                    coroutineScope.launch {
                        state.animateScrollBy(relativeAmount * state.layoutInfo.viewportSize.height)
                    }
                    true
                } else {
                    false
                }
            }
            .focusRequester(focusRequester),
            .indication(interactionSource, BorderIndication())
            .focusable(interactionSource = interactionSource),
        state = state,
    ) {
      // Code to layout the selected article.
    }
}

Ejecución

Ahora el enfoque del teclado se trasladará al artículo cuando los usuarios elijan un artículo de la lista. Observa que, en el mensaje, se recomienda usar el Spacebar para desplazarse hacia abajo cuando eliges un artículo.

8. Felicitaciones

¡Buen trabajo! Agregaste compatibilidad con el teclado y mouse físicos a la app de ejemplo. Como resultado, los usuarios pueden seleccionar un artículo de la lista y leerlo usando únicamente un teclado o mouse físico.

Aprendiste las siguientes acciones necesarias para agregar compatibilidad con el teclado y mouse físicos:

  • Cómo comprobar si tu app admite un teclado y mouse físicos, incluso con un emulador
  • Cómo administrar la navegación con el teclado con Compose
  • Cómo agregar combinaciones de teclas con Compose

También agregaste compatibilidad con el teclado y mouse físicos con una pequeña cantidad de modificaciones de código.

Ya está todo listo para agregar compatibilidad con el teclado y mouse físicos a tu app de producción con Compose.

Además, con un poco más de aprendizaje, podrías agregar combinaciones de teclas para las siguientes funcionalidades:

  • Marcar el artículo seleccionado como Me gusta
  • Agregar el artículo seleccionado a favoritos
  • Compartir el artículo seleccionado con otras apps

Más información