Передача данных между экранами в Flutter

Поскольку я изучаю Флаттер, я пришел к навигации. Я хочу передавать данные между экранами аналогично передаче данных между операциями в Android и передачей данных между контроллерами представления в iOS. Как мне это сделать во Флаттере?

Смежные вопросы:

Ответ 1

Этот ответ будет охватывать как передачу данных вперед, так и передачу данных обратно. В отличие от Android Activity и iOS ViewControllers, разные экраны во Flutter являются просто виджетами. Навигация между ними включает создание чего-либо, называемого маршрутом, и использование Navigator для проталкивания и извлечения маршрутов из стека.

Передача данных вперед на следующий экран

enter image description here

Чтобы отправить данные на следующий экран, вы делаете следующие вещи:

  1. Сделайте так, SecondScreen конструктор SecondScreen принял параметр для типа данных, которые вы хотите отправить ему. В этом конкретном примере данные определены как String значения и задаются здесь с помощью this.text.

    class SecondScreen extends StatelessWidget {
      final String text;
      SecondScreen({Key key, @required this.text}) : super(key: key);
    
      ...
    
  2. Затем с помощью Navigator в виджете FirstScreen маршрут к виджету SecondScreen. Вы помещаете данные, которые хотите отправить, в качестве параметра в его конструктор.

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

Полный код для main.dart находится здесь:

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),
        ),
      ),
    );
  }
}

Передача данных на предыдущий экран

enter image description here

При передаче данных обратно необходимо выполнить следующие действия:

  1. На FirstScreen помощью Navigator нажмите (запустите) SecondScreen в async методе и дождитесь результата, который он вернет после завершения.

    final result = await Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => SecondScreen(),
        ));
    
  2. На SecondScreen данные, которые вы хотите передать обратно, в качестве параметра при SecondScreen Navigator.

    Navigator.pop(context, 'Hello');
    
  3. Тогда в FirstScreen await завершится, и вы можете использовать результат.

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

Вот полный код для main.dart для вашей справки.

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);
  }
}

Ответ 2

Самый простой способ

FirstPage.dart

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

//usernameController это строковое значение, если вы хотите передать несколько значений, добавьте все

SecondPage.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);
}
}

Ответ 3

Это решение очень просто, передав переменные в конструктор:

первая страница:

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

вторая страница:

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),
   ),
   ...
  }

Ответ 4

Как мы можем передать данные, если маршрутизация настроена так?

return MaterialApp(
      theme: ThemeData.dark(),
      routes: {
        '/': (context) => InputPage(),
        'resultpage': (context) => ResultPage()
      },
    );

Caller: Navigator.pushNamed(context, 'resultpage'); Я хочу передать данные на страницу результатов.

Ответ 5

An important question: How to pass those Strings into the Firestore code such as:
Firestore.instance.collection(this.name) etc.... ??
To make it more clear For example:
SignUp.dart
i want to create multiple collections with a String name here its easy i can do it here with:
String Name name;
Name ({this.name});
and then pass it to the textField and Firestore.instance.collection(this.name)
Create.dart
But now how to use this.name from the SignUp.dart here to create a document for the same this.name collection.