Resumen del capítulo 24. Navegación de páginas
Nota
Este libro se publicó en la primavera de 2016 y no se ha actualizado desde entonces. Gran parte del libro sigue siendo útil, pero algunos de los materiales están anticuados y algunos temas ya no son completamente correctos o completos.
Muchas aplicaciones se componen de varias páginas entre las que se desplaza el usuario. La aplicación siempre tiene una página principal o página de inicio y, desde ahí, el usuario se desplaza a otras páginas, que se mantienen en una pila para volver a ellas. En el Capítulo 25. Variedades de página se describen opciones de navegación adicionales.
VisualElement
define una propiedad Navigation
de tipo INavigation
, que incluye los siguientes dos métodos para ir a una nueva página:
Ambos métodos aceptan una instancia de Page
como argumento y devuelven un objeto Task
. Los dos métodos siguientes permiten volver a la página anterior:
Si la interfaz de usuario tiene su propio botón Atrás (como en los teléfonos Android y Windows), no es necesario que la aplicación llame a estos métodos.
Aunque estos métodos están disponibles en cualquier VisualElement
, por lo general se les llama desde la propiedad Navigation
de la instancia de Page
actual.
Las aplicaciones suelen usar páginas modales cuando el usuario debe proporcionar información sobre la página antes de volver a la página anterior. Las páginas que no son modales a veces se denominan sin modo o jerárquicas. Nada en la propia página indica que sea modal o no modal, sino que se rige por el método que se usa para ir a ella. Para que funcione en todas las plataformas, una página modal debe proporcionar su propia interfaz de usuario para volver a la página anterior.
El ejemplo ModelessAndModal permite explorar la diferencia entre las páginas no modales y modales. Cualquier aplicación que use la navegación de páginas debe pasar su página principal al constructor NavigationPage
, generalmente en la clase App
del programa. Una ventaja es que ya no es necesario establecer un elemento Padding
en la página para iOS.
Descubrirá que, en el caso de las páginas no modales, se muestra la propiedad Title
de la página. Todas las plataformas de escritorio y tableta de iOS, Android y Windows proporcionan un elemento de interfaz de usuario para volver a la página anterior. Por supuesto, los dispositivos de teléfono Android y Windows tienen un botón Atrás estándar para volver.
En las páginas modales, el elemento Title
de la página no se muestra y no se proporciona ningún elemento de la interfaz de usuario para volver a la página anterior. Aunque puede usar el botón Atrás estándar de los teléfonos Android y Windows para volver a la página anterior, la página modal de las otras plataformas debe proporcionar su propio mecanismo para volver.
Se proporcionan versiones alternativas de los distintos métodos de navegación con un segundo argumento booleano que se establece en true
si quiere que la transición de página incluya una animación:
Sin embargo, los métodos de navegación de páginas estándar incluyen la animación de forma predeterminada, por lo que solo son valiosos para ir a una página determinada al inicio (como se describe hacia el final de este capítulo) o al proporcionar su propia animación de entrada (como se describe en el Capítulo 22. Animación).
NavigationPage
incluye dos propiedades que se pueden establecer al crear una instancia de la clase en el método App
:
NavigationPage
también incluye cuatro propiedades enlazables asociadas que afectan a la página concreta en la que se establecen:
SetHasBackButton
yGetHasBackButton
SetHasNavigationBar
yGetHasNavigationBar
SetBackButtonTitle
yGetBackButtonTitle
funcionan solo en iOSSetTitleIcon
yGetTitleIcon
funcionan solo en iOS y Android
Los métodos de navegación de páginas son todos asincrónicos y deben usarse con await
. La finalización no indica que se haya completado la navegación de páginas, sino que solo es seguro examinar la pila de navegación de páginas.
Cuando una página lleva a otra, la primera suele obtener una llamada a su método OnDisappearing
, y la segunda página obtiene una llamada a su método OnAppearing
. De igual forma, cuando una página devuelve a otra, la primera obtiene una llamada a su método OnDisappearing
y la segunda página obtiene generalmente una llamada a su método OnAppearing
. El orden de estas llamadas (y la finalización de los métodos asincrónicos que invoca la navegación) depende de la plataforma. El uso de la palabra "general" en las dos instrucciones anteriores se debe a la navegación de páginas modales de Android, en la que no se producen estas llamadas de método.
Además, las llamadas a los métodos OnAppearing
y OnDisappearing
no indican necesariamente la navegación de páginas.
La interfaz INavigation
incluye dos propiedades de colección que permiten examinar la pila de navegación:
NavigationStack
de tipoIReadOnlyList<Page>
para la pila no modalModalStack
de tipoIReadOnlyList<Page>
para la pila modal
Es más seguro acceder a estas pilas desde la propiedad Navigation
de NavigationPage
(que debe ser la propiedad MainPage
de la clase App
). Solo es seguro examinar estas pilas una vez completados los métodos de navegación de páginas asincrónicos. La propiedad CurrentPage
de NavigationPage
no indica la página actual si esta es una página modal, sino que indica en su lugar la última página no modal.
El ejemplo SinglePageNavigation le permite explorar la navegación de páginas y las pilas, así como los tipos lícitos de navegaciones de páginas:
- Una página no modal puede llevar a otra página no modal o a una página modal
- Una página modal solo puede llevar a otra página modal
Una aplicación usa una página modal cuando es necesario obtener información del usuario. Se le debe prohibir al usuario que vuelva a la página anterior hasta que se proporcione esa información. En iOS, es fácil proporcionar un botón Atrás y habilitarlo solo cuando el usuario haya terminado con la página. Pero en el caso de los dispositivos telefónicos Android y Windows, la aplicación debe invalidar el método OnBackButtonPressed
y devolver true
si el programa ha administrado el botón Atrás por sí solo, como se muestra en el ejemplo ModalEnforcement.
En el ejemplo MvvmEnforcement se muestra cómo funciona esto en un escenario de MVVM.
Si se puede ir a una página modal determinada varias veces, esta debe conservar la información de forma que el usuario pueda editarla en lugar de escribirla toda de nuevo. Para ello, puede conservar la instancia en particular de la página modal; sin embargo, un mejor enfoque (especialmente en iOS) es conservar la información en un modelo de vista.
En el ejemplo ViewGalleryType se muestra cómo usar TableView
para enumerar los elementos de menú. Cada elemento está asociado a un objeto Type
de una página determinada. Cuando se selecciona ese elemento, el programa crea una instancia de la página y se desplaza a ella.
El ejemplo ViewGalleryInst es un poco diferente, ya que el menú contiene instancias de cada página en lugar de tipos. Esto ayuda a conservar la información de cada página, pero se deben crear instancias de todas las páginas al inicio del programa.
StackManipulation muestra varias funciones definidas por INavigation
que permiten manipular la pila de navegación de una manera estructurada:
RemovePage
InsertPageBefore
PopToRootAsync
yPopToRootAsync
con animación opcional
En el ejemplo BuildAPage se muestra cómo crear una página en tiempo de ejecución según los datos proporcionados por el usuario.
Con frecuencia es necesario compartir datos entre páginas para transferir datos a una página a la que se ha ido y para que una página devuelva datos a la página que la invocó. Para ello, existen varias técnicas.
Al desplazarse a una nueva página, es posible crear una instancia de la clase de página con un argumento de constructor que permita que la página se inicialice por sí sola. En el ejemplo SchoolAndStudents se muestra cómo. También es posible que la página a la que se ha ido tenga su valor de BindingContext
establecido por la página que lleva a ella.
En el resto de ejemplos de transferencia de datos se explora el problema de pasar información entre páginas cuando una página lleva a otra y viceversa. En estas explicaciones, la página de inicio lleva a la página de información, y debe transferir a esta información inicializada. La página de información obtiene información adicional del usuario y la transfiere a la página de inicio.
La página de inicio puede acceder fácilmente a métodos públicos y propiedades de la página de información en cuanto crea la instancia de esa página. La página de información también puede acceder a métodos públicos y propiedades de la página de inicio, pero puede resultar complicado elegir un buen momento para ello. En el ejemplo DateTransfer1 se hace esto en su invalidación de OnDisappearing
. Una desventaja es que la página de información tiene que conocer el tipo de la página de inicio.
La clase Xamarin.FormsMessagingCenter
proporciona otra manera de que dos páginas se comuniquen entre sí. Los mensajes se identifican mediante una cadena de texto y pueden ir acompañados de cualquier objeto.
Un programa que desea recibir mensajes de un tipo determinado debe suscribirse a ellos mediante MessagingCenter.Subscribe
y especificar una función de devolución de llamada. Posteriormente, puede cancelar la suscripción llamando a MessagingCenter.Unsubscribe
. La función de devolución de llamada recibe los mensajes enviados desde el tipo especificado con el nombre especificado enviado mediante el método Send
.
El programa DateTransfer2 muestra cómo se transfieren los datos mediante el centro de mensajería, pero, de nuevo, es necesario para ello que la página de información conozca el tipo de la página de inicio.
El evento es un enfoque de larga tradición para que una clase envíe información a otra sin conocer el tipo de esa clase. En el ejemplo DateTransfer3, la clase info define un evento que se activa cuando la información está lista. Sin embargo, no hay ningún lugar adecuado para que la página de inicio desasocie el controlador de eventos.
En el ejemplo DateTransfer4 se muestra cómo obtener acceso a las propiedades definidas en la clase App
tanto en la página de inicio como en la página de información. Aunque esta es una buena solución, en la sección siguiente se describe otra mejor.
El uso de ViewModel para la información permite que la página de inicio y la página de información compartan la instancia de la clase de información. Esto se muestra en el ejemplo DateTransfer5.
El intermediario de la clase App
o el enfoque ViewModel son idóneos cuando la aplicación debe guardar información si el programa entra en suspensión mientras la página de información está activa. En el ejemplo DateTransfer6 se muestra cómo.
En general, un programa de varias páginas que entra en suspensión debe ir a la misma página cuando se restaure. Esto significa que dicho programa debe guardar el contenido de la pila de navegación. En esta sección se muestra cómo automatizar este proceso en una clase diseñada para este fin. Esta clase también llama a las páginas individuales para permitirles guardar y restaurar su estado.
La biblioteca Xamarin.FormsBook.Toolkit define una interfaz llamada IPersistantPage
que pueden implementar las clases para guardar y restaurar elementos en el diccionario Properties
.
La clase MultiPageRestorableApp
de la biblioteca Xamarin.FormsBook.Toolkit se deriva de Application
. Luego, puede derivar la clase de App
de MultiPageRestorableApp
y realizar algunas tareas de mantenimiento.
En StackRestoreDemo se muestra el uso de MultiPageRestorableApp
.
El ejemplo NoteTaker también utiliza MultiPageRestorableApp
y permite escribir y editar notas que se guardan en el diccionario de Properties
.