[Flutter]flutter基础之组件基础(六)

一、概述

上篇文章介绍 MaterialAppScaffold ,但是没有内容比较多,没有介绍完毕。本篇文章继续上文继续说明。

二、 Scaffold Widget 补充

bottomNavigationBarScaffold 的属性,用来设置应用程序的底部应用或导航栏,其是一个 Widget ,通常使用 BottomAppBarBottomNavigationBar 。主要用来显示消息以及提供特定功能的导航。

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,
    );
  }
}

如果不提供 BottomAppBarchild 设置,不会抛出异常,但是不会显示 BottomAppBar

本例的效果如下:

2020312245.jpg

如果想要设置 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,
    );
  }
}
2020312513.jpg

使用有凹口的 BottomAppBar 需要 shapeFloatingActionButtonLocation.centerDockedFloatingActionButtonLocation.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,
    );
  }
}

效果如下图:

2020312725.jpg

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,
    );
  }
}

效果如下图:

2020312739.jpg

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 加载自定义的图片。上述代码效果如下:

20203121058.jpg

BottomNavigationBartypeBottomNavigationBarType 类型,是一个枚举类型,如下:

enum BottomNavigationBarType {
  //底部导航条的底部导航条有固定的宽度
  fixed,

  //底部导航栏底部导航栏的位置和大小动画和标签在被点击时淡入
  shifting,
}

ScaffoldpersistentFooterButtonsList 类型,是一组显示在 Scaffold 底部的 Widget ,通常使用 FlatButton 。这组 Widget 会呈现在 bottomNavigationBar 的上方,body 下方。他们是持续可见的,即使 body 进行滚动依然如此。使用方式如下:

persistentFooterButtons: [
        FlatButton(onPressed: (){}, child: Text("按钮1")),
        FlatButton(onPressed: (){}, child: Text("按钮1")),
        FlatButton(onPressed: (){}, child: Text("按钮1"))
      ],

效果如下图:

20203121115.jpg

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(),
    );
  }
}

效果如下图:

2020313235.jpg

在底部展示消息还可以使用 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(),
    );
  }
}

效果如下:

2020314732.gif

三、MaterialApp Widget 补充

MaterialApp 中的 themedarkTheme 均是 ThemeData 类型,用于设置应用的主题颜色和板式值。可以配置 ThemeMaterialApp Widget ,获取当前的主题,可以使用 Theme.of 。区别在于 darkTheme 意思是提供暗黑模式的主题,在设置 ThemeDataBrightness 时应设置为 dark 。如果同时提供 themedarkTheme ,则可以设置 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 [],
})

在执行路由线路切换需要使用 Navigatorpushpop 方法,如下:

//将制定路由添加到到导航的路由栈中
@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);
          },
        ),
      ),
    );
  }
}

效果如下:

2020315123.gif

也可以通过设置 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

你可能感兴趣的:([Flutter]flutter基础之组件基础(六))