Flutter学习

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

2020-04-28  本文已影响0人  文小猿666

本节我们主要通过实现项目中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详解

上一篇下一篇

猜你喜欢

热点阅读