flutter知识点总结

1.Windows搭建Flutter Android运行环境
    (1)电脑上安装配置java JDK
    (2)电脑上安装Android Studio
    (3)电脑上安装配置Flutter SDK
    (4)电脑上配置Flutter国内镜像
        FLUTTER_STORAGE_BASE_URL:https://storage.flutter-io.cn
        PUB_HOSTED_URL:https://pub.flutter-io.cn
    (5)运行flutter doctor命令检查环境是否配置成功
    (6)打开Android studio安装Flutter Dart插件
    (7)创建Flutter项目
    (8)Android Studio中导入运行Flutter项目
    (9)运行Flutter项目
        flutter run
            r键:点击后热加载,R键:重新编译
            p键:显示网络布局
            o键:切换Android与ios预览模式
            q键:退出预览模式

2.文件夹说明
    android:android平台相关代码
    ios:ios平台相关代码
    lib:flutter相关代码,我们主要编写也在这个文件夹
    test:主要用于存放测试代码
    pubspec.yaml:配置文件,一般存放一些第三方库的依赖

3.Flutter把内容单独抽离成一个组件
    在Flutter中自定义组件其实就是一个类,这个类需要继承StatelessWidget/StatefulWidget
    StatelessWidget:无状态组件,状态不可变的widget
    StatefulWidget:有状态组件,持有的状态可能在widget生命周期改变

4.MaterialApp和Scaffold
    来源:https://segmentfault.com/a/1190000018445793?utm_source=tag-newest
    MaterialApp:MaterialApp是一个方便的widget,它封装了应用程序实现Material Desgin所需要的一些Widget,一般作为顶层的widget使用
        属性:
            title:String类型,该属性在Android应用管理器的App上方显示,对于ios是没有效果的
            home:Widget类型,这是在应用程序正常启动时首先显示的Widget,除非指定了initialRoute。如果initialRoute显示失败,也该显示该Widget。
                 需要注意的是, 如果你指定了home属性,则在routes的路由表中不允许出现/的命名路由
            routes:Map类型,是应用的顶级路由表。当我们再使用Navigator.pushNamed进行命名路由的跳转时,会在此路表中进行查找并跳转。如果你的应用程序只有一个页面,则无需使用routes,直接指定home对应的Widget即可
            theme:主题
                theme: ThemeData(
                    primarySwatch: Colors.yellow
                )

    Scaffold:Scaffold通常被用作MaterialApp的子Widget,它会填充可用空间,占据整个窗口或设备屏幕。Scaffold提供了大多数应用程序都应该具备的功能,例如顶部的appBar,底部的bottomNavigationBar,隐藏的侧边栏drawer等。
        属性:
            appBar:PreferredSizeWidget类型,显示在Scaffold的顶部区域。
            drawer:Widget drawer类型,通常用来形成一个汉堡包按钮显示其侧边栏
            bottomNavigationBar:Widget bottomNavigationBar类型,用户显示底部的tab栏,items必须大于2个
            body:Widget类型,Scaffold的主体内容

    如:
        import 'package:flutter/material.dart';

        void main(){
          runApp(MyApp());
        }

        //自定义组件
        class MyApp extends StatelessWidget{
          @override
          Widget build(BuildContext context){
            return MaterialApp(
              title: '王清最帅',
              home: Scaffold(
                appBar: AppBar(
                  title: Text('Flutter Demo')
                ),
                body: HomeContent(),
              ),
              theme: ThemeData(
                primarySwatch: Colors.yellow
              ),
            );
          }
        }

        class HomeContent extends StatelessWidget{
          @override
          Widget build(BuildContext context) {
            return Center(
              child: Text(
                '你好,flutter,我叫王清呀',
                textDirection: TextDirection.ltr,
                style: TextStyle(
                  // 所有数字都应该是double类型
                  fontSize: 40.0,
                  color: Colors.blue,
                  // color: Color.fromRGBO(200, 200, 200, 0.6)
                ),
              ),
            );
          }
        }

5.Container组件、Text组件
    Container(
        // 设置子元素
        child: Text(
            // 内容
            '王清最帅',
            // 文字居中显示
            textAlign: TextAlign.center,
            // 文本超出显示省略号
            overflow: TextOverflow.ellipsis,
            // 文本显示最大行数
            maxLines: 1,
            // 文字显示倍率
            textScaleFactor: 1.5,
            // 文字的样式设置
            style: TextStyle(
              fontSize: 20.0,
              color: Colors.blue,
              // 字间隙
              letterSpacing:5,
              // 字体样式 italic 斜体
              fontStyle:  FontStyle.italic,
              // 字体加粗
              fontWeight: FontWeight.w300,
              // 文字装饰线 lineThrough 删除线 overline 上划线 underline 下划线
              decoration: TextDecoration.underline,
              // 文字下划线颜色
              decorationColor: Colors.black,
              // 下划线风格 dashed dotted 虚线 double 两根线 solid 一根实线 wavy 波浪线
              decorationStyle: TextDecorationStyle.wavy,
              // 单词间隙
              wordSpacing: 10
            ),
        ),
        // 高度
        height: 300.0,
        // 宽度
        width: 300.0,
        // 设置背景颜色,但是不能与BoxDecoration同时设置
        // color: Colors.black,
        // 背景装饰:设置边框、背景色、背景图片、圆角等属性
        decoration:
          BoxDecoration(
            // 背景色
            color: Colors.yellow,
            // 边框设置
            border: Border.all(
              // 边框颜色
              color: Colors.blue,
              // 边框宽度
              width: 2.0
            ),
            // 设置圆角
            borderRadius: BorderRadius.all(
              Radius.circular(10)
            )
          ),
          // 内边距
          // padding: EdgeInsets.all(10),
          padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
          // 外边距
          margin: EdgeInsets.fromLTRB(10, 10, 10, 10),
          // 转换
          // transform: Matrix4.translationValues(100, 0, 0),
          transform: Matrix4.rotationZ(0.1),
          // 内部内容显示的位置
          alignment: Alignment.bottomLeft,
    )

6.图片组件
    Image.asset 本地图片
    Image.network 远程图片

    Image.network基本属性:
        child: Image.network(
             // 链接src
            'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1588676390324&di=fc02867b89bc67ad7ede0ebd95cbdfe3&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20180227%2Fcf96af3dc6a348c18d60064de6c4f88d.png',
             // 图片的对齐方式
             alignment: Alignment.center,
             // 设置图片区域颜色,单独设置之后将图片覆盖
             color: Colors.blue,
             colorBlendMode: BlendMode.colorBurn,
             // 控制图片的拉伸和挤压,是根据父容器来的
             /*
             *    BoxFit.fill:全图显示,图片会被拉伸并且充满父容器
             *    BoxFit.contain:全图显示,按照原比例
             *    BoxFit.cover:图片要充满整个容器,还不变形
             *    BoxFit.fitWidth:横向充满
             *    BoxFit.fitHeight:纵向充满
             *    BoxFit.scaleDown:此属性不允许显示超过原图片大小,可小不可大
             * */
             fit: BoxFit.scaleDown,
             // 平铺
             repeat: ImageRepeat.repeatY,
             // width 和 height属性一般结合ClipOval才能看到效果
             width: 300
        )
    实现圆角以及圆形图片:
        第一种方式:
            child: Container(
                width: 300.0,
                height: 300.0,
                decoration: BoxDecoration(
                  color: Colors.yellow,
                  borderRadius: BorderRadius.circular(150),
                  image: DecorationImage(
                    image: NetworkImage('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1588676390324&di=fc02867b89bc67ad7ede0ebd95cbdfe3&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20180227%2Fcf96af3dc6a348c18d60064de6c4f88d.png'),
                    fit: BoxFit.cover
                  )
                ),
            )
        第二种方式:
            child: Container(
                child: ClipOval(
                  child: Image.network(
                    'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1588676390324&di=fc02867b89bc67ad7ede0ebd95cbdfe3&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20180227%2Fcf96af3dc6a348c18d60064de6c4f88d.png',
                    width: 300,
                    height: 300,
                  ),
                ),
            )

    Image.asset 本地图片:
        1.在根目录新建images目录,在目录下新建2.0x、3.0x、4.0x目录,在每个文件夹引入需要的图片
        如下图1;
        2.修改pubspec.yaml声明一下添加的图片文件
        如下图2;
        3.引用
        	child: Container(
		        child: Image.asset('images/timg.jpg'),
		     )
