美文网首页Flutter学习
Flutter学习--项目实战(三)布局练习

Flutter学习--项目实战(三)布局练习

作者: 文小猿666 | 来源:发表于2020-04-28 00:04 被阅读0次

    本节我们主要通过实现项目中ListView的来巩固练习一下flutter的布局。
    下图是我们要实现的效果,仿微信的“发现”页面


    图片.png

    首先我们来分析一下这个ListView的cell的结构


    图片.png

    通过这个cell我们把这个view分为左右两个Container
    左边Container上面有一个Text和一个Image ,右边Container上面有一个Text和一个红点Image 以及一个箭头。

    1.自定义cell
    首先我们给cell创建一个类DiscoverCell,然后在类中创建一个构造函数,构造函数的参数有左边Text的文本内容title 左边图标imageName,右边Text的文本内容subTitle,右边‘红点’image图片subImageName,

    class DiscoverCell extends StatefulWidget {
      final String title;
      final String subTitle;
      final String imageName;
      final String subImageName;
    
      const DiscoverCell({//使用快捷键 option+回车 生成的构造函数
        Key key,
        @required this.title,
        @required this.subTitle,
        this.imageName,
        this.subImageName
      }) : assert(title != null, 'title 不能为空'),//起到断言的作用,当assert()中的条件为true时语句会正常执行
            assert(imageName != null, 'imageName 不能为空');
    
      @override
    
      _State createState() => _State();
    }
    
    

    注意:assert()起到断言的作用,当assert()中的条件为true时语句会正常执行,如果条件为false 则会抛出一个异常。

    2.cell布局
    由于这里cell中的组件都是从左自右水平排列,因此我们这里选择Rrow方式布局左右两个Container。每一个Container中的Text和Image也都是水平排列。所以这里我们用Row里面嵌套Row来布局

    child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                Container(
                  child: Row(
                    children: <Widget>[
                      Image(image:AssetImage(widget.imageName),width: 20,height: 20,),
                      SizedBox(width: 15),
                      Text(widget.title)
                    ],
                  ),
                ),
                Container(
                  child: Row(
                    children: <Widget>[
                      SizedBox(width: 15),
                      Text(widget.subTitle != null ? widget.subTitle:'',
                          style: TextStyle(
                            color: Colors.grey,
                          )
                      ),//判断子标题是否为空,不为空则显示
                      widget.subImageName != null ? Image(image: AssetImage(widget.subImageName),width: 10,height: 10,):Container(),//判断图片是否为空,不为空则显示
    
                      Image(image: AssetImage('images/icon_right.png'),width: 20,height: 20,)//右边的箭头图片
                    ],
                  ),
                )
              ],
            ),
    

    这里稍微讲解一下mainAxisAlignment的几个常用属性
    1.spaceEvently
    一行中如果有2个widget(五个五角星暂且看成1个widget),那么除去2widget所占据的宽度,3个红色方块宽度是一样的, 如下图所示

    图片.png

    2.spaceBetween
    一行中如果有2个widget,那么分布2端,如下图所示

    图片.png

    3.spaceAround
    一行中如果有2个widget,那么每个widget左右都是相同的方块,如下图所示

    图片.png

    我们实现效果如图所示:


    图片.png

    3.ListView中使用
    实现了一个cell之后我们到ListView组件中实现多个cell。

            child: ListView(
              children: <Widget>[
                DiscoverCell(title:'朋友圈' ,subTitle: '',imageName: 'images/朋友圈.png',subImageName: ''),
                SizedBox(height: 10),//实现cell与cell中高为10的空格
                DiscoverCell(title:'扫一扫' ,subTitle: '',imageName: 'images/扫一扫2.png',subImageName: ''),
                Row(//实现cell中间的高为1的细线
                  children: <Widget>[
                    Container(
                      color: Colors.white,
                      width: 15.0,
                      height: 1,
                    ),
                    Container(
                      color: Color.fromRGBO(240, 240, 240, 1)
                    ),
                  ],
                ),
                DiscoverCell(title:'摇一摇' ,subTitle: '',imageName: 'images/摇一摇.png',subImageName: ''),
                SizedBox(height: 10),
                DiscoverCell(title:'看一看' ,subTitle: '',imageName: 'images/看一看icon.png',subImageName: ''),
                Row(
                  children: <Widget>[
                    Container(
                      color: Colors.white,
                      width: 15.0,
                      height: 1,
                    ),
                    Container(
                        color: Color.fromRGBO(240, 240, 240, 1)
                    ),
                  ],
                ),
                DiscoverCell(title:'搜一搜' ,subTitle: '',imageName: 'images/搜一搜.png',subImageName: ''),
                SizedBox(height: 10),
                DiscoverCell(title:'附近的人' ,subTitle: '',imageName: 'images/附近的人icon.png',subImageName: ''),
                SizedBox(height: 10),
                    DiscoverCell(title:'购物' ,subTitle: '618限时特惠',imageName: 'images/购物.png',subImageName: 'images/badge.png'),
              ],
            ),
    

    这里稍微讲一下SizedBox组件

    使用场景
    1.一般限制子控件大小
    2.还有这么一种场景也可以使用SizeBox,就是可以代替padding和container,然后 用来设置两个控件之间的间距,比如在行或列中就可以设置两个控件之间的间距 主要是可以比使用一个padding或者container简单方便 (在Flutter中可能用不同的控件可以实现到相同的目的,尽量使用越简单的widget来实现)

    我们这里用的是第二种使用场景
    4.给cell添加点击手势

    return GestureDetector(//添加手势组件
          onTap:() {
            //实现页面跳转路由
            Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) =>ContactPage()));
            setState(() {
              _backGroundColors = Colors.white;
            });
            print('点击了');
          },
          onTapDown: (TapDownDetails details){//类似于iOS中的selectedState
            setState(() {
              _backGroundColors = Colors.white30;
            });
            print('按下来了');
          },
    }
    

    我们给cell的点击手势里面添加的是跳转到下级页面事件。
    至此功能就实现啦。😄
    页面效果为:


    图片.png

    这里吐槽一下pubspec.yaml中设置assets图片路径碰到的小坑,
    下面是我在项目中设置的路径的格式,很奇葩的是这个格式居然只能在真机上面加载,在模拟器上加载不出来。

      assets:
      - images/tabbar_chat.png
      - images/tabbar_chat_hl.png
      - images/tabbar_friends.png
      - images/tabbar_friends_hl.png
      - images/tabbar_mine.png
      - images/tabbar_mine_hl.png
      - images/tabbar_discover.png
      - images/tabbar_discover_hl.png
      - images/朋友圈.png
      - images/icon_right.png
      - images/扫一扫2.png
      - images/搜一搜.png
      - images/摇一摇.png
      - images/看一看icon.png
      - images/附近的人icon.png
      - images/购物.png
      - images/badge.png
    

    后面改成了这样:

      assets:
        - images/tabbar_chat.png
        - images/tabbar_chat_hl.png
        - images/tabbar_friends.png
        - images/tabbar_friends_hl.png
        - images/tabbar_mine.png
        - images/tabbar_mine_hl.png
        - images/tabbar_discover.png
        - images/tabbar_discover_hl.png
        - images/朋友圈.png
        - images/icon_right.png
        - images/扫一扫2.png
        - images/搜一搜.png
        - images/摇一摇.png
        - images/看一看icon.png
        - images/附近的人icon.png
        - images/购物.png
        - images/badge.png
    

    assets:往里面锁进一格,
    - images/xxxx往里面缩进两格才成功在模拟器和真机上面都能显示。

    参考文章:1.Flutter--SizedBox
    2.Flutter MainAxisAlignment.spaceEvently、spaceBetween、spaceAround 区别
    3.Flutter 布局(二)- Padding、Align、Center详解

    相关文章

      网友评论

        本文标题:Flutter学习--项目实战(三)布局练习

        本文链接:https://www.haomeiwen.com/subject/tnbswhtx.html