如何在 Flutter 的小部件树中将新的 MaterialPageRoute 作为子项打开

How to open new MaterialPageRoute as a child in widget tree in Flutter

在下面的示例中,当我推送新的 MaterialPageRoute 时,它​​是在与 Flutter 小部件树中的 Home 小部件相同的级别上创建的。我想将它作为小部件 Home 的子项,因此 Home 将成为 Child 小部件的父项。

完整代码如下:

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    home: Home(),
  ));
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: <Widget>[
          Center(
            child: Text("This is home"),
          ),
          RaisedButton(
            child: Text("Open child view"),
            onPressed: () {
              Navigator.of(context)
                  .push(MaterialPageRoute(builder: (context) => Child()));
            },
          )
        ],
      ),
    );
  }
}

class Child extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Container(
      child: Text("Child view"),
    ));
  }
}

这是小部件树的样子

我想实现这一点,因为我想在 Home 小部件中初始化 ScopedModel,并让它在我创建的每个新 MaterialPageRoute 中可用。

Navigator.of(context).push() 将用一个新屏幕替换您的 Home 屏幕(同时将 Home 屏幕保留在内存中以便您可以返回它)。它们在小部件树中处于同一级别,嵌套它们的唯一方法是使用嵌套 Navigators 我认为。

但是,考虑到您想实现的目标:为什么不向上一级初始化 ScopedModel 并在小部件树的根部提供?这样您就可以在 Home 屏幕和 Child 屏幕中访问您的模型。

下面是你如何做到这一点,我添加了一个简单的 ScopedModel 并且能够在 Child 屏幕内访问它的 text属性。

import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';
import 'package:tryout/model.dart';

void main() {
  runApp(
    ScopedModel<TestModel>(
      model: TestModel(),
      child: MaterialApp(
        home: Home(),
      ),
    )
  );
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: <Widget>[
          Center(
            child: Text("This is home"),
          ),
          RaisedButton(
            child: Text("Open child view"),
            onPressed: () {
              Navigator.of(context)
                  .push(MaterialPageRoute(builder: (context) => Child()));
            },
          )
        ],
      ),
    );
  }
}

class Child extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Container(
      child: Text("${ScopedModel.of<TestModel>(context).text}"),
    ));
  }
}

这里是 TestModel class:

import 'package:scoped_model/scoped_model.dart';

class TestModel extends Model {
  String _text = "Test to see if this works!";
  String get text => _text;
}

我使用嵌套导航器解决了我的问题。

示例如下:

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    home: Home(),
  ));
}

var homeNavigatorKey = GlobalKey<NavigatorState>();

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Navigator(
        key: homeNavigatorKey,
        onGenerateRoute: (settings) {
          /*dirty code for illustration purposes only*/
          if (settings.name == '/child') {
            return MaterialPageRoute(builder: (context) => Child());
          } else {
            return MaterialPageRoute(
                builder: (context) => Column(
                      children: <Widget>[
                        Center(
                          child: Text("This is home"),
                        ),
                        RaisedButton(
                          child: Text("Open child view"),
                          onPressed: () {
                            homeNavigatorKey.currentState.pushNamed('/child');
                          },
                        )
                      ],
                    ));
          }
        },
      ),
    );
  }
}

class Child extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Container(
      child: RaisedButton(
        onPressed: () => Navigator.of(context).pop(),
        child: Text("Back to home"),
      ),
    ));
  }
}

树看起来像这样

并允许将数据从 Home 传递到每个 child。

如果您有任何更简单的解决方案,请随时发表评论或 post 回答。