Flutter - Push и Get value между маршрутами

Как отправить зеленую строку со страницы HomePage на страницу ContaPage?

Я думаю, что так Navigator.of(context).pushNamed('/conta/green'); но я не знаю, как получить на странице conta в green строке

Итак, получив значение строки, я могу, например, изменить цвет backgroundColor appBar в ContaPage.

main.dart

import "package:flutter/material.dart";

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "MyApp",
      home: new HomePage(),
      routes: <String, WidgetBuilder> {
        '/home': (BuildContext context) => new HomePage(),
        '/conta': (BuildContext context) => new ContaPage()
      },
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) => new Scaffold(
    appBar: new AppBar(
      backgroundColor: new Color(0xFF26C6DA),
    ),
    body: new ListView  (
      children: <Widget>[
        new FlatButton(
          child: new Text("ok"),
          textColor: new Color(0xFF66BB6A),               
          onPressed: () {
            Navigator.of(context).pushNamed('/conta');
          },
        ),
      ],
    )
  );
}

class ContaPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) => new Scaffold(
    appBar: new AppBar(
      backgroundColor: new Color(0xFF26C6DA),
    ), 
  );
}

Ответ 1

Вы можете создать MaterialPageRoute по запросу и передать аргумент конструктору ContaPage.

import "package:flutter/material.dart";

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "MyApp",
      home: new HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) => new Scaffold(
    appBar: new AppBar(
      backgroundColor: new Color(0xFF26C6DA),
    ),
    body: new ListView  (
      children: <Widget>[
        new FlatButton(
          child: new Text("ok"),
          textColor: new Color(0xFF66BB6A),
          onPressed: () {
            Navigator.push(context, new MaterialPageRoute(
              builder: (BuildContext context) => new ContaPage(new Color(0xFF66BB6A)),
            ));
          },
        ),
      ],
    )
  );
}

class ContaPage extends StatelessWidget {
  ContaPage(this.color);
  final Color color;
  @override
  Widget build(BuildContext context) => new Scaffold(
    appBar: new AppBar(
      backgroundColor: color,
    ),
  );
}

Ответ 2

Вы всегда можете сделать статическую переменную String зеленой, как это значение в вашей HomePage, и использовать это значение в своих маршрутах при создании нового ContaPage. Что-то вроде этого:

import "package:flutter/material.dart";

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "MyApp",
      home: new HomePage(),
      routes: <String, WidgetBuilder> {
        '/home': (BuildContext context) => new HomePage(),
        '/conta': (BuildContext context) => new ContaPage(HomePage.color)
      },
    );
  }
}

class HomePage extends StatelessWidget {

  static String color = "green";

  @override
  Widget build(BuildContext context) => new Scaffold(
    appBar: new AppBar(
      backgroundColor: new Color(0xFF26C6DA),
    ),
    body: new ListView  (
      children: <Widget>[
        new FlatButton(
          child: new Text("ok"),
          textColor: new Color(0xFF66BB6A),               
          onPressed: () {
            Navigator.of(context).pushNamed('/conta');
          },
        ),
      ],
    )
  );
}

class ContaPage extends StatelessWidget {

  ContaPage({this.color})
  String color;

  @override
  Widget build(BuildContext context) => new Scaffold(
    appBar: new AppBar(
      backgroundColor: new Color(0xFF26C6DA),
    ), 
  );
}

Есть, вероятно, лучшие решения, но это всплыло мне в голову :)

Ответ 3

Лучшее решение уже дано на сайте Flutter, как использовать:

Аргументы

class ScreenArguments {
  final String title;
  final String message;

  ScreenArguments(this.title, this.message);
}

Извлечь аргументы

class ExtractArgumentsScreen extends StatelessWidget {
  static const routeName = '/extractArguments';

  @override
  Widget build(BuildContext context) {
    final ScreenArguments args = ModalRoute.of(context).settings.arguments;
    return Scaffold(
      appBar: AppBar(
        title: Text(args.title),
      ),
      body: Center(
        child: Text(args.message),
      ),
    );
  }
}

Зарегистрировать маршрут

MaterialApp(
  //...
  routes: {
    ExtractArgumentsScreen.routeName: (context) => ExtractArgumentsScreen(),
    //...
  },     
);

Navigate

Navigator.pushNamed(
      context,
      ExtractArgumentsScreen.routeName,
      arguments: ScreenArguments(
        'Extract Arguments Screen',
        'This message is extracted in the build method.',
      ),
    );

Code copied from link.

Ответ 4

Это немного поздно, но это может помочь кому-то. Я думаю, что лучший способ - использовать flutter route project fluro.

определить где-то глобально:

final router = Router();

после этого определить маршруты

var contaHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
  return ContaPage(color: params["color"][0]);
});

void defineRoutes(Router router) {
  router.define("/conta/:color", handler: contaHandler);
}

установите onGenerateRoute в MaterialApp для использования генератора маршрутизатора:

 new MaterialApp (
   ...
   nGenerateRoute: router.generator
   ...
 ),

вам нужно добавить fluro в зависимости:

 dependencies:
     fluro: "^1.3.4"

и выполните обновление пакета следующим образом или способом IDE.

 flutter packages upgrade

Ответ 5

Передача данных с 1-й страницы на 2-ю

На 1-й странице

// sending "Foo" from 1st page
Navigator.push(context, MaterialPageRoute(builder: (_) => Page2("Foo")));

На 2-й странице.

class Page2 extends StatelessWidget {
  final String string;
  Page2(this.string); // receiving "Foo" in 2nd
}

Передача данных со 2-й страницы обратно на 1-ю

На 2-й странице

// sending "Bar" from 2nd
Navigator.pop(context, "Bar");

На 1-й странице это то же самое, что использовалось ранее, но с небольшими изменениями.

// receiving "Bar" in 1st
String received = await Navigator.push(context, MaterialPageRoute(builder: (_) => Page2("Foo")));