La navegación en Flutter

Este es el cuarto tutorial de las serie Fundamentos de Flutter donde aprenderemos sobre el uso de rutas para navegar entre pantallas de nuestra aplicación.

Índice

  1. Navegación directa
  2. Usando rutas
  3. Rutas dinámicas
  4. Tu turno
  5. El código

1. Navegación directa

Para lograr la navegación entre pantallas hay varios métodos. El método más simple es creando un objeto MaterialPageRoute. En el siguiente ejemplo mostramos este método dentro de un método onTap() de algún botón.

onTap: () {
  // Creamos una ruta
  // recuerda que necesitamos del context proporcionado por el build
  final route = MaterialPageRoute(builder: (context) {
    return Contador();
  });
  // Usamos el método Navigator para ir a la página
  // Este método requiere del contexto y la ruta
  Navigator.push(context, route);
},

Ahora si lo que queremos es volver a una página anterior usamos el siguiente método dentro de algún botón o evento.

Navigator.pop(context);

Esta es la forma más simple de cambiar de vistas en Flutter. Sin embargo, no es la mejor ni la más adecuada.

2. Usando rutas

La forma más eficiente de navegar entre distintas páginas de nuestra aplicación es usando ruta. Para esto debemos crear el nombre de ruta para cada una de las pantallas que tenemos en nuestra aplicación. Esto lo haremos en el widget MaterialApp().

return MaterialApp(
  debugShowCheckedModeBanner: false,
  // Definimos la ruta inicial
  initialRoute: '/',
  // Definimos la lista de rutas en nuestra aplicación
  routes: <String, WidgetBuilder>{
    '/': (BuildContext context) => Home(),
    'contador': (BuildContext context) => Contador(),
    'lista': (BuildContext context) => Lista(),
  },
);

La propiedad initialRoute la usamos para definir la ruta con la que iniciará nuestra aplicación. Mientras que la propiedad routes lo usamos para definir mediante un Map las rutas con sus respectivas pantallas.

Cuando definamos el initialRoute ya no debemos colocar la propiedad home, ya que si lo hacemos obtendremos un error.

Ahora para dirigirnos a una ruta determinada desde un botón o algún evento usamos el método Navigator.pushNamed() donde le enviamos como parámetro el contexto de nuestra aplicación y el nombre de la ruta.

onTap: () {
  Navigator.pushNamed(context, 'lista');
},
Las rutas en una aplicación pueden ser muchas si es que la aplicación tiene demasiadas páginas. Por esta razón la propiedad routes solo debe referenciar un map con las rutas de nuestra aplicación, que bien puede ser creado en un archivo distinto. Para esto generalmente se usa la carpeta routes.
Map<String, Widget Function(BuildContext)> getApplicationRoutes() {
  return <String, Widget Function(BuildContext)>{
    '/': (BuildContext context) => Home(),
    '/alert': (BuildContext context) => Contador(),
    '/avatar': (BuildContext context) => Lista(),
  };
}

3. Rutas dinámicas

En nuestro MaterialApp podemos colocar una propiedad que se ejecute solo cuando nuestra aplicación no encuentre una ruta específica. Este parámetro es el onGenerateRoute.

return MaterialApp(
  debugShowCheckedModeBanner: false,
  initialRoute: '/',
  routes: <String, WidgetBuilder>{
    '/': (BuildContext context) => Home(),
    'contador': (BuildContext context) => Contador(),
    'lista': (BuildContext context) => Lista(),
  },
  onGenerateRoute: (RouteSettings settings) {
    // Se ejecutará este código si no se encuentra una ruta específica
    // Para saber el nombre de la ruta que se llamo se usa el settings.name
    print('La ruta no encontrada es ${settings.name}');
  },
);

Esta propiedad necesita de una función que tenga como parámetro un RouteSettings y retorne un Route<dynamic>. Para esto usamos el método MaterialPageRoute()que devuelve un MaterialPageRoute<dynamic> que por herencia es un Route<dynamic> y con esto cumplimos con lo que necesita esta propiedad.

El MaterialPageRoute() tiene como parámetro un builder que es una función que retorna el widget que construirá nuestra ruta. Pero esta función necesita de un parámetro BuildContext para que sea aceptada correctamente por la propiedad builder.

El BuildContext es usando internamente por la función para entregarle un contexto al widget que debe crear y que nosotros retornamos.
onGenerateRoute: (RouteSettings settings) {
  print('Ruta llamado ${settings.name}');
  return MaterialPageRoute(builder: (BuildContext builder) => Contador());
},

Como puedes ver el desarrollo en Flutter esta compuesto de funciones con distintas propiedad que nos ayudan a construir nuestra aplicación. En este sentido cae perfecto la funcionalidad de la extensión de Flutter para VSCode que nos permite tener a la mano la descripción de las funciones y las diferentes propiedad que podemos usar para lograr lo que buscamos en nuestra aplicación. Así que utilízalo te será de gran ayuda.

4. Tu turno

Ya sabemos como manejar las rutas para saltar de una vista a otra en Flutter. Ahora es tu turno de aplicar todos estos conceptos y crear una aplicación con múltiples vistas y botones para navegar entre ellas.

Cuando quieras puedes ver el código de este proyecto de ejemplo. Pero ándale inténtalo tu mismo!!

5. El código

El código fuente de la aplicación la podemos encontrar en el siguiente repositorio: github.com/andygeek/rutas_app_flutter