7.ListView基础列表组件、水平列表组件、图表组件
    ListView:Flutter中通过ListView来定义列表项,支持水平方向和垂直方向,通过一个属性即可,列表分类:
        垂直列表、垂直图文列表、水平列表、动态列表、矩阵式列表
    参数:
        scrollDirection:
            Axis.horizontal 水平列表
            Axis.Vertical 垂直列表
        padding: 内边距
        reverse: 组件反向排序
        children: 列表元素
    基本列表实例:
        ListView(
          padding: EdgeInsets.all(10),
          children: [
            ListTile(
              // 左边设置图标
              leading: Icon(
                Icons.subtitles,
                color: Colors.yellow,
                size: 30,
              ),
              title: Text('王清帅帅哒1'),
              subtitle: Text('王清将会越来越帅啦'),
            ),
            ListTile(
              title: Text('王清帅帅哒2'),
              subtitle: Text('王清将会越来越帅啦'),
              // 右边设置图标
              trailing: Icon(Icons.chevron_right),
            ),
            ListTile(
              leading: Image.network('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1588676390324&di=fc02867b89bc67ad7ede0ebd95cbdfe3&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20180227%2Fcf96af3dc6a348c18d60064de6c4f88d.png'),
              title: Text('王清帅帅哒3'),
              subtitle: Text('王清将会越来越帅啦')
            )
          ],
        )
8.动态列表
     方法一:
        class HomeContent extends StatelessWidget{
          // 自定义方法
          List getData(){
            return ['王清最帅1','王清最帅2','王清最帅3','王清最帅4'].map((item){
                  return ListTile(
                      title: Text(item),
                  );
            }).toList();
          }
          @override
          Widget build(BuildContext context) {
            return ListView(
              children: this.getData(),
            );
          }
        }
     方法二:
        class HomeContent extends StatelessWidget{
          // 自定义方法
          List getData(){
            return ['王清最帅1','王清最帅2','王清最帅3','王清最帅4'];
          }
        
          @override
          Widget build(BuildContext context) {
            return ListView.builder(
                itemCount: this.getData().length,
                itemBuilder: (context,index){
                  return ListTile(
                    title: Text(this.getData()[index]),
                  );
                }
            );
          }
        }
 9.网格列表(GridView)
    scrollDirection 滚动方向
    padding 内边距
    resolve 组件反向排序 bool
    crossAxisSpacing 水平子Widget之间间距
    mainAxisSpacing 垂直子Widget之间间距
    crossAxisCount 一行的Widget数量
    childAspectRatio 子Widget宽高比例
    children []
    gridDelegate 控制布局主要用在GridVIew.builder里面

    方法一:通过GridView.count实现网格布局
        class HomeContent extends StatelessWidget{
          // 自定义方法
          List getData(){
            List list = ['图片1','图片2','图片3'];
            return list.map((item){
                return Container(
                  // Column组件会垂直方向布局
                  child: Column(
                    children: [
                      Image.network(
                          'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1588676390324&di=fc02867b89bc67ad7ede0ebd95cbdfe3&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20180227%2Fcf96af3dc6a348c18d60064de6c4f88d.png',
                      ),
                      // 增加图片和文字之间的距离
                      SizedBox(height: 10),
                      Text(item)
                    ],
                  ),
                  alignment: Alignment.center,
                  decoration: BoxDecoration(
                    border: Border.all(
                      color: Colors.red,
                      width: 1
                    )
                  ),
                );
            }).toList();
          }

          @override
          Widget build(BuildContext context) {
            return GridView.count(
              crossAxisCount: 2,
              crossAxisSpacing: 10,
              mainAxisSpacing: 10,
              children: this.getData(),
              childAspectRatio: 1.2
            );
          }
        }

    方法二:通过GridView.builder实现网格布局
        class HomeContent extends StatelessWidget{
          // 自定义方法
          List getData(){
            List list = ['图片1','图片2','图片3'];
            return list;
          }

          @override
          Widget build(BuildContext context) {
            return GridView.builder(
              padding: EdgeInsets.all(10),
              itemCount: this.getData().length,
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2,
                mainAxisSpacing: 10,
                crossAxisSpacing: 10
              ),
              itemBuilder: (context, index){
                return Container(
                  // Column组件会垂直方向布局
                  child: Column(
                    children: [
                      Image.network(
                        'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1588676390324&di=fc02867b89bc67ad7ede0ebd95cbdfe3&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20180227%2Fcf96af3dc6a348c18d60064de6c4f88d.png',
                      ),
                      // 增加图片和文字之间的距离
                      SizedBox(height: 10),
                      Text(this.getData()[index])
                    ],
                  ),
                  alignment: Alignment.center,
                  decoration: BoxDecoration(
                      border: Border.all(
                          color: Colors.red,
                          width: 1
                      )
                  ),
                );
              },
            );
          }
        }

10. Padding、Row、Colomn、Expanded组件
    Padding:有的组件没有Padding属性,就可以使用Padding组件去替代
        属性:padding:内边距值  child:子widget
        如:
            Padding(
                padding: EdgeInsets.all(10),
                child: Image.network(
                    'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1588676390324&di=fc02867b89bc67ad7ede0ebd95cbdfe3&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20180227%2Fcf96af3dc6a348c18d60064de6c4f88d.png',
                    fit: BoxFit.fill
                ),
             )
    Row/Column:水平/垂直布局组件
        属性:mainAxisAlignment 主轴的排序方式
             crossAxisAlignment 次轴的排序方式
             children 组件子元素
        实例:
            class HomeContent extends StatelessWidget{
              @override
              Widget build(BuildContext context) {
                return Container(
                  height: 400,
                  color: Colors.pink,
                  child: Row /* Column */(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      IconContainer(Icons.search),
                      IconContainer(Icons.home),
                      IconContainer(Icons.select_all)
                    ],
                  ),
                );
              }
            }

            class IconContainer extends StatelessWidget{

              double size;
              Color color;
              IconData icon;

              IconContainer(this.icon,{this.color = Colors.white,this.size = 32});

              @override
              Widget build(BuildContext context) {
                return Container(
                  height: 100,
                  width: 100,
                  color: Colors.red,
                  child: Center(
                    child: Icon(this.icon,size: this.size,color: this.color),
                  ),
                );
              }
            }

    Expanded:类似于web中的Flex布局
        属性:
            flex 元素占整个父Row/Column的比例
            child 子元素
        实例:
            class HomeContent extends StatelessWidget{
              @override
              Widget build(BuildContext context) {
                return Row(
                  children: [
                    Expanded(
                      flex: 1,
                      child: IconContainer(Icons.search,color: Colors.yellow,),
                    ),
                    Expanded(
                      flex: 2,
                      child: IconContainer(Icons.home),
                    ),
                  ],
                );
              }
            }

            class IconContainer extends StatelessWidget{
              double size;
              Color color;
              IconData icon;

              IconContainer(this.icon,{this.color = Colors.red,this.size = 32});

              @override
              Widget build(BuildContext context) {
                return Container(
                  height: 100,
                  width: 100,
                  color: this.color,
                  child: Center(
                    child: Icon(this.icon,size: this.size,color: Colors.white),
                  ),
                );
              }
            }

11.Stack层叠组件
    Stack组件:
        属性: alignment 配置所有子元素的显示位置
              children  子组件
        实例:
            Stack(
                  // 让元素居中显示
                  // alignment: Alignment.center,
                  // 参数分别为x,y轴,值的范围为[-1,1],原点为[0,0]显示为居中
                  alignment: Alignment(-1,1),
                  children: [
                    Container(
                      height: 400,
                      width: 300,
                      color: Colors.red,
                    ),
                    Container(
                      height: 200,
                      width: 150,
                      color: Colors.yellow,
                    )
                  ],
            )
    Align:如果内部包含多个组件则无法定位,需要对每个内部组件单独定位
        Container(
              height: 400,
              width: 300,
              color: Colors.red,
              child: Stack(
                children: [
                  Align(
                    alignment: Alignment.topLeft,
                    child: Icon(Icons.home,size: 32,color: Colors.white),
                  ),
                  Align(
                    alignment: Alignment.center,
                    child: Icon(Icons.search,size: 32,color: Colors.white),
                  ),
                  Align(
                    alignment: Alignment.bottomRight,
                    child: Icon(Icons.send,size: 32,color: Colors.white),
                  )
                ],
              ),
        )

    Positioned:实现的功能与Align一致
        top、bottom、left、right:距离上下左右的距离
        child:子组件
        实例:
            Container(
                  height: 400,
                  width: 300,
                  color: Colors.red,
                  child: Stack(
                    children: [
                      Positioned(
                        left: 0,
                        child: Icon(Icons.home,size: 32,color: Colors.white),
                      ),
                      Positioned(
                        left: 150,
                        bottom: 200,
                        child: Icon(Icons.search,size: 32,color: Colors.white),
                      ),
                      Positioned(
                        right: 0,
                        bottom: 0,
                        child: Icon(Icons.send,size: 32,color: Colors.white),
                      )
                    ],
                  ),
            )

