El arsenal de Android – Navegación

Una biblioteca de navegación pequeña y simple, pero completa y personalizable para Esfera de mochila propulsora:

  • Completo Tipo de seguridad
  • restauración del estado
  • Navegación anidada con backstacks independientes
  • Usted posee el ciclo de vida, el estado guardado y las plantillas de vista para cada entrada de backstack
  • Transiciones animadas
  • La lógica de navegación se puede mover fácilmente a la capa ViewModel
  • Sin constructores, sin superclases obligatorias para tus componibles
  • Se puede utilizar para la gestión de diálogos.

Para comenzar

Agregue una sola dependencia a su proyecto:

implementation("dev.olshevski.navigation:reimagined:1.0.0-beta01")

Defina un conjunto de pantallas, por ejemplo, como una clase sellada:

sealed class Screen : Parcelable {

    @Parcelize
    object First : Screen()

    @Parcelize
    data class Second(val id: Int) : Screen()

    @Parcelize
    data class Third(val text: String) : Screen()

}

Crear un modular con NavController Y NavHost:

@Composable
fun NavHostScreen() {
    val navController = rememberNavController<Screen>(
        startDestination = Screen.First,
    )

    NavBackHandler(navController)

    NavHost(controller = navController) { screen ->
        when (screen) {
            Screen.First -> Column {
                Text("First screen")
                Button(onClick = {
                    navController.navigate(Screen.Second(id = 42))
                }) {
                    Text("To Second screen")
                }
            }
            is Screen.Second -> Column {
                Text("Second screen: ${screen.id}")
                Button(onClick = {
                    navController.navigate(Screen.Third(text = "Hello"))
                }) {
                    Text("To Third screen")
                }
            }
            is Screen.Third -> {
                Text("Third screen: ${screen.text}")
            }
        }
    }
}

Como puedes ver, NavController se utiliza para cambiar entre pantallas, NavBackHandler gestiona las prensas traseras e NavHost simplemente proporciona un componible correspondiente al último destino en el backstack. Tan sencillo.

Lo esencial

Aquí está el flujo de trabajo general de la biblioteca:

Vamos a entrar en detalle en cada uno de ellos.

controlador de navegación

Este es el principal punto de control de navegación. Realiza un seguimiento de todas las entradas backstack actuales y las mantiene en actividades/recreación de procesos.

NavController se puede crear con rememberNavController dentro de la composición o con navController fuera de ella Este último se puede usar para almacenar NavController en un ViewModel. Dado que implementa la interfaz Parcelable, podría (y debería) almacenarse en Manejador de estado guardado.

Ambos rememberNavController Y navController los métodos aceptan startDestination como parámetro. Si desea crear NavController con un número arbitrario de elementos backstack, puede usar initialBackstack parámetro en su lugar.

Destinos

NavController acepta todos los tipos que cumplen los requisitos como objetivos. Los requisitos son:

  1. El tipo debe ser Parcelable, Serializable o primitivo o cualquier otro tipo en el que se pueda escribir Paquete.

  2. El tipo debe ser uno de los dos Estableo Inmutableo primitivo.

Métodos de navegación

Hay un puñado de métodos predefinidos adecuados para la navegación básica de aplicaciones: navigate, pop, popUpTo, popAll, replaceLast, replaceUpTo, replaceAll. Todos son bastante autoexplicativos.

Si su caso de uso requiere alguna manipulación avanzada de backstack, puede usarlo setNewBackstackEntries método. De hecho, este es el único método público definido en NavController, todos los demás métodos se proporcionan como extensiones y uso setNewBackstackEntries bajo el capó. Puede verlo como un nuevo método de extensión navigateToTab se implementa en el muestra.

NavBackstack

Esta es una clase de solo lectura que puede usar para acceder a las entradas actuales de backstack y la última NavAction. Las propiedades son compatibles con estado mutableentonces Compose será notificado de los cambios.

Si desea escuchar los cambios de backstack fuera de la composición, puede configurar onBackstackChange oyente en NavController.

Anfitrión de navegación

NavHost es un complemento que muestra la última entrada en un backstack y proporciona todos los componentes asociados con esta entrada en particular: Ciclo vital, Registro de estado guardado Y VerModeloTienda. Todos estos componentes se suministran a través de ComposiciónLocalProvider dentro de sus respectivos dueños LocalLifecycleOwner, LocalSavedStateRegistryOwner Y LocalViewModelStoreOwner.

Los componentes se retienen hasta que la entrada asociada se elimine del backstack (o hasta que se elimine la entrada principal que contiene el NavHost secundario actual).

NavHost en sí mismo no proporciona transiciones animadas, simplemente salta al siguiente destino.

AnimatedNavHost

AnimatedNavHost incluye todas las funciones del NavHost normal, pero también admite transiciones animadas. La transición predeterminada es un fundido cruzado simple, pero puede personalizar granularmente cada transición con su propia transición. AnimatedNavHostTransitionSpec implementación.

