我们的应用程序建立在Scaffold
之上,到目前为止,我们已经能够使用NavigatorState
中提供的调用来满足大多数路由和导航要求(pushNamed()
,{ {1}}等)。我们不想要的是,有什么样的推动'用户从我们的抽屉(导航)菜单中选择项目时的动画。我们希望从导航菜单中单击目标屏幕,以有效地成为堆栈的新初始路径。目前我们正在使用pushReplacementNamed()来确保应用栏中没有后退箭头。但是,右下方的幻灯片意味着正在构建堆栈。
在没有动画的情况下更改初始路线的最佳选择是什么?我们可以这样做同时同时关闭抽屉的动画吗?或者我们在这里看一下我们需要从Navigator转移到只使用一个Scaffold并更新' body'当用户想要更改屏幕时直接?
我们注意到在pushReplacementNamed()
上有一个replace()
来电,我们认为这可能是开始寻找的正确位置,但目前还不清楚如何访问最初在{{}设置的各种路线{1}}。像NavigatorState
这样的东西可能是有序的;-)
答案 0 :(得分:42)
你在做什么听起来有点像BottomNavigationBar
,所以你可能想要考虑其中一个而不是Drawer
。
但是,当用户点击抽屉项目时,拥有一个Scaffold
并更新body
是一种非常合理的方法。您可以考虑将FadeTransition
从一个身体更改为另一个身体。
或者,如果您喜欢使用Navigator
但不想使用默认幻灯片动画,则可以通过扩展MaterialPageRoute
来自定义(或禁用)动画。这是一个例子:
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyCustomRoute<T> extends MaterialPageRoute<T> {
MyCustomRoute({ WidgetBuilder builder, RouteSettings settings })
: super(builder: builder, settings: settings);
@override
Widget buildTransitions(BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
if (settings.isInitialRoute)
return child;
// Fades between routes. (If you don't want any animation,
// just return child.)
return new FadeTransition(opacity: animation, child: child);
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Navigation example',
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/': return new MyCustomRoute(
builder: (_) => new MyHomePage(),
settings: settings,
);
case '/somewhere': return new MyCustomRoute(
builder: (_) => new Somewhere(),
settings: settings,
);
}
assert(false);
}
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Navigation example'),
),
drawer: new Drawer(
child: new ListView(
children: <Widget> [
new DrawerHeader(
child: new Container(
child: const Text('This is a header'),
),
),
new ListTile(
leading: const Icon(Icons.navigate_next),
title: const Text('Navigate somewhere'),
onTap: () {
Navigator.pushNamed(context, '/somewhere');
},
),
],
),
),
body: new Center(
child: new Text(
'This is a home page.',
),
),
);
}
}
class Somewhere extends StatelessWidget {
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Text(
'Congrats, you did it.',
),
),
appBar: new AppBar(
title: new Text('Somewhere'),
),
drawer: new Drawer(
child: new ListView(
children: <Widget>[
new DrawerHeader(
child: new Container(
child: const Text('This is a header'),
),
),
],
),
),
);
}
}
答案 1 :(得分:3)
感谢你提供非常有用的答案,科林!
有时也可能有用的小mod:由于其他原因,当我的屏幕(Scaffold)进来时,我想要一个淡入动画,但它是在堆栈上,当我外出时我想要一个常规的滑动,因为它是使用Navigator.pushReplacement(...)添加的。非常容易实现这一点:
class FadeInSlideOutRoute<T> extends MaterialPageRoute<T> {
FadeInSlideOutRoute({WidgetBuilder builder, RouteSettings settings})
: super(builder: builder, settings: settings);
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
if (settings.isInitialRoute) return child;
// Fades between routes. (If you don't want any animation,
// just return child.)
if (animation.status == AnimationStatus.reverse)
return super.buildTransitions(context, animation, secondaryAnimation, child);
return FadeTransition(opacity: animation, child: child);
}
}
答案 2 :(得分:3)
您也可以使用PageRouteBuilder
。
示例:
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: () {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, anim1, anim2) => SecondScreen(),
transitionsBuilder: (context, anim1, anim2, child) => FadeTransition(opacity: anim1, child: child),
transitionDuration: Duration(seconds: 1),
),
);
},
);
}
如果您不想播放任何动画,请在
上方的transitionsBuilder
处替换
transitionsBuilder: (context, anim1, anim2, child) => Container(child: child),
答案 3 :(得分:0)
为防止显示路线时出现动画,请将RouteSettings(isInitialRoute: true)
传递给PageRoute
构造函数。