Pasar datos entre pantallas en Flutter

Resuelto Suragch asked hace 6 años • 13 respuestas

Mientras aprendo Flutter, llegué a la navegación. Quiero pasar datos entre pantallas de manera similar a pasar datos entre actividades en Android y pasar datos entre controladores de vista en iOS . ¿Cómo lo hago en Flutter?

Preguntas relacionadas:

  • La mejor manera de pasar datos entre widgets en Flutter
  • ¿Aleteo pasa datos entre widgets?
  • Flutter/Cómo pasar y obtener datos entre Statefulwidget
Suragch avatar Dec 20 '18 08:12 Suragch
Aceptado

Esta respuesta cubrirá tanto el paso de datos hacia adelante como el paso de datos hacia atrás. A diferencia de las actividades de Android y los ViewControllers de iOS, las diferentes pantallas en Flutter son solo widgets. Navegar entre ellos implica crear algo llamado ruta y usar Navigatorpara insertar y sacar las rutas de la pila.

Pasar datos a la siguiente pantalla

ingrese la descripción de la imagen aquí

Para enviar datos a la siguiente pantalla, haga lo siguiente:

  1. Haga que el SecondScreenconstructor tome un parámetro para el tipo de datos que desea enviarle. En este ejemplo particular, los datos se definen como un Stringvalor y se configuran aquí con this.text.

    class SecondScreen extends StatelessWidget {
      final String text;
      SecondScreen({Key key, @required this.text}) : super(key: key);
    
      ...
    
  2. Luego use Navigatoren el FirstScreenwidget para enviar una ruta al SecondScreenwidget. Pones los datos que quieres enviar como parámetro en su constructor.

    Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => SecondScreen(text: 'Hello',),
        ));
    

El código completo main.dartestá aquí:

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    title: 'Flutter',
    home: FirstScreen(),
  ));
}

class FirstScreen extends StatefulWidget {
  @override
  _FirstScreenState createState() {
    return _FirstScreenState();
  }
}

class _FirstScreenState extends State<FirstScreen> {

  // this allows us to access the TextField text
  TextEditingController textFieldController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('First screen')),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [

          Padding(
            padding: const EdgeInsets.all(32.0),
            child: TextField(
              controller: textFieldController,
              style: TextStyle(
                fontSize: 24,
                color: Colors.black,
              ),
            ),
          ),

          RaisedButton(
            child: Text(
              'Go to second screen',
              style: TextStyle(fontSize: 24),
            ),
            onPressed: () {
              _sendDataToSecondScreen(context);
            },
          )

        ],
      ),
    );
  }

  // get the text in the TextField and start the Second Screen
  void _sendDataToSecondScreen(BuildContext context) {
    String textToSend = textFieldController.text;
    Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => SecondScreen(text: textToSend,),
        ));
  }
}

class SecondScreen extends StatelessWidget {
  final String text;

  // receive data from the FirstScreen as a parameter
  SecondScreen({Key key, @required this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second screen')),
      body: Center(
        child: Text(
          text,
          style: TextStyle(fontSize: 24),
        ),
      ),
    );
  }
}

Pasar datos a la pantalla anterior

ingrese la descripción de la imagen aquí

Al devolver datos, debe hacer lo siguiente:

  1. En FirstScreen, use Navigatorpara presionar (iniciar) SecondScreenun asyncmétodo y esperar el resultado que devolverá cuando finalice.

    final result = await Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => SecondScreen(),
        ));
    
  2. En SecondScreen, incluya los datos que desea pasar como parámetro cuando abra el archivo Navigator.

    Navigator.pop(context, 'Hello');
    
  3. Luego FirstScreenterminará awaity podrás usar el resultado.

    setState(() {
      text = result;
    });
    

Aquí está el código completo main.dartpara su referencia.

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    title: 'Flutter',
    home: FirstScreen(),
  ));
}

class FirstScreen extends StatefulWidget {
  @override
  _FirstScreenState createState() {
    return _FirstScreenState();
  }
}

class _FirstScreenState extends State<FirstScreen> {