12.AspectRatio、Card卡片组件
    AspectRatio:根据父元素宽高设置去调整子元素的宽高比
        属性:
            Container(
                  width: 300,
                  color: Colors.red,
                  child: AspectRatio(
                    aspectRatio: 2,
                    child: Container(
                      color: Colors.yellow,
                    ),
                  ),
            )

    Card:
        属性:
            margin:外边距
            child:子组件
            shape:card的阴影效果,默认的阴影效果为圆角的长方形边
            color:设置颜色
        实例:
            ListView(
                  children: [
                    Card(
                      color: Colors.yellow,
                      shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.all(Radius.circular(20.0))
                      ),
                      margin: EdgeInsets.all(10),
                      child: Column(
                        children: [
                          ListTile(
                            leading: CircleAvatar(
                              backgroundImage: NetworkImage('https://www.itying.com/images/flutter/3.png'),
                            ),
                            title: Text('张三',style: TextStyle(fontSize: 28)),
                            subtitle: Text('高级工程师'),
                          )
                        ],
                      ),
                    )
                  ],
            )

13.Wrap组件
    Wrap可以实现流布局,单行的Wrap跟Row表现几乎一致,如果宽度不够,则会自动撑开
    属性:
        direction:主轴的方向,默认水平
        alignment:主轴的对其方式
        spacing:主轴方向上的间距
        textDirection:文字方向
        verticalDirection:定义了children摆放顺序,默认为down
        runAlignment:run的对齐方式,run可以理解为新的行或者列,可以理解为纵轴排列方式
        runSpacing:run的间距,可以理解为纵轴间距
    实例:
        class HomeContent extends StatelessWidget{
          @override
          Widget build(BuildContext context) {
            return Wrap(
              // 主轴上的间距
              spacing: 10,
              alignment: WrapAlignment.spaceEvenly,
              runAlignment: WrapAlignment.spaceEvenly,
              children: [
                MyButton('第num季'),
                MyButton('第一季'),
                MyButton('第一季'),
                MyButton('第一一季'),
                MyButton('第一季'),
                MyButton('第一季'),
              ],
            );
          }
        }

        class MyButton extends StatelessWidget{

          String text;
          MyButton(this.text);

          @override
          Widget build(BuildContext context) {
            return RaisedButton(
              child: Text(this.text),
              // 获取主题颜色
              textColor: Theme.of(context).accentColor,
              onPressed: (){
              },
            );
          }
        }

14.Flutter中自定义有状态组件
    快速生成无状态和有状态组件:
        下载flutter snippets插件
    实例:
        // 有状态组件
        class HomePage extends StatefulWidget {
          @override
          _HomePageState createState() => _HomePageState();
        }

        class _HomePageState extends State {
          int num = 0;
          @override
          Widget build(BuildContext context) {
            return Column(
              children: [
                Chip(
                  label: Text('${this.num}'),
                ),
                RaisedButton(
                  child: Text('点击'),
                  onPressed: (){
                    setState(() {
                      this.num++;
                    });
                  },
                )
              ],
            );
          }
        }
 15. BottomNavigationBar 底部导航条
    属性:
        items:底部导航条按钮集合
        iconSize:icon
        currentIndex:默认选中第几个
        onTap:选中变化回调函数
        fixedColor:选中的颜色
        type:BottomNavigationBarType.fixed/BottomNavigationBarType.shifting
    实例:
        main.js文件:
            import 'package:flutter/cupertino.dart';
            import 'package:flutter/material.dart';

            import 'pages/Tabs/Tabs.dart';
            void main(){
              runApp(MyApp());
            }

            //自定义组件
            class MyApp extends StatelessWidget{
              @override
              Widget build(BuildContext context){
                return MaterialApp(
                  title: '王清最帅',
                  home: Tabs(),
                  theme: ThemeData(
                    primarySwatch: Colors.blue
                  ),
                );
              }
            }
        Tabs.js文件:
            import 'package:flutter/material.dart';
            import 'Home.dart';
            import 'Category.dart';
            import 'Setting.dart';

            class Tabs extends StatefulWidget {
              @override
              _TabsState createState() => _TabsState();
            }

            class _TabsState extends State {

              int _currentIndex = 0;
              List _pageList = [
                  HomePage(),
                  Category(),
                  Setting()
              ];
              List _pageName = [
                {
                  "icon": Icon(Icons.home),
                  "title": Text('首页')
                },
                {
                  "icon": Icon(Icons.category),
                  "title": Text('分类')
                },
                {
                  "icon": Icon(Icons.settings),
                  "title": Text('设置')
                },
              ];

              @override
              Widget build(BuildContext context) {
                return Scaffold(
                  appBar: AppBar(
                      title: _pageName[_currentIndex]['title']
                  ),
                  body: this._pageList[this._currentIndex],
                  bottomNavigationBar: BottomNavigationBar(
                    currentIndex: this._currentIndex,
                    fixedColor: Colors.red,
                    // 如果底部按钮超过3个就需要设置type
                    type: BottomNavigationBarType.fixed,
                    items: _pageName.map((value){
                      return BottomNavigationBarItem(
                        icon: value['icon'],
                        title: value['title']
                      );
                    }).toList(),
                    onTap: (int index){
                      print(index);
                      setState(() {
                        this._currentIndex = index;
                      });
                    },
                  ),
                );
              }
            }

