如何在 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 回答。
在下面的示例中,当我推送新的 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 回答。