  String text = 'Text';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('First screen')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [

            Padding(
              padding: const EdgeInsets.all(32.0),
              child: Text(
                text,
                style: TextStyle(fontSize: 24),
              ),
            ),

            RaisedButton(
              child: Text(
                'Go to second screen',
                style: TextStyle(fontSize: 24),
              ),
              onPressed: () {
                _awaitReturnValueFromSecondScreen(context);
              },
            )

          ],
        ),
      ),
    );
  }

  void _awaitReturnValueFromSecondScreen(BuildContext context) async {

    // start the SecondScreen and wait for it to finish with a result
    final result = await Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => SecondScreen(),
        ));

    // after the SecondScreen result comes back update the Text widget with it
    setState(() {
      text = result;
    });
  }
}

class SecondScreen extends StatefulWidget {
  @override
  _SecondScreenState createState() {
    return _SecondScreenState();
  }
}

class _SecondScreenState extends State<SecondScreen> {
  // this allows us to access the TextField text
  TextEditingController textFieldController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second screen')),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [

          Padding(
            padding: const EdgeInsets.all(32.0),
            child: TextField(
              controller: textFieldController,
              style: TextStyle(
                fontSize: 24,
                color: Colors.black,
              ),
            ),
          ),

          RaisedButton(
            child: Text(
              'Send text back',
              style: TextStyle(fontSize: 24),
            ),
            onPressed: () {
              _sendDataBack(context);
            },
          )

        ],
      ),
    );
  }

  // get the text in the TextField and send it back to the FirstScreen
  void _sendDataBack(BuildContext context) {
    String textToSendBack = textFieldController.text;
    Navigator.pop(context, textToSendBack);
  }
}
Suragch avatar Dec 20 '2018 01:12 Suragch

Esta solución es muy fácil pasando variables en el constructor:

primera página:

Navigator.of(context).push(MaterialPageRoute(builder:(context)=>SecondPage('something')));

segunda pagina:

class SecondPage extends StatefulWidget {
  String something;
  SecondPage(this.something);
  @override
  State<StatefulWidget> createState() {
    return SecondPageState(this.something);
  }
}
class SecondPageState extends State<SecondPage> {
  String something;
  SecondPageState(this.something);
  @override
  Widget build(BuildContext context) {
   return Scaffold(
    appBar: AppBar(
    //now you have passing variable
    title: Text(something),
   ),
   ...
  }
Mahmoud Salah Eldin avatar Jun 24 '2019 22:06 Mahmoud Salah Eldin

Obtenga la solución perfecta:

  1. Desde la primera pantalla navegue a otras como:

    Navigator.pushNamed(context, "second",arguments: {"name" : 
      "Bijendra", "rollNo": 65210});
    },
    
  2. En la segunda pantalla del método de compilación, obtenga lo siguiente:

    @override
    Widget build(BuildContext context) {
        final  Map<String, Object>rcvdData = ModalRoute.of(context).settings.arguments;
        print("rcvd fdata ${rcvdData['name']}");
        print("rcvd fdata ${rcvdData}");
    
        return Scaffold(appBar: AppBar(title: Text("Second")),
          body: Container(child: Column(children: <Widget>[
          Text("Second"),
        ],),),);
    
    }
    
Bijendra Singh avatar Feb 09 '2020 13:02 Bijendra Singh

La manera más fácil

Primera página.dart

 Navigator.push(
          context,
          MaterialPageRoute(
              builder: (context) => PasswordRoute(usernameController)));

//usernameController es un valor de cadena, si desea pasar varios valores, agregue todos

SegundaPágina.dart

class PasswordRoute extends StatefulWidget {
  final String usernameController;//if you have multiple values add here
PasswordRoute(this.usernameController, {Key key}): super(key: key);//add also..example this.abc,this...

  @override
  State<StatefulWidget> createState() => _PasswordPageState();
}

class _PasswordPageState extends State<PasswordRoute> {
 @override
  Widget build(BuildContext context) {
...child: Text(widget.usernameController);
}
}
 avatar Mar 06 '2019 06:03

Las respuestas anteriores son útiles para una aplicación pequeña, pero si desea eliminar el dolor de cabeza de preocuparse continuamente por el estado de los widgets, Google presentó el paquete Proveedor. https://pub.dev/packages/provider

Échale un vistazo o mira estos videos de Andrea Bizzotto: https://www.youtube.com/watch?v=MkFjtCov62g // Proveedor: La guía esencial https://www.youtube.com/watch?v =O71rYKcxUgA&t=258s // Proveedor: Introducción

Aprenda a utilizar el paquete Proveedor y estará listo para toda la vida :)

serg avatar Dec 25 '2019 13:12 serg