16.路由
    在Flutter中通过Navigator组件管理路由导航,并提供了管理堆栈的方法,如:Navigator.push和Navigator.pop
    配置理由跳转的方式:1.基本路由 2.命名路由

    1.基本路由(实例:Home.dart跳转至SearchPage.dart页面)
    Home.dart:
        import 'package:flutter/material.dart';
        import '../SearchPage.dart';

        class HomePage extends StatefulWidget {
          @override
          _HomePageState createState() => _HomePageState();
        }

        class _HomePageState extends State {
          @override
          Widget build(BuildContext context) {
            return Container(
              child: Center(
                child: RaisedButton(
                  child: Text('跳转到搜索页面'),
                  onPressed: (){
                    // 路由跳转
                    Navigator.of(context).push(
                      MaterialPageRoute(
                        // 传值
                        builder: (context)=> SearchPage(content: '王清最帅')
                      )
                    );
                  },
                  color: Theme.of(context).accentColor,
                  textTheme: ButtonTextTheme.primary,
                ),
              ),
            );
          }
        }
    SearchPage.dart:
        import 'package:flutter/material.dart';

        class SearchPage extends StatelessWidget {
          String content;
          SearchPage({this.content="搜索页"});

          @override
          Widget build(BuildContext context) {
            return Scaffold(
              floatingActionButton: FloatingActionButton(
                child: Text('返回'),
                onPressed: (){
                  // 返回上级页面
                  Navigator.of(context).pop();
                },
              ),
              appBar: AppBar(
                title: Text('搜素页')
              ),
              body: Column(
                children: [
                  Text(this.content),
                ],
              ),
            );
          }
        }

    2.命名路由
        (1)不传参的命名路由
            main.dart:
                import 'pages/Search.dart';
                import 'pages/Tabs.dart';
                class MyApp extends StatelessWidget{
                  @override
                  Widget build(BuildContext context){
                    return MaterialApp(
                      title: '王清最帅',
                      home: Tabs(),
                      routes: {
                        '/search': (context) => SearchPage()
                      },
                    );
                  }
                }
            Home.dart:
                import 'package:flutter/material.dart';
                class HomePage extends StatefulWidget {
                  @override
                  _HomePageState createState() => _HomePageState();
                }
                class _HomePageState extends State {
                  @override
                  Widget build(BuildContext context) {
                    return Container(
                      child: Center(
                        child: RaisedButton(
                          child: Text('跳转到搜索页面'),
                          onPressed: (){
                             // 跳转路由,但是不可以传参
                             Navigator.pushNamed(context, '/search');
                          },
                          color: Theme.of(context).accentColor,
                          textTheme: ButtonTextTheme.primary,
                        ),
                      ),
                    );
                  }
                }

        (2)传参的命名路由
            新建route.dart:
                import 'package:flutter/material.dart';
                import 'pages/Search.dart';
                import 'pages/Tabs.dart';
                final routes = {
                  '/': (context,{arguments}) => Tabs(arguments: arguments),
                  '/search': (context,{arguments}) => SearchPage(arguments: arguments)
                };

                var onGenerateRoute = (RouteSettings settings) {
                  final String name = settings.name;
                  final Function pageContentBuilder = routes[name];
                  if (pageContentBuilder != null) {
                    if (settings.arguments != null) {
                      final Route route = MaterialPageRoute(
                          builder: (context) =>
                              pageContentBuilder(context, arguments: settings.arguments));
                      return route;
                    } else {
                      final Route route = MaterialPageRoute(
                          builder: (context) => pageContentBuilder(context)
                      );
                      return route;
                    }
                  }
                };

            main.dart:
                import 'package:flutter/material.dart';
                import 'pages/Tabs/Tabs.dart';
                import 'route.dart';
                void main(){
                  runApp(MyApp());
                }

                //自定义组件
                class MyApp extends StatelessWidget{
                  @override
                  Widget build(BuildContext context){
                    return MaterialApp(
                      title: '王清最帅',
                      initialRoute: '/',
                      onGenerateRoute: onGenerateRoute
                    );
                  }
                }
            Home.dart:
                import 'package:flutter/material.dart';

                class HomePage extends StatefulWidget {
                  @override
                  _HomePageState createState() => _HomePageState();
                }

                class _HomePageState extends State {
                  @override
                  Widget build(BuildContext context) {
                    return Container(
                      child: Center(
                        child: RaisedButton(
                          child: Text('跳转到搜索页面'),
                          onPressed: (){
                             // 跳转路由携带参数
                             Navigator.pushNamed(context, '/search', arguments:{
                               "id": '1234567'
                             });
                          },
                          color: Theme.of(context).accentColor,
                          textTheme: ButtonTextTheme.primary,
                        ),
                      ),
                    );
                  }
                }
            (1)无状态组件获取参数
            Search.dart:
                import 'package:flutter/material.dart';

                class SearchPage extends StatelessWidget {
                  final arguments;
                  SearchPage({this.arguments});

                  @override
                  Widget build(BuildContext context) {
                    return Scaffold(
                      floatingActionButton: FloatingActionButton(
                        child: Text('返回'),
                        onPressed: (){
                          // 返回上级页面
                          Navigator.of(context).pop();
                        },
                      ),
                      appBar: AppBar(
                        title: Text('搜素页')
                      ),
                      body: Text('id:${this.arguments['id']}')
                    );
                  }
                }
            (2)有状态组件获取参数
                import 'package:flutter/material.dart';
                class SearchPage extends StatefulWidget {
                  Map arguments;
                  Search({Key key, this.arguments}) : super(key: key);
                  @override
                  _SearchState createState() => _SearchState(arguments: this.arguments);
                }

                class _SearchState extends State {
                  Map arguments;
                  _SearchState({this.arguments});

                  @override
                  Widget build(BuildContext context) {
                    return Scaffold(
                      appBar: AppBar(
                        title: Text('搜索'),
                      ),
                      body: Container(
                        child: Text('id: ${this.arguments["id"]}'),
                      ),
                    );
                  }
                }
    3.不使用命名路由的新方法
        Home.dart:
        import 'package:flutter/material.dart';
        import '../Search.dart';

        class HomePage extends StatefulWidget {
          @override
          _HomePageState createState() => _HomePageState();
        }

        class _HomePageState extends State {
          @override
          Widget build(BuildContext context) {
            return Container(
              child: Center(
                child: FlatButton(
                  child: Text('跳转到搜索页面'),
                  onPressed: (){
                     Navigator.of(context).push(
                       MaterialPageRoute(
                         builder: (context){
                           return Search();
                         },
                         settings: RouteSettings(arguments: {"id": 'abc'}),
                         fullscreenDialog: true
                       )
                     );
                  },
                  color: Theme.of(context).accentColor,
                  textTheme: ButtonTextTheme.primary,
                ),
              ),
            );
          }
        }

        Search.dart:
            import 'package:flutter/material.dart';
            class Search extends StatefulWidget {
              @override
              _SearchState createState() => _SearchState();
            }

            class _SearchState extends State {
              @override
              Widget build(BuildContext context) {
                Map args = ModalRoute.of(context).settings.arguments;
                return Scaffold(
                  appBar: AppBar(
                    title: Text('搜索'),
                  ),
                  body: Container(
                    child: Text('id: ${args["id"]}'),
                  ),
                );
              }
            }

17.路由替换 返回到根目录
    路由替换:
        作用:返回的时候可以直接跳转到进入的页面
        RaisedButton(
                child: Text('再次跳转'),
                onPressed: (){
                  Navigator.pushReplacementNamed(context, '/');
                },
        )

    返回根目录:
        Navigator.of(context).pushAndRemoveUntil(
            MaterialPageRoute(
              builder: (context) => Tabs(index: 1)
            ),
            (route) => route == null
        )