Aquí hay una posible implementación de AnimatedNavHostTransitionSpec:

val CustomTransitionSpec = AnimatedNavHostTransitionSpec<Any?> { action, from, to ->
    val direction = if (action == NavAction.Pop) {
        AnimatedContentScope.SlideDirection.End
    } else {
        AnimatedContentScope.SlideDirection.Start
    }
    slideIntoContainer(direction) with slideOutOfContainer(direction)
}

Configúralo en AnimatedNavHost:

AnimatedNavHost(
    controller = navController,
    transitionSpec = CustomTransitionSpec
) { destination ->
    // ...
}

y terminará luciendo así:

En AnimatedNavHostTransitionSpec obtenga los parámetros:

  • action – el consejo sobre el último método NavController que cambió el backstack
  • from – el destino visible anterior
  • to – el objetivo visible del objetivo

Esta información es suficiente para elegir una transición para cada combinación posible de pantallas y acciones de navegación.

Acción de navegación

Hay cuatro tipos de NavAction predefinidos:

  • Pop, Replace Y Navigate – objetos a los que corresponden pop…, replace…, navigate Métodos de NavController
  • Idle – la acción predeterminada de un NavController recién creado

También puede crear un nuevo tipo de acción extendiendo resumen NavAction clase. Cambiar este nuevo tipo en setNewBackstackEntries método de NavController y manejarlo en AnimatedNavHostTransitionSpec.

También se puede acceder a la última acción a través de action propiedad de NavBackstack.

DialogNavHost

La versión de NavHost más adecuada para mostrar diálogos. Se basa en AnimatedNavHost y proporciona una transición más suave entre los diálogos sin scrim/fade.

Si desea ver cómo implementar la navegación en los cuadros de diálogo, explore el archivo muestra.

Tenga en cuenta que DialogNavHost no envuelve sus componibles en un cuadro de diálogo. Debe usar el uso de Dialog o Composable AlertDialog dentro de un contentSelector tú mismo.

Gestión de la espalda

Volver a la administración de la biblioteca es optar por participar en lugar de optar por no participar. Por sí mismos, ni NavController ni NavHost manejan presionar el botón Atrás. puedes añadir NavBackHandler o normales BackHandler para reaccionar a las presiones traseras donde se necesita.

NavBackHandler es la implementación más simple de llamadas BackHandler pop hasta que quede un artículo en la pila trasera. Luego se desactiva, por lo que cualquier BackHandler de nivel superior puede reaccionar al presionar el botón Atrás.

Nota IMPORTANTE: siempre coloque NavBackHandler / BackHandler antes de el NavHost correspondiente. Lee la explicación aquí.

Navegación anidada

Agregar navegación anidada es tan simple como colocar un NavHost en otro. Todo se maneja correctamente y funciona.

Puede ir a tantas capas en profundidad como desee. Y cómo fractalespero en la navegación.

Devuelve los valores a los destinos anteriores

Dado que los tipos de destino no necesariamente tienen que ser inmutables, puede cambiarlos mientras están apilados. Se puede utilizar para devolver valores de otros destinos. Simplemente cree una propiedad mutable compatible con mutableStateOf y cambiarlo cuando sea necesario. Puede ver la demostración aquí.

Nota: Por lo general, devolver valores al destino anterior complica la lógica de navegación. Además, este enfoque no garantiza la seguridad del tipo en tiempo de compilación. Úselo con precaución y cuando esté seguro de lo que está haciendo. A veces puede ser más fácil usar un titular de estado compartido.

Documentación y muestra

Explore la documentación de KDoc de la biblioteca para obtener más detalles sobre cada componente y cada función admitida.

Además, explore la muestra. Proporciona demostraciones de todas las características mencionadas anteriormente y más. La muestra muestra:

  • navegación anidada
  • navegación por pestañas
  • Usando NavHost / AnimatedNavHost
  • diálogos
  • pasar y devolver valores
  • Ver plantillas
  • elevando NavController al nivel de ViewModel

¿Por qué beta?

Estoy muy satisfecho con la forma y la forma de la librería. He pasado largas noches sin dormir depurando y puliendo todos los casos de esquina.

Por ahora, estaré encantado de recibir comentarios y realizar pequeños cambios en la API (si los hay). Si hay algún cambio, es posible que espere un aviso en las notas de la versión.

De

He estado pensando en la arquitectura y la navegación de las aplicaciones de Android en particular durante mucho tiempo. Cuando conocí Compose, finalmente pude crear la estructura de navegación que se adapta perfectamente a todas mis necesidades.

Hacerlo en forma de biblioteca pública cierra para mí una gestalt. Finalmente terminé. ¡Hacia nuevos proyectos!

Si le gusta esta biblioteca y la encuentra útil, agregue el proyecto a Destacado y compártalo con sus compañeros desarrolladores. Un poco de promoción nunca viene mal.

Compruebe también

Permitir que todos los desarrolladores construyan para el hogar

Publicado por Matt Van Der Staay, director de ingeniería de Google Home Este blog fue …

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *