一、概述
上篇文章介绍 MaterialApp
、Scaffold
,但是没有内容比较多,没有介绍完毕。本篇文章继续上文继续说明。
二、 Scaffold Widget 补充
bottomNavigationBar
是 Scaffold
的属性,用来设置应用程序的底部应用或导航栏,其是一个 Widget ,通常使用 BottomAppBar
或 BottomNavigationBar
。主要用来显示消息以及提供特定功能的导航。
BottomAppBar
是一个顶部可以有凹口的 Widget ,是一个 StatefulWidget
。通常与 FloatingActionButton
一起使用。其构造方法如下:
const BottomAppBar({
Key key,
//Color类型可选命名参数,底部程序栏的背景色
this.color,
//double类型可选命名参数,相对于其父应用程序栏放置底部应用程序栏的z坐标
this.elevation,
//NotchedShape类型可选命名参数,为浮动操作按钮制作的凹槽
this.shape,
//Clip类型可选命名参数,设置内容裁剪方式
this.clipBehavior = Clip.none,
//double类型可选命名参数,浮动动作按钮和底部应用栏的凹口之间的边距
this.notchMargin = 4.0,
//Widget类型可选命名参数,要显示的Widget
this.child,
})
使用如下:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyFirstPage(),
);;
}
}
class MyFirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Page 1"),
),
body: Container(
color: Colors.yellow,
child: Center(child: Text("主体内容"),),
),
endDrawer: Drawer(),
bottomNavigationBar: BottomAppBar(
color: Colors.deepPurpleAccent,
child: Text("底部BottomAppBar"),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
print("点击");
},
child: Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
如果不提供 BottomAppBar
的 child
设置,不会抛出异常,但是不会显示 BottomAppBar
。
本例的效果如下:
如果想要设置 BottomAppBar
的高度,可以通过嵌套使用带有高度的 Widget ,如下使用 Container
:
class MyFirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Page 1"),
),
body: Container(
color: Colors.yellow,
child: Center(child: Text("主体内容"),),
),
endDrawer: Drawer(),
bottomNavigationBar: BottomAppBar(
color: Colors.deepPurpleAccent,
child: Container(
child: Text("底部BottomAppBar"),
height: 50.0,
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
print("点击");
},
child: Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
使用有凹口的 BottomAppBar
需要 shape
和 FloatingActionButtonLocation.centerDocked
或 FloatingActionButtonLocation.endDocked
配合使用。如下:
class MyFirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Page 1"),
),
body: Container(
color: Colors.yellow,
child: Center(child: Text("主体内容"),),
),
endDrawer: Drawer(),
bottomNavigationBar: BottomAppBar(
color: Colors.deepPurpleAccent,
shape: const CircularNotchedRectangle(),
child: Container(
height: 50.0,
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
print("点击");
},
child: Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
}
效果如下图:
BottomAppBar
中也可以显示多个 Widget
,需要使用 Row
横向布局 Widget 容器,后面会详细介绍 Row
。使用如下:
class MyFirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Page 1"),
),
body: Container(
color: Colors.yellow,
child: Center(child: Text("主体内容"),),
),
endDrawer: Drawer(),
bottomNavigationBar: BottomAppBar(
color: Colors.deepPurpleAccent,
shape: const CircularNotchedRectangle(),
child: Container(
child: Row(
children: [
IconButton(icon: Icon(Icons.print), onPressed: (){}),
IconButton(icon: Icon(Icons.add), onPressed: (){}),
IconButton(icon: Icon(Icons.add_a_photo), onPressed: (){}),
],
),
height: 50.0,
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
print("点击");
},
child: Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
}
效果如下图:
BottomNavigationBar
主要用于应用的底部导航,继承自 StatefulWidget
,为有状态的 Widget ,构造函数如下:
BottomNavigationBar({
Key key,
//List类型必传参数,底部导航栏中的选项
@required this.items,
//ValueChanged类型可选命名参数,点击某个选项时的回调函数
this.onTap,
//int类型可选命名参数,当前被选择的选项索引
this.currentIndex = 0,
//double类型可选命名参数,此底部导航栏的z坐标。
this.elevation = 8.0,
//BottomNavigationBarType类型可选命名参数,定义底部导航栏的布局和行为
BottomNavigationBarType type,
//Color类型可选命名参数,被选择的选项的颜色,get属性
Color fixedColor,
//Color类型可选命名参数,底部导航栏背景色
this.backgroundColor,
//double类型可选命名参数,底部导航中的图标的大小
this.iconSize = 24.0,
//Color类型可选命名参数,所选底部导航图标和底部导航图标标签的颜色
Color selectedItemColor,
//Color类型可选命名参数,未选择的底部导航图标和底部导航图标标签的颜色
this.unselectedItemColor,
//IconThemeData类型可选命名参数,当前选定的底部导航图标中图标的大小、不透明度和颜色
this.selectedIconTheme = const IconThemeData(),
//IconThemeData类型可选命名参数,当前未选中的底部导航图标中图标的大小、不透明度和颜色
this.unselectedIconTheme = const IconThemeData(),
//double类型可选命名参数,选择时底部导航项标签的字体大小
this.selectedFontSize = 14.0,
//double类型可选命名参数,未选择时底部导航项标签的字体大小
this.unselectedFontSize = 12.0,
//TextStyle类型可选命名参数,选择时底部导航项标签的文本样式。
this.selectedLabelStyle,
//TextStyle类型可选命名参数,未选择时底部导航项标签的文本样式。
this.unselectedLabelStyle,
//bool类型可选命名参数,是否为选择的底部导航图标显示标签文本
this.showSelectedLabels = true,
//bool类型可选命名参数,是否为未选定的底部导航项显示标签文本
bool showUnselectedLabels,
})
BottomNavigationBarItem
为带有图标和标题的交互式按钮,通常与 BottomNavigationBar
一起使用,构造方法如下:
const BottomNavigationBarItem({
//Widget类型必传参数,底部导航选项的图标
@required this.icon,
//Widget类型可选命名参数,底部导航选项的标题
this.title,
//Widget类型可选命名参数,选择底部导航选项的替代图标。当选项被选择时将使用此设置的图标,如果不为null
Widget activeIcon,
//Color类型可选命名参数,底部导航栏的背景径向动画的颜色。只有当设置BottomNavigationBarType.shifting
//时才生效,点击后底部导航背景色将变化为此色
this.backgroundColor,
})
使用方法如下:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyRootNavigationPage(),
);;
}
}
class MyRootNavigationPage extends StatefulWidget {
@override
State createState() {
// TODO: implement createState
return _MyRootNavigationPage();
}
}
class _MyRootNavigationPage extends State {
final List _pageTitles = [
"page 1",
"page 2",
"page 3"
];
String _pageTitle;
int _currentSelected = 0;
final List _pageWidget = [
_FirstPage(),
_SecondPage(),
_ThirdPage(),
];
_itemSelected(int valueIndex) {
setState(() {
_currentSelected = valueIndex;
_pageTitle = _pageTitles.elementAt(valueIndex);
});
}
@override
void initState() {
super.initState();
_pageTitle = _pageTitles.first;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("$_pageTitle"),
),
body: Container(
child: _pageWidget.elementAt(_currentSelected),
),
endDrawer: Drawer(),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.print),
title: Text("Page1"),
),
BottomNavigationBarItem(
icon: Icon(Icons.party_mode),
title: Text("Page2"),
),
BottomNavigationBarItem(
icon: Icon(Icons.add_a_photo),
title: Text("Page3"),
),
],
currentIndex: _currentSelected,
onTap: _itemSelected,
backgroundColor: Colors.yellowAccent,
selectedItemColor: Colors.red,
unselectedItemColor: Colors.black45,
),
);
}
}
class _FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(child: Text("Page 1"));
}
}
class _SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(child: Text("Page 2"));
}
}
class _ThirdPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(child: Text("Page 3"));
}
}
对于 BottomNavigationBarItem
内的显示图标,可以使用 Image
加载自定义的图片。上述代码效果如下:
BottomNavigationBar
的 type
为 BottomNavigationBarType
类型,是一个枚举类型,如下:
enum BottomNavigationBarType {
//底部导航条的底部导航条有固定的宽度
fixed,
//底部导航栏底部导航栏的位置和大小动画和标签在被点击时淡入
shifting,
}
Scaffold
的 persistentFooterButtons
为 List
类型,是一组显示在 Scaffold
底部的 Widget ,通常使用 FlatButton
。这组 Widget 会呈现在 bottomNavigationBar
的上方,body
下方。他们是持续可见的,即使 body
进行滚动依然如此。使用方式如下:
persistentFooterButtons: [
FlatButton(onPressed: (){}, child: Text("按钮1")),
FlatButton(onPressed: (){}, child: Text("按钮1")),
FlatButton(onPressed: (){}, child: Text("按钮1"))
],
效果如下图:
bottomSheet
对应的是一个 Widget ,是一个始终可见的 Widget 。可以用来定义底部的菜单或对话框。也可以使用 Flutter 提供好的
使用任意 Widget 的方法如下:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyFirstPage(),
);;
}
}
class MyFirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Page 1"),
),
body: Container(
color: Colors.yellow,
child: Center(child: Text("主体内容"),),
),
bottomSheet: Container( //bottomSheet
color: Colors.red,
height: 80,
child: Center(child: Text("BottomSheet")),
),
endDrawer: Drawer(),
);
}
}
效果如下图:
在底部展示消息还可以使用 SnackBar
Widget ,其是一个 StatefulWidget
,是一个轻量级的带有可选操作的在屏幕底部暂时出现的 Widget。其构造方法如下:
const SnackBar({
Key key,
//Widget类型必传参数,要显示的Widget
@required this.content,
//Color类型可选命名参数,用于指定背景色
this.backgroundColor,
//double类型可选命名参数,SnackBar的z坐标,这可以控制SnackBar下方阴影的大小
this.elevation,
//ShapeBorder类型可选命名参数,SnackBar的形状
this.shape,
//SnackBarBehavior类型可选命名参数,用于设置SnackBar的行为和位置
this.behavior,
//SnackBarAction类型可选命名参数,要执行的行为
this.action,
//Duration类型可选命名参数,SnackBar的持续显示时间
this.duration = _snackBarDisplayDuration,
//Animation类型可选命名参数,动画
this.animation,
//VoidCallback类型可选命名参数,第一次在Scaffold中出现时的回调函数
this.onVisible,
})
使用如下:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyFirstPage(),
);;
}
}
class MyFirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Page 1"),
),
body: Builder(
builder: (BuildContext context){
return Container(
color: Colors.yellow,
child: Center(
child: RaisedButton(
child: Text("SnackBar"),
onPressed: (){
ScaffoldState state = Scaffold.of(context);
SnackBar snBar = SnackBar(
content: Text("这是一个提示信息"),
backgroundColor: Colors.deepPurpleAccent,
action: SnackBarAction(
label: "点击查看详情",
onPressed: (){
print("详情内容");
},
),
onVisible: ()=> print("第一次出现执行,仅执行一次"),
);
state.showSnackBar(snBar);
},
),
),
);
},
),
endDrawer: Drawer(),
);
}
}
效果如下:
三、MaterialApp Widget 补充
MaterialApp
中的 theme
和 darkTheme
均是 ThemeData
类型,用于设置应用的主题颜色和板式值。可以配置 Theme
或 MaterialApp
Widget ,获取当前的主题,可以使用 Theme.of
。区别在于 darkTheme
意思是提供暗黑模式的主题,在设置 ThemeData
的 Brightness
时应设置为 dark
。如果同时提供 theme
和 darkTheme
,则可以设置 themeMode
进行主题选择,这就是同时提供两种主题模式的用途,可以通过不同的设置提供不同的主题样式。主题主要用来定义应用程序通用的样式和颜色基调,可以再对不同的 Widget 做具体细节调整。其构工厂造函数如下:
factory ThemeData({
//Brightness类型可选命名参数,用于设置主题的模式,dark或者light
Brightness brightness,
//MaterialColor类型可选命名参数,用于定义一种单一的颜色,此颜色带有始终色调的颜色样本
MaterialColor primarySwatch,
//Color类型可选命名参数,用于设置工具栏、标签栏等的背景色
Color primaryColor,
//Brightness类型可选命名参数,在主题模式不变的情况下设置基色(工具栏等)的文本和图标反色
Brightness primaryColorBrightness,
//Color类型可选命名参数,原色的较轻版本
Color primaryColorLight,
//Color类型可选命名参数,原色的较暗版本
Color primaryColorDark,
//Color类型可选命名参数,小部件的前景色(旋钮、文本、过卷边缘效果等)
Color accentColor,
//Brightness类型可选命名参数,用于确定放置在强调色顶部的文本和图标的颜色(例如,浮动操作按钮上的图标)
Brightness accentColorBrightness,
//Color类型可选命名参数,画布颜色
Color canvasColor,
//Color类型可选命名参数,Scaffold的页面背景色
Color scaffoldBackgroundColor,
//Color类型可选命名参数,底部应用栏的默认颜色
Color bottomAppBarColor,
//Color类型可选命名参数,Card的颜色
Color cardColor,
//Color类型可选命名参数,分隔线和弹出窗口的颜色也用于列表间、数据表中的行间等等
Color dividerColor,
//Color类型可选命名参数,使用的焦点颜色表示组件具有输入焦点
Color focusColor,
//Color类型可选命名参数,用于指示指针何时悬停在组件上的悬停颜色
Color hoverColor,
//Color类型可选命名参数,高亮颜色
Color highlightColor,
//Color类型可选命名参数,InkWell颜色
Color splashColor,
//InteractiveInkFeatureFactory类型可选命名参数,定义墨水池和墨水响应产生的墨水飞溅的外观
InteractiveInkFeatureFactory splashFactory,
//Color类型可选命名参数,用于突出显示选定行的颜色
Color selectedRowColor,
//Color类型可选命名参数,处于非活动(但已启用)状态的小部件所用的颜色
Color unselectedWidgetColor,
//Color类型可选命名参数,不工作的小部件所用的颜色,与它们的状态无关
Color disabledColor,
//Color类型可选命名参数,“凸起”按钮中使用的材料的默认填充颜色
Color buttonColor,
//ButtonThemeData类型可选命名参数,定义按钮小部件的默认配置,如上升按钮和平板按钮
ButtonThemeData buttonTheme,
//ToggleButtonsThemeData类型可选命名参数,定义ToggleButtons小部件的默认配置
ToggleButtonsThemeData toggleButtonsTheme,
//Color类型可选命名参数,当有选定行时,分页数据表的标题颜色
Color secondaryHeaderColor,
//Color类型可选命名参数,文本字段中文本选择的颜色,如文本字段
Color textSelectionColor,
//Color类型可选命名参数,TextField(如文本字段)等中光标的颜色
Color cursorColor,
//Color类型可选命名参数,用于调整当前所选文本部分的手柄颜色
Color textSelectionHandleColor,
//Color类型可选命名参数,与原色形成对比的颜色,例如用作进度条的剩余部分
Color backgroundColor,
//Color类型可选命名参数,对话框元素的背景颜色
Color dialogBackgroundColor,
//Color类型可选命名参数,标签栏中所选标签指示器的颜色
Color indicatorColor,
//Color类型可选命名参数,用于提示文本或占位符文本的颜色,例如在文本字段中
Color hintColor,
//Color类型可选命名参数,用于输入验证错误的颜色,例如在文本字段中
Color errorColor,
//Color类型可选命名参数,用于突出显示可切换小部件(如开关、收音机和复选框)活动状态的颜色
Color toggleableActiveColor,
//String类型可选命名参数,用于设置字体名称
String fontFamily,
//TextTheme类型可选命名参数,文字颜色与卡片和画布颜色
TextTheme textTheme,
//TextTheme类型可选命名参数,与原色形成对比的文本主题
TextTheme primaryTextTheme,
//TextTheme类型可选命名参数,与强调色形成对比的文本主题
TextTheme accentTextTheme,
//InputDecorationTheme类型可选命名参数,输入编辑器、文本字段和文本表单字段的默认输入配置值基于此主题
InputDecorationTheme inputDecorationTheme,
//IconThemeData类型可选命名参数,与卡片和画布颜色形成对比的图标主题
IconThemeData iconTheme,
//IconThemeData类型可选命名参数,与原色形成对比的图标主题
IconThemeData primaryIconTheme,
//IconThemeData类型可选命名参数,与强调色形成对比的图标主题
IconThemeData accentIconTheme,
//SliderThemeData类型可选命名参数,用于渲染滑块的颜色和形状
SliderThemeData sliderTheme,
//TabBarTheme类型可选命名参数,用于自定义标签栏指示器的大小、形状和颜色的主题
TabBarTheme tabBarTheme,
//TooltipThemeData类型可选命名参数,用于自定义工具提示视觉属性的主题
TooltipThemeData tooltipTheme,
//CardTheme类型可选命名参数,用于渲染卡片的颜色和样式
CardTheme cardTheme,
//ChipThemeData类型可选命名参数,用于渲染芯片的颜色和样式
ChipThemeData chipTheme,
//TargetPlatform类型可选命名参数,材料部件应适应目标的平台
TargetPlatform platform,
//MaterialTapTargetSize类型可选命名参数,配置某些材质小部件的命中测试大小
MaterialTapTargetSize materialTapTargetSize,
//bool类型可选命名参数,在材质表面应用半透明叠加颜色,以指示深色主题的高度
bool applyElevationOverlayColor,
//PageTransitionsTheme类型可选命名参数,每个目标平台的默认材质页面输出转换
PageTransitionsTheme pageTransitionsTheme,
//AppBarTheme类型可选命名参数,用于自定义应用栏的颜色、高度、亮度、图标主题和文本主题的主题
AppBarTheme appBarTheme,
//BottomAppBarTheme类型可选命名参数,用于自定义底部工具栏的形状、高度和颜色的主题
BottomAppBarTheme bottomAppBarTheme,
//ColorScheme类型可选命名参数,一组十三种颜色,可用于配置大多数组件的颜色属性
ColorScheme colorScheme,
//DialogTheme类型可选命名参数,用于自定义对话框形状的主题
DialogTheme dialogTheme,
//FloatingActionButtonThemeData类型可选命名参数,用于自定义浮动动作按钮的形状、高度和颜色的主题
FloatingActionButtonThemeData floatingActionButtonTheme,
//Typography类型可选命名参数,用于配置文本主题、主文本主题和重音文本主题的颜色和几何文本主题值
Typography typography,
//CupertinoThemeData类型可选命名参数,要从“材料”主题“数据”自适应中覆盖的CupertinoThemeData的组件
CupertinoThemeData cupertinoOverrideTheme,
//SnackBarThemeData类型可选命名参数,用于自定义SnackBar的颜色、形状、高度和行为的主题
SnackBarThemeData snackBarTheme,
//BottomSheetThemeData类型可选命名参数,用于自定义底部工作表的颜色、高度和形状的主题
BottomSheetThemeData bottomSheetTheme,
//PopupMenuThemeData类型可选命名参数,用于自定义弹出菜单的颜色、形状、高度和文本样式的主题
PopupMenuThemeData popupMenuTheme,
//MaterialBannerThemeData类型可选命名参数,用于自定义材质横幅的颜色和文本样式的主题
MaterialBannerThemeData bannerTheme,
//DividerThemeData类型可选命名参数,自定义分割线、垂直分割线等的颜色、厚度和缩进的主题
DividerThemeData dividerTheme,
//ButtonBarThemeData类型可选命名参数,自定义按钮栏小部件外观和布局的主题
ButtonBarThemeData buttonBarTheme,
})
关于 ThemeData
的不同属性只是翻译自官方文档,部分没有做验证看效果,各位要自己试验看效果。
locale
用于设置应用程序的本地语言初始化环境值。如果为 null
,则使用系统的区域设置值。如果 Localizations.locale
的值与 supportedLocales
之一匹配,则它将等于该语言环境。 否则它将是第一个 supportedLocale
。
关于国际化的使用方式查看官方网址:https://flutter.dev/docs/development/accessibility-and-localization/internationalization 。后续文章也会详细介绍。
上述说的都是单独的界面,如果涉及到页面的切换,比如查看列表的详细信息,进入下一级等,需要使用到 Navigator
Widget 。
Navigator
是使用堆栈规则管理一组 Widget ,这些 Widget (界面)称为 Route
对象 。其继承自 StatefulWidget
,是一个有状态的 Widget 。其构造方法如下:
const Navigator({
Key key,
//String类型可选命名参数,要显示的第一个路由(页面)的名称
this.initialRoute,
//RouteFactory类型必传参数,调用以生成给定路由设置的路由
@required this.onGenerateRoute,
//RouteFactory类型必传参数,当onGenerateRoute无法生成路由时调用
this.onUnknownRoute,
//List类型必传参数,导航器的观察者列表
this.observers = const [],
})
在执行路由线路切换需要使用 Navigator
的 push
和 pop
方法,如下:
//将制定路由添加到到导航的路由栈中
@optionalTypeArgs
static Future push(BuildContext context, Route route) {
return Navigator.of(context).push(route);
}
//用于弹出最顶端的路由
@optionalTypeArgs
static bool pop(BuildContext context, [ T result ]) {
return Navigator.of(context).pop(result);
}
Navigator.push()
接收两个参数,一个是上下文信息,另一个是 Route
,可以使用 MaterialPageRote
的实例。其构造函数如下:
MaterialPageRoute({
//WidgetBuilder类型必传参数,构建路线的主要内容
@required this.builder,
//RouteSettings类型可选命名参数,路由的设置
RouteSettings settings,
//bool类型可选命名参数,路由处于非活动状态时是否应保留在内存中
this.maintainState = true,
//bool类型可选命名参数,此页面路由是否为全屏对话框。在iOS上,
//这些页面从底部到顶部(而不是水平)进行动画处理。
bool fullscreenDialog = false,
})
使用方式如下:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);;
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("HomePage"),
),
body: Builder(
builder: (BuildContext context){
return Container(
color: Colors.yellow,
child: Center(
child: RaisedButton(
child: Text("下一页"),
onPressed: (){
Navigator.push(context, MaterialPageRoute(
builder: (context) => FirstPage(),
fullscreenDialog: false, //如果为true,则动画为从下至上推出
));
},
),
),
);
},
),
endDrawer: Drawer(),
);
}
}
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("FirstPage"),
),
body: Center(
child: RaisedButton(
child: Text("上一页"),
onPressed: (){
Navigator.pop(context);
},
),
),
);
}
}
效果如下:
也可以通过设置 Material.routes
来设置导航的顶级路由路线,通过 Navigator.pushNamed
方法进行导航界面切换,pushNamed
方法原型如下:
@optionalTypeArgs
static Future pushNamed(
//BuildContext类型必传参数,上线文
BuildContext context,
//String类型必传参数,路由路径名称
String routeName, {
//Object类型可选命名参数,参数
Object arguments,
}) {
return Navigator.of(context).pushNamed(routeName, arguments: arguments);
}
使用方式如下:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
routes: {
"/first" : (context)=> FirstPage(),
},
);;
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("HomePage"),
),
body: Builder(
builder: (BuildContext context){
return Container(
color: Colors.yellow,
child: Center(
child: RaisedButton(
child: Text("下一页"),
onPressed: (){
Navigator.pushNamed(context, "/first");
},
),
),
);
},
),
endDrawer: Drawer(),
);
}
}
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("FirstPage"),
),
body: Center(
child: RaisedButton(
child: Text("上一页"),
onPressed: (){
Navigator.pop(context);
},
),
),
);
}
}
因为在 home
中设置了首页,所以在 routes
中不需要设置 /
来表示首页,home
等同于 /
。
如果涉及到页面传值,正向传值如果使用 Navigator.push()
,可以使用被传递参数的 Widget 的构造方法,使用Navigator.pushNamed()
,可以使用其第三个参数 arguments
进行参数设置。 反向可以使用 Navigator.pop
的参数进行设置。如下:
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("HomePage"),
),
body: Builder(
builder: (BuildContext context){
return Container(
color: Colors.yellow,
child: Center(
child: RaisedButton(
child: Text("下一页"),
onPressed: (){
//使用push
Navigator.push(context, MaterialPageRoute(
builder: (context) => FirstPage("hike"),
fullscreenDialog: false,
)
).then((value){
print(value);
});
},
),
),
);
},
),
endDrawer: Drawer(),
);
}
}
class FirstPage extends StatelessWidget {
FirstPage(this.userName);
final String userName;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("FirstPage"),
),
body: Center(
child: RaisedButton(
child: Text("上一页 名字为:$userName"),
onPressed: (){
Navigator.pop(context, "返回给HomePage的值");
},
),
),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("HomePage"),
),
body: Builder(
builder: (BuildContext context){
return Container(
color: Colors.yellow,
child: Center(
child: RaisedButton(
child: Text("下一页"),
onPressed: () async {
final result = await Navigator.pushNamed(context, "/first", arguments: {
"name" : "hike",
"age" : "20",
});
print(result);
},
),
),
);
},
),
endDrawer: Drawer(),
);
}
}
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
RouteSettings setting = ModalRoute.of(context).settings;
final Map args = ModalRoute.of(context).settings.arguments;
print(setting.name);
return Scaffold(
appBar: AppBar(
title: Text("FirstPage"),
),
body: Center(
child: RaisedButton(
child: Text("上一页"),
onPressed: (){
Navigator.pop(context, ["hike", "nick"]);
},
),
),
);
}
}
在正向传值中,使用 Navigator.pushNamed()
方法时,参数 arguments
参数为 Object
类型,所以可以定义任意类型参数,也可以使用 class
等包装参数进行传递。当在接收参数页面接收参数时,使用 ModalRoute.of
进行获取,其返回一个带有参数的当前路由。
在反向传值时,当调用 Navigator.pop()
时,会将其中的参数包装到该方法返回的 Feature
对象中。后续文章会详细介绍。可以查看官方说明文档:https://flutter.dev/docs/cookbook/navigation/returning-data