18. AppBar自定义顶部导航  TabBar定义顶部Tab切换
    AppBar:
        属性:
            leading:在标题前面显示的图标
            title:标题
            actions:通常使用IconButton来表示
            bottom:通常放tabBar,标题下面显示一个Tab导航栏
            backgroundColor:导航背景颜色
            iconTheme:图标样式
            textTheme:文字样式
            centerTitle:标题是否居中显示
        实例:
            import 'package:flutter/material.dart';
            class AppBarDemo extends StatelessWidget {
              @override
              Widget build(BuildContext context) {
                return Scaffold(
                  appBar: AppBar(
                    title: Text('AppBarDemo'),
                    // 标题是否居中显示
                    centerTitle: true,
                    // 背景颜色
                    backgroundColor: Colors.red,
                    // 左边的图标
                    leading: IconButton(
                      icon: Icon(Icons.menu, color: Colors.white),
                      onPressed: (){
                        Navigator.pop(context);
                      },
                    ),
                    // 右边的图标
                    actions: [
                      IconButton(
                        icon: Icon(Icons.search),
                        onPressed: (){
                          print('search');
                        },
                      ),
                      IconButton(
                        icon: Icon(Icons.home),
                        onPressed: (){
                          print('home');
                        },
                      )
                    ],
                  ),
                  body: Text('AppBarDemo'),
                );
              }
            }

    Tab切换第一种方式:
        TabBar:
            import 'package:flutter/material.dart';
            class AppBarDemo extends StatelessWidget {
              @override
              Widget build(BuildContext context) {
                return DefaultTabController(
                  length: 7,
                  child: Scaffold(
                    appBar: AppBar(
                      title: Text('今日头条'),
                      // 标题是否居中显示
                      centerTitle: true,
                      // 背景颜色
                      backgroundColor: Colors.deepOrange,
                      bottom: TabBar(
                        // 是否可滚动
                        isScrollable: true,
                        // 下划线颜色
                        indicatorColor: Colors.yellow,
                        // 下划线高度
                        indicatorWeight: 4,
                        // label字体颜色
                        labelColor: Colors.amberAccent,
                        // 未选中颜色
                        unselectedLabelColor: Colors.white,
                        // 下划线与文字等宽
                        indicatorSize: TabBarIndicatorSize.label,
                        tabs: [
                          Tab(text: "关注"),
                          Tab(text: "热门"),
                          Tab(text: "推荐"),
                          Tab(text: "上海"),
                          Tab(text: "精品课"),
                          Tab(text: "职场"),
                          Tab(text: "视频"),
                        ]
                      ),
                    ),
                    // TabBarView里面的内容是跟TabBar中的内容一一对应的
                    body: TabBarView(
                      children: [
                        Text('关注'),
                        Text('热门'),
                        Text('推荐'),
                        Text('上海'),
                        Text('精品课'),
                        Text('职场'),
                        Text('视频'),
                      ],
                    ),
                  ),
                );
              }
            }
        实现头条样式:
            import 'package:flutter/material.dart';

            class AppBarDemo extends StatelessWidget {
              @override
              Widget build(BuildContext context) {
                return DefaultTabController(
                  length: 7,
                  child: Scaffold(
                    appBar: AppBar(
                      title: TabBar(
                        // 是否可滚动
                          isScrollable: true,
                          // 下划线颜色
                          indicatorColor: Colors.yellow,
                          // 下划线高度
                          indicatorWeight: 4,
                          // label字体颜色
                          labelColor: Colors.amberAccent,
                          tabs: [
                            Tab(text: "关注"),
                            Tab(text: "热门"),
                            Tab(text: "推荐"),
                            Tab(text: "上海"),
                            Tab(text: "精品课"),
                            Tab(text: "职场"),
                            Tab(text: "视频"),
                          ]
                      ),
                      // 标题是否居中显示
                      centerTitle: true,
                      // 背景颜色
                      backgroundColor: Colors.deepOrange
                    ),
                    // TabBarView里面的内容是跟TabBar中的内容一一对应的
                    body: TabBarView(
                      children: [
                        Text('关注'),
                        Text('热门'),
                        Text('推荐'),
                        Text('上海'),
                        Text('精品课'),
                        Text('职场'),
                        Text('视频'),
                      ],
                    ),
                  ),
                );
              }
            }

    Tab切换的第二种方式:
        import 'package:flutter/material.dart';

        class AppBarDemo extends StatefulWidget {
          @override
          _AppBarDemoState createState() => _AppBarDemoState();
        }

        class _AppBarDemoState extends State with SingleTickerProviderStateMixin {
          TabController _tabController;
          @override
          void initState() {
            super.initState();
            _tabController = new TabController(
                // Tab的个数
                length: 2,
                vsync: this
            );
            _tabController.addListener((){
              // 打印当前的tab index
              print(_tabController.index);
            });
          }

          // 组件销毁的声明周期函数
          @override
          void dispose() {
            super.dispose();
            _tabController.dispose();
          }

          @override
          Widget build(BuildContext context) {
            return Scaffold(
              appBar: AppBar(
                title: Text('今日头条'),
                bottom: TabBar(
                  controller: this._tabController,
                  tabs: [
                    Tab(text: '热销'),
                    Tab(text: '推荐')
                  ],
                ),
              ),
              body: TabBarView(
                controller: this._tabController,
                children: [
                  Text('热销'),
                  Text('推荐')
                ],
              ),
            );
          }
        }

19.按钮组件
    常见的按钮组件:
        RaisedButton:凸起的按钮,其实就是Material Design风格的按钮
        FlatButton:扁平化按钮
        OutlineButton:线框按钮
        IconButton:图标按钮
        ButtonBar:按钮组
        FloatingActionButton:浮动按钮

    属性:
        onPressed:点击回调
        child:文本组件
        textColor: 文本颜色
        color:按钮颜色
        disabledTextColor:按钮禁用时的文字颜色
        disabledColor:按钮禁用时的按钮颜色
        splashColor:点击按钮时的水波纹的颜色
        highlightColor:长按按钮后的颜色
        elevation:阴影的范围
        padding:内边距
        shape:按钮的形状

    (1)给按钮设置宽高
        Container(
            height: 60,
            width: 200,
            child: RaisedButton(
              child: Text('跳转到AppBAr'),
              color: Colors.blue,
              textColor: Colors.white,
              elevation: 20,
              onPressed: (){
              },
            ),
        )
    (2)设置全屏按钮
        Row(
            children: [
              Expanded(
                child: Container(
                  margin: EdgeInsets.fromLTRB(10, 0, 10, 0),
                  height: 60,
                  child: RaisedButton(
                    child: Text('跳转到AppBAr'),
                    color: Colors.blue,
                    textColor: Colors.white,
                    elevation: 20,
                    onPressed: (){
                    },
                  ),
                ),
              )
            ],
        )
    (3)给按钮加图标
        RaisedButton.icon(
          // 代表按钮disabled
          onPressed: null,
          icon: Icon(Icons.search),
          label: Text('图标按钮')
        )
    (4)设置按钮的形状(圆角、圆形)
        圆角按钮:
            RaisedButton(
                child: Text('按钮'),
                color: Colors.blue,
                onPressed: (){},
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10)
                ),
            )
        圆形按钮:
            Container(
                height: 80,
                child: RaisedButton(
                  child: Text('按钮'),
                  color: Colors.blue,
                  onPressed: (){},
                  shape: CircleBorder(
                      side: BorderSide(
                          color: Colors.blue
                      )
                  ),
                ),
            )
    (5)按钮组
        Container(
            child: Row(
              children: [
                ButtonBar(
                    children: [
                      RaisedButton(
                          child: Text('按钮1'),
                          onPressed: (){}
                      ),
                      RaisedButton(
                          child: Text('按钮2'),
                          onPressed: (){}
                      ),
                      RaisedButton(
                          child: Text('按钮2'),
                          onPressed: (){}
                      )
                    ]
                )
              ],
        )
    (6)FloatingActionButton
        属性:
            child:一般为Icon
            tooltip:被长按时显示
            backgroundColor:背景颜色
            elevation:未点击的阴影
            highlightElevation:点击时阴影值
            shape:形状
            mini:是否为mini类型,默认false
        实例:(实现咸鱼底部)
            import 'package:flutter/material.dart';
            import 'Home.dart';
            import 'Category.dart';
            import 'Setting.dart';

            class Tabs extends StatefulWidget {
              final index;
              Tabs({this.index =0});
              @override
              _TabsState createState() => _TabsState(this.index);
            }

            class _TabsState extends State {

              int _currentIndex;

              _TabsState(this._currentIndex);
              List _pageList = [
                  HomePage(),
                  Category(),
                  Setting()
              ];
              List _pageName = [
                {
                  "icon": Icon(Icons.home),
                  "title": Text('首页')
                },
                {
                  "icon": Icon(Icons.category),
                  "title": Text('分类')
                },
                {
                  "icon": Icon(Icons.settings),
                  "title": Text('设置')
                },
              ];

              @override
              Widget build(BuildContext context) {
                return Scaffold(
                  appBar: AppBar(
                      title: _pageName[_currentIndex]['title']
                  ),
                  body: this._pageList[this._currentIndex],
                  floatingActionButton: Container(
                    height: 65,
                    width: 65,
                    padding: EdgeInsets.all(5),
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(40),
                      color: Colors.white
                    ),
                    child: FloatingActionButton(
                      child: Icon(Icons.add),
                      backgroundColor: Colors.amber,
                      onPressed: (){
                        setState(() {
                          this._currentIndex = 1;
                        });
                      },
                    ),
                  ),
                  floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
                  bottomNavigationBar: BottomNavigationBar(
                    currentIndex: this._currentIndex,
                    fixedColor: Colors.red,
                    type: BottomNavigationBarType.fixed,
                    items: _pageName.map((value){
                      return BottomNavigationBarItem(
                        icon: value['icon'],
                        title: value['title']
                      );
                    }).toList(),
                    onTap: (int index){
                      print(index);
                      setState(() {
                        this._currentIndex = index;
                      });
                    },
                  ),
                );
              }
            }

