En una aplicación es normal que el contenido esté dividido en diferentes pantallas. Vamos a ver cómo podemos crearlas y navegar por ellas con Navigator.
En Flutter, el Navigator es el encargado de gestionar las pantallas y lo hace en forma de pila. Si queremos crear una nueva pantalla, ésta se pondrá en el primer lugar de la pila y se mostrará al usuario. Si el usuario decide volver hacia atrás o cerrar esa nueva pantalla, el Navigator la quitará de la pila dejando paso a la pantalla que estábamos viendo antes, quedará en primer lugar de la pila y por tanto se mostrará de nuevo.
Vamos a verlo con un ejemplo, que siempre es más fácil.
Abrir nueva pantalla con Navigator
Lo primero que vamos a hacer es crear una primera pantalla inicial muy sencilla. Tendrá solamente un App Bar un Floating Action Button y un texto como contenido (todo eso lo podemos hacer en unos segundos con Scaffold, ¡qué maravilla!).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My app title',
home: new HomeScreen()
);
}
}
class HomeScreen extends StatelessWidget{
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Ejemplo con Navigator'),
backgroundColor: Colors.orange,
),
body: Center(
child: Center(
child: Text('Ejemplo Navigator'),
)
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.orangeAccent,
child: Icon(Icons.add),
),
);
}
}
En este momento el Navigator tiene una sola pantalla en la pila, la que estamos viendo.Lo que vamos a hacer ahora es que al presionar el botón el Navigator cree una nueva ventana.
El floating action button tiene la propiedad onPressed, podemos usarla para indicar la función que se ejecutará cuando un usuario pulse sobre el botón. Aquí es donde vamos a usar al Navigator y vamos a hacer que llame a su método push.
1
2
3
4
5
6
7
8
9
10
11 floatingActionButton: FloatingActionButton(
...
onPressed: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
//TODO return widget
}),
);
}
),
Como vemos al método push le hemos pasado dos parámetros, el contexto actual y un MaterialPageRoute, un componente que nos ayuda a crear una nueva página y además utiliza una animación específica de la plataforma donde se está ejecutando (iOS o Android).
MaterialPageRoute tiene un método builder que es obligatorio implementar y que debe devolver el widget que será la nueva pantalla. Vamos a crear la segunda pantalla, en esta caso en una clase que se llamará por ejemplo «NewScreen». Hacemos que el build de MaterialPageRoute devuelva esta segunda página y ya lo tenemos, al pulsar sobre el botón vemos cómo se abre esta segunda página.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My app title',
home: new HomeScreen()
);
}
}
class HomeScreen extends StatelessWidget{
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Ejemplo con Navigator'),
backgroundColor: Colors.orange,
),
body: Center(
child: Center(
child: Text('Ejemplo Navigator'),
)
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.orangeAccent,
child: Icon(Icons.add),
onPressed: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return NewScreen();
}),
);
}
),
);
}
}
class NewScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Nueva pantalla'),
backgroundColor: Colors.orange,
),
body: Center(
child: Center(
child: Text('Contenido nueva pantalla'),
)
),
);
}
}
Lo que está pasando en realidad es que el Navigator crea la pantalla y la pone en la pila. Fíjate que el método se llama «push» porque lo que hace es poner en la pila, no se llama «show» ni nada por el estilo. Como está en lo más alto de la pila, esta nueva pantalla es la que el usuario ve.
Volver atrás
Como en la pila hemos dejado debajo la pantalla inicial, por defecto el appBar de la segunda pantalla muestra la flecha para volver atrás. Esto también lo podemos forzar con la función «pop» de Navigator, es lo contrario a «push», en lugar de poner un nuevo elemento en la pila, lo que hace es eliminar el elemento actual para volver a mostrar la pantalla anterior. Por ejemplo podemos poner un botón «Atrás» que haga lo mismo que la «flechita» y vuelva a la pantalla anterior.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My app title',
home: new HomeScreen()
);
}
}
class HomeScreen extends StatelessWidget{
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Ejemplo con Navigator'),
backgroundColor: Colors.orange,
),
body: Center(
child: Center(
child: Text('Ejemplo Navigator'),
)
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.orangeAccent,
child: Icon(Icons.add),
onPressed: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return NewScreen();
}),
);
}
),
);
}
}
class NewScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Nueva pantalla'),
backgroundColor: Colors.orange,
),
body: Container(
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Contenido nueva pantalla'),
RaisedButton(
child: Text('Atrás'),
onPressed: () {
Navigator.pop(context);
}
)
],
),
)
);
}
}
Como ves, con Navigator podemos crear nuevas pantallas de forma muy sencilla. Todas las pantallas son widgets y con Navigator se pueden gestionar.
Puedes ver el código de este ejemplo en github por si te sirve de algo.