20.Drawer侧边栏
    Drawer/endDrawer:左侧边栏/右侧边栏
    DrawerHeader:
        属性:
            decoration:设置顶部背景颜色
            child:配置子元素
            padding:内边距
            margin:外边距
    实例:
        Drawer(
            child: Column(
              children: [
                Row(
                  children: [
                    Expanded(
                      child: DrawerHeader(
                        child: Text(''),
                        decoration: BoxDecoration(
                          image: DecorationImage(
                            image: NetworkImage('https://www.itying.com/images/flutter/1.png'),
                            fit: BoxFit.cover
                          )
                        ),
                      ),
                    )
                  ],
                ),
                ListTile(
                  leading: CircleAvatar(
                    child: Icon(Icons.home),
                  ),
                  title: Text('我的空间'),
                  onTap: (){
                      // 侧边栏隐藏
                      Navigator.of(context).pop();
                      Navigator.pushNamed(context, '/login');
                  },
                ),
                ListTile(
                  leading: CircleAvatar(
                    child: Icon(Icons.account_circle),
                  ),
                  title: Text('我的好友'),
                )
              ],
            ),
        )
    UserAccountsDrawerHeader:
        属性:
            decoration:设置顶部背景颜色
            accountName:账号名称
            accountEmail:账户邮箱
            currentAccountPicture:用户头像
            otherAccountsPictures:用来设置当前用户的其他头像
            margin:外边距
        实例:
            Drawer(
                child: Column(
                  children: [
                    Row(
                      children: [
                        Expanded(
                          child: UserAccountsDrawerHeader(
                            accountName: Text('王清'),
                            accountEmail: Text('[email protected]'),
                            currentAccountPicture: CircleAvatar(
                              backgroundImage: NetworkImage(
                                  'https://www.itying.com/images/flutter/1.png'
                              ),
                            ),
                            decoration: BoxDecoration(
                              image: DecorationImage(
                                image: NetworkImage('https://www.itying.com/images/flutter/2.png'),
                                fit: BoxFit.cover
                              )
                            ),
                            otherAccountsPictures: [
                              Image.network('https://www.itying.com/images/flutter/3.png'),
                              Image.network('https://www.itying.com/images/flutter/4.png')
                            ],
                          ),
                        )
                      ],
                    ),
                    ListTile(
                      leading: CircleAvatar(
                        child: Icon(Icons.home),
                      ),
                      title: Text('我的空间'),
                    ),
                    ListTile(
                      leading: CircleAvatar(
                        child: Icon(Icons.account_circle),
                      ),
                      title: Text('我的好友'),
                    )
                  ],
                ),
            )

21.表单组件
    TextField组件:
        maxLines:设置此参数可以把文本框改为多行文本框
        onChanged:文本框改变的时候触发的事件
        decoration:
            hintText:类似于html中的placeholder
            border:配置文本框边框  OutlineInputBorder配合使用
            labelText:label名称
            labelStyle:配置label的样式
        obscureText:把文本框改为密码框
        controller:结合TextEditingController可以配置表单显示默认内容
    实例:
        import 'package:flutter/material.dart';

        class Category extends StatefulWidget {
          @override
          _CategoryState createState() => _CategoryState();
        }

        class _CategoryState extends State {
          // 初始化赋值的时候才需要定义TextEditingController
          var username = new TextEditingController();
          var password;
          @override
          void initState() {
            super.initState();
            this.username.text = '王清';
          }
          @override
          Widget build(BuildContext context) {
            return Container(
              child: Padding(
                padding: EdgeInsets.all(10),
                child: Column(
                  children: [
                    TextField(
                      // 密码框
                      // obscureText: true,
                      decoration: InputDecoration(
                        // 标签前面的Icon
                        //icon:Icon(Icons.airplanemode_active),
                        hintText: "用户名",
                        // 显示边框
                        // border: OutlineInputBorder(),
                        // labelText: "用户名",
                      ),
                      controller: this.username,
                      onChanged: (value){
                          setState(() {
                            this.username.text = value;
                          });
                      },
                    ),
                    TextField(
                      obscureText: true,
                      decoration: InputDecoration(
                        hintText: "密码"
                      ),
                      onChanged: (value){
                        setState(() {
                          this.password = value;
                        });
                      },
                    ),
                    Container(
                      width: double.infinity,
                      child: RaisedButton(
                        child: Text('登录'),
                        color: Colors.blue,
                        onPressed: (){
                          print(this.username.text);
                          print(this.password);
                        },
                      ),
                    )
                  ],
                ),
              ),
            );
          }
        }

    Checkbox组件:
        属性:
            value:true或者false
            onChanged:改变的时候触发事件
            activeColor:选中的颜色
            checkColor:选中的里面对号的颜色
        实例:
            import 'package:flutter/material.dart';

            class Category extends StatefulWidget {
              @override
              _CategoryState createState() => _CategoryState();
            }
            class _CategoryState extends State {
              var flag = true;
              @override
              Widget build(BuildContext context) {
                return Container(
                  child: Padding(
                    padding: EdgeInsets.all(10),
                    child: Column(
                      children: [
                        Checkbox(
                          activeColor: Colors.yellow,
                          checkColor: Colors.red,
                          value: this.flag,
                          onChanged: (value){
                            setState(() {
                              this.flag = value;
                            });
                          },
                        )
                      ],
                    ),
                  ),
                );
              }
            }

    CheckboxListTile:
        value:true或者false
        onChanged:改变的时候触发的事件
        activeColor:选中的颜色
        title:标题
        subtitle:二级标题
        secondary:配置图标或者图片
        selected:选中时候的文字颜色是否跟着变化
        实例:
            import 'package:flutter/material.dart';
            class Category extends StatefulWidget {
              @override
              _CategoryState createState() => _CategoryState();
            }
            class _CategoryState extends State {
              var flag = true;
              @override
              Widget build(BuildContext context) {
                return Container(
                  child: Padding(
                    padding: EdgeInsets.all(10),
                    child: Column(
                      children: [
                        CheckboxListTile(
                          title: Text('标题'),
                          subtitle: Text('子标题'),
                          // 设置图标
                          secondary: Icon(Icons.settings),
                          value: this.flag,
                          selected: true,
                          onChanged: (value){
                            setState(() {
                              this.flag = value;
                            });
                          },
                        )
                      ],
                    ),
                  ),
                );
              }
            }
    Radio:
        属性:
            value:单选的值
            onchanged:改变时触发
            activeColor:选中的颜色
            groupValue:选择组的值
        实例:
            import 'package:flutter/material.dart';

            class Category extends StatefulWidget {
              @override
              _CategoryState createState() => _CategoryState();
            }
            class _CategoryState extends State {
              var sex = 1;
              @override
              Widget build(BuildContext context) {
                return Container(
                  child: Padding(
                    padding: EdgeInsets.all(10),
                    child: Column(
                      children: [
                        Radio(
                          value: 1,
                          onChanged: (value){
                              setState(() {
                                this.sex = value;
                              });
                          },
                          groupValue: this.sex,
                        ),
                        Radio(
                          value: 2,
                          onChanged: (value){
                            setState(() {
                              this.sex = value;
                            });
                          },
                          groupValue: this.sex,
                        )
                      ],
                    ),
                  ),
                );
              }
            }
    RadioListTile:
        属性:
            value:单选的值
            onChanged:改变的时候触发的事件
            activeColor:选中的颜色
            title:标题
            subtitle:二级标题
            secondary:配置图标或者图片
            groupValue:选择组的值
        实例:
            import 'package:flutter/material.dart';
            class Category extends StatefulWidget {
              @override
              _CategoryState createState() => _CategoryState();
            }
            class _CategoryState extends State {
              var sex = 1;
              @override
              Widget build(BuildContext context) {
                return Container(
                  child: Padding(
                    padding: EdgeInsets.all(10),
                    child: Column(
                      children: [
                        RadioListTile(
                          value: 1,
                          groupValue: this.sex,
                          title: Text('标题'),
                          subtitle: Text('子标题'),
                          secondary: Icon(Icons.settings),
                          onChanged: (value){
                              setState(() {
                                this.sex = value;
                              });
                          },
                        ),
                        RadioListTile(
                          value: 2,
                          groupValue: this.sex,
                          title: Text('标题'),
                          subtitle: Text('子标题'),
                          secondary: Icon(Icons.settings),
                          onChanged: (value){
                            setState(() {
                              this.sex = value;
                            });
                          },
                        )
                      ],
                    ),
                  ),
                );
              }
            }

    Switch/SwitchListTile:
        实例:
            import 'package:flutter/material.dart';
            class Category extends StatefulWidget {
              @override
              _CategoryState createState() => _CategoryState();
            }
            class _CategoryState extends State {
              var flag = false;
              @override
              Widget build(BuildContext context) {
                return Container(
                  child: Padding(
                    padding: EdgeInsets.all(10),
                    child: Column(
                      children: [
                        Switch(
                          value: this.flag,
                          onChanged: (value){
                            setState(() {
                              this.flag = value;
                            });
                          },
                        ),
                        SwitchListTile(
                          value: this.flag,
                          title: Text('标题'),
                          subtitle: Text('子标题'),
                          secondary: Icon(Icons.flag),
                          onChanged: (value){
                            setState(() {
                              this.flag = value;
                            });
                          },
                        )
                      ],
                    ),
                  ),
                );
              }
            }
 22.时间组件
    汉化:
        第一步: 配置pubspec.yaml
            dependencies:
              flutter:
                sdk: flutter
              flutter_localizations:
                sdk: flutter
        第二步:配置入口文件
            import 'package:flutter_localizations/flutter_localizations.dart';
            class MyApp extends StatelessWidget{
              @override
              Widget build(BuildContext context){
                return MaterialApp(
                  title: '王清最帅',
                  initialRoute: '/',
                  onGenerateRoute: onGenerateRoute,
                  // 配置多语言
                  localizationsDelegates: [
                    GlobalMaterialLocalizations.delegate,
                    GlobalWidgetsLocalizations.delegate
                  ],
                  supportedLocales: [
                    const Locale("zh", "CH"),
                    const Locale("en", "US")
                  ]
                );
              }
            }
        第三步:
            locale: Locale("zh")

    日期转时间戳:
        var now = new DateTime.now();
        print(now.millisecondsSinceEpoch); // 单位毫秒
    时间戳转日期
        DateTime.fromMillisecondsSinceEpoch(时间戳);
    时间格式转换:
        第三方库 date_format
        配置pubspec.yaml:
            dependencies:
              flutter:
                sdk: flutter
              date_format: ^1.0.6
        使用:
            import 'package:date_format/date_format.dart';
            print(formatDate(DateTime.now(), [yyyy,'年',mm,'月',dd, '日']));
    flutter自带时间组件:
        日期选择 showDatePicker
        时间选择 showTimePicker
        实例:
            import 'package:flutter/material.dart';
            import 'package:date_format/date_format.dart';

            class Category extends StatefulWidget {
              @override
              _CategoryState createState() => _CategoryState();
            }
            class _CategoryState extends State {

              DateTime nowDate = DateTime.now();
              var timeDate = TimeOfDay(hour: 12, minute: 20);

              _showDatePicker() async{
                // 第一种方式获取日期
            //    showDatePicker(
            //      context: context,
            //      // 初始化日期
            //      initialDate: this.nowDate,
            //      // 起始日期
            //      firstDate: DateTime(1980),
            //      // 结束日期
            //      lastDate: DateTime(2020,10,10)
            //    ).then((result){
            //      print(result);
            //    });
                // 第二种方式获取日期
                var result = await showDatePicker(
                    context: context,
                    // 初始化日期
                    initialDate: this.nowDate,
                    // 起始日期
                    firstDate: DateTime(1980),
                    // 结束日期
                    lastDate: DateTime(2020,10,10)
                );
                setState(() {
                  this.nowDate = result;
                });
              }

              _showTimePicker() async{
                var result = await showTimePicker(
                    context: context,
                    initialTime: this.timeDate
                );
                setState(() {
                  this.timeDate = result;
                });
              }

              @override
              Widget build(BuildContext context) {
                return Container(
                  child: Padding(
                    padding: EdgeInsets.all(10),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        // 相当于bottom,但是不显示组件
                        InkWell(
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              Text(formatDate(this.nowDate, [yyyy,'年',mm,'月',dd, '日'])),
                              Icon(Icons.keyboard_arrow_down)
                            ],
                          ),
                          onTap: this._showDatePicker,
                        ),
                        InkWell(
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              Text(this.timeDate.format(context)),
                              Icon(Icons.keyboard_arrow_down)
                            ],
                          ),
                          onTap: this._showTimePicker,
                        )
                      ],
                    ),
                  ),
                );
              }
            }
 23. 第三方库的日期选择器(flutter_cupertino_date_picker)
    flutter_cupertino_date_picker: ^1.0.24
    实例:
        import 'package:flutter/material.dart';
        import 'package:date_format/date_format.dart' as date_format;
        import 'package:flutter_cupertino_date_picker/flutter_cupertino_date_picker.dart';

        class Category extends StatefulWidget {
          @override
          _CategoryState createState() => _CategoryState();
        }
        class _CategoryState extends State {
          var dateTime = DateTime.now();

          _showDatePicker(){
            DatePicker.showDatePicker(
              context,
              onMonthChangeStartWithFirstDate: true,
              pickerTheme: DateTimePickerTheme(
                showTitle: true,
                confirm: Text('确定', style: TextStyle(color: Colors.red)),
                cancel: Text('取消', style: TextStyle(color: Colors.cyan)),
              ),
              minDateTime: DateTime.parse('1980-01-01'),
              maxDateTime: DateTime.parse('2100-01-01'),
              initialDateTime: DateTime.now(),
              // 只显示日期
              // dateFormat: 'yyyy-MMMM-dd',
              // 显示时分秒的时候加上
              dateFormat: 'yy年M月d日 EEE,H时:m分',
              pickerMode: DateTimePickerMode.datetime,

              locale: DateTimePickerLocale.zh_cn,
              onClose: () => print("----- onClose -----"),
              onCancel: () => print('onCancel'),
              onChange: (dateTime, List index) {
                print('dateTime1 $dateTime  $index');
                setState(() {
                  this.dateTime = dateTime;
                });
              },
              onConfirm: (dateTime, List index) {
                print('dateTime2 $dateTime  $index');
                setState(() {
                  this.dateTime = dateTime;
                });
              },
            );
          }

          @override
          Widget build(BuildContext context) {
            return Container(
              child: Padding(
                padding: EdgeInsets.all(10),
                child: Column(
                  children: [
                    Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        InkWell(
                          child: Row(
                            children: [
                              Text(date_format.formatDate(this.dateTime, ['yyyy','-','mm','-','dd',' ','HH',':','nn'])),
                              Icon(Icons.arrow_drop_down)
                            ],
                          ),
                          onTap: _showDatePicker,
                        )
                      ],
                    )
                  ],
                )
              ),
            );
          }
        }

24.轮播图
    第三方组件:flutter_swiper
    实例:
        import 'package:flutter/material.dart';
        import 'package:flutter_swiper/flutter_swiper.dart';

        class Category extends StatefulWidget {
          @override
          _CategoryState createState() => _CategoryState();
        }
        class _CategoryState extends State {
          @override
          Widget build(BuildContext context) {
            return Container(
              child: AspectRatio(
                aspectRatio: 16/9,
                child: new Swiper(
                  itemBuilder: (BuildContext context,int index){
                    return new Image.network(
                        "https://www.itying.com/images/flutter/1.png",
                        fit: BoxFit.fill
                    );
                  },
                  itemCount: 3,
                  pagination: new SwiperPagination(),
                  control: new SwiperControl(),
                ),
              ),
            );
          }
        }

25.Dialog
    import 'package:flutter/material.dart';

    class Category extends StatefulWidget {
      @override
      _CategoryState createState() => _CategoryState();
    }
    class _CategoryState extends State {
      _alertDialog() async{
        var result = await showDialog(
          context: context,
          builder: (context){
            return AlertDialog(
              title: Text('提示'),
              content: Text('您确定要删除吗?'),
              actions: [
                FlatButton(
                  child: Text('取消'),
                  onPressed: (){
                    Navigator.pop(context,'cancel');
                  },
                ),
                FlatButton(
                  child: Text('确定'),
                  onPressed: (){
                    Navigator.pop(context,'ok');
                  },
                )
              ],
            );
          }
        );
        print('result $result');
      }
      _simpleDialog() async{
          var result = await showDialog(
            context: context,
            builder: (context){
              return SimpleDialog(
                title: Text('选择内容'),
                children: [
                  SimpleDialogOption(
                    child: Text('option A'),
                    onPressed: (){
                      Navigator.pop(context,'A');
                    },
                  ),
                  SimpleDialogOption(
                    child: Text('option B'),
                    onPressed: (){
                      Navigator.pop(context,'B');
                    },
                  ),
                  SimpleDialogOption(
                    child: Text('option C'),
                    onPressed: (){
                      Navigator.pop(context,'C');
                    },
                  )
                ],
              );
            }
          );
          print(result);
      }
      _showModalBottomSheet() async{
        var result = await showModalBottomSheet(
            context: context,
            builder: (context){
              return Container(
                height: 200,
                child: Column(
                  children: [
                    ListTile(
                      title: Text('分享A'),
                      onTap: (){
                        Navigator.pop(context,'A');
                      },
                    ),
                    ListTile(
                        title: Text('分享B'),
                        onTap: (){
                          Navigator.pop(context,'B');
                        }
                    ),
                    ListTile(
                        title: Text('分享C'),
                        onTap: (){
                          Navigator.pop(context,'C');
                        }
                    )
                  ],
                ),
              );
            }
        );
        print(result);
      }
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Column(
            children: [
              RaisedButton(
                child: Text('AlertDialog'),
                onPressed: this._alertDialog,
              ),
              RaisedButton(
                child: Text('SimpleDialog'),
                onPressed: this._simpleDialog,
              ),
              RaisedButton(
                child: Text('ShowModalBottomSheet'),
                onPressed: this._showModalBottomSheet,
              )
            ],
          ),
        );
      }
    }
注意:有时候我们需要通过组件传递数据到类似于ShowModalBottomSheet组件中,如果原数据发生变化,而ShowModalBottomSheet无法改变,就需要使用StatefulBuilder
showModalBottomSheet(
        context: context,
        builder: (context){
          return StatefulBuilder(
            builder: (BuildContext buildContext, setBottomState){
              return Stack(
                children: [
                  ListView(
                    children: [
                      Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: this.getAttrWiget(setBottomState),
                      )
                    ],
                  ),
                  Positioned(
                    bottom: 0,
                    width: MediaQuery.of(context).size.width,
                    height: 40,
                    child: Row(
                      children: [
                        Expanded(
                          flex: 1,
                          child: BuyButton(
                            color: Color.fromRGBO(253, 1, 0, 0.9),
                            text: "加入购物车",
                            callback: (){
                              print('加入购物车');
                            },
                          ),
                        ),
                        Expanded(
                          flex: 1,
                          child: BuyButton(
                            color: Color.fromRGBO(255, 165, 0, 0.9),
                            text: "立即购买",
                            callback: (){
                              print('立即购买');
                            },
                          ),
                        )
                      ],
                    ),
                  )
                ],
              );
            },
          );
        }
    )

26.Toast
    第三方组件:fluttertoast
    实例:
        import 'package:flutter/material.dart';
        import 'package:fluttertoast/fluttertoast.dart';

        class Category extends StatefulWidget {
          @override
          _CategoryState createState() => _CategoryState();
        }
        class _CategoryState extends State {
          _showToast(){
            Fluttertoast.showToast(
                msg: '王清最帅',
                toastLength: Toast.LENGTH_LONG,
                // 显示位置(顶部、居中、底部)
                gravity: ToastGravity.CENTER,
                timeInSecForIos: 1,
                backgroundColor: Colors.red,
                textColor: Colors.white,
                fontSize: 16
            );
          }

          @override
          Widget build(BuildContext context) {
            return Container(
              child: Column(
                children: [
                  RaisedButton(
                    child: Text('Toast'),
                    onPressed: this._showToast,
                  )
                ],
              ),
            );
          }
        }

27.自定义Dialog
    import 'package:flutter/material.dart';
    import 'dart:async';

    class MyDialog extends Dialog{
      String title;
      String content;

      MyDialog(this.title,this.content);

      _showTimer(context){
          // 定时器
          Timer.periodic(
            Duration(milliseconds: 2000),
            (t){
              Navigator.pop(context);
              //取消定时器,避免无限回调
              t.cancel();
              t = null;
            }
          );
      }

      @override
      Widget build(BuildContext context) {
        _showTimer(context);
        return Material(
          type: MaterialType.transparency,
          child: Center(
            child: Container(
              width: 200,
              height: 200,
              color: Colors.white,
              child: Column(
                children: [
                  Padding(
                    padding: EdgeInsets.all(10),
                    child: Stack(
                      children: [
                        Align(
                          alignment: Alignment.center,
                          child: Text(this.title),
                        ),
                        Align(
                          alignment: Alignment.topRight,
                          child: InkWell(
                            child: Icon(Icons.close),
                            onTap: (){
                              // Navigator.pop(context);
                            },
                          ),
                        ),
                      ],
                    ),
                  ),
                  Divider(),
                  Container(
                    padding: EdgeInsets.only(left: 10),
                    width: double.infinity,
                    child: Text(this.content,textAlign: TextAlign.left),
                  )
                ],
              ),
            ),
          ),
        );
      }
    }

28. http get post请求
   知识点:
    JSON字符串转换为Map:
        import 'dart:convert';
        var str = '{"name":"wq","age":23}';
        var mapStr = json.decode(str);
        print(mapStr["name"]);
    Map转化为字符串:
        var map = {"name":"wq"};
        print(json.encode(map));

    Http:
        配置依赖:
            dependencies:
              http: ^0.12.1
    实例:
        import 'package:flutter/material.dart';
        import 'dart:convert';
        import 'package:http/http.dart' as http;
        class Category extends StatefulWidget {
          @override
          _CategoryState createState() => _CategoryState();
        }
        class _CategoryState extends State {
          // Get请求数据
          _getData() async{
            var apiUrl = 'http://a.itying.com/api/productlist';
            var result = await http.get(apiUrl);
            if(result.statusCode == 200){
              print(json.decode(result.body));
            } else {
              print(result.statusCode);
            }
          }

          // POST提交数据
          _postData() async{
            var apiUrl = 'http://www.baidu.com/post';
            var result = await http.post(
              apiUrl,
              body: {
                "name": "wq",
                "age": 23
              }
            );
            print(result);
          }

          @override
          Widget build(BuildContext context) {
            return Container(
              child: Column(
                children: [
                  RaisedButton(
                    child: Text('GET请求'),
                    onPressed: (){
                      this._getData();
                    },
                  ),
                  RaisedButton(
                    child: Text('POST请求'),
                    onPressed: (){
                      this._postData();
                    },
                  )
                ],
              ),
            );
          }
        }

29. Dio实现网络请求
    配置依赖:
        dio: ^3.x.x
    实例:
        import 'package:flutter/material.dart';
        import 'package:dio/dio.dart';
        class Category extends StatefulWidget {
          @override
          _CategoryState createState() => _CategoryState();
        }
        class _CategoryState extends State {

          // Get请求数据
          _getData() async{
            var apiUrl = 'http://a.itying.com/api/productlist';
            Response response = await Dio().get(apiUrl);
            print(response.data);
          }

          // POST提交数据
          _postData() async{
            var apiUrl = 'http://a.itying.com/api/productlist';
            Response response = await Dio().post(apiUrl, data: {"name":"wq"});
            print(response);
          }

          @override
          Widget build(BuildContext context) {
            return Container(
              child: Column(
                children: [
                  RaisedButton(
                    child: Text('GET请求'),
                    onPressed: (){
                      this._getData();
                    },
                  ),
                  RaisedButton(
                    child: Text('POST请求'),
                    onPressed: (){
                      this._postData();
                    },
                  )
                ],
              ),
            );
          }
        }4

30. Menu
		(1)组件方式PopupMenuButton
			PopupMenuButton(
                offset: Offset(0,100),
                icon: Icon(Icons.more_horiz),
                onSelected: (String value) {
                  print("valeeueu $value");
                },
                itemBuilder: (BuildContext context) => >[
                  PopupMenuItem(
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: [
                        Icon(Icons.home, color: Colors.black54,),
                        Text('首页')
                      ],
                    ),
                    value: 'home',
                  ),
                  PopupMenuItem(
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: [
                        Icon(Icons.search, color: Colors.black54,),
                        Text('搜索')
                      ],
                    ),
                    value: 'search',
                  )
                ])
		(2)点击事件方式(showMenu)
			onPressed:(){
				showMenu(
					context:context,
					position: RelativeRect.fromLTRB(10,0,0,0),
					items: [
						PopupMenuItem(
		                    child: Row(
		                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
		                      children: [
		                        Icon(Icons.home, color: Colors.black54,),
		                        Text('首页')
		                      ],
		                    ),
		                    value: 'home',
		                  )
					]
				)
			}

flutter知识点总结_第1张图片
flutter知识点总结_第2张图片

你可能感兴趣的:(前端)