[Flutter开发]02.如何构建一个Flutter布局

作者: 沈枫_ShenF | 来源:发表于2020-03-09 09:07 被阅读0次

前言

在Flutter中,几乎所有东西都是一个widget,包括对齐(alignment)、填充(padding)和布局(layout)。widget的主要工作是提供一个build()方法来描述如何通过简单的widget来构建复杂的widget来显示自己,例如官方中下面的UI:

上面的UI可以通过一个行包含3列,其中每列包含一个图标和一个标签来完成。

在Flutter中,Widget的作用是描述UI元素的配置数据,它并不是表示最终绘制在设备屏幕上的显示元素,而它只是描述显示元素的一个配置数据。

而实际上显示元素的类是Element,也就是说Widget只是描述Element的配置数据!Widget只是UI元素的一个配置数据,并且一个Widget可以对应多个Element。这是因为同一个Widget对象可以被添加到UI树的不同部分,而真正渲染时,UI树的每一个Element节点都会对应一个Widget对象,所以:

  • Widget是Element的配置数据,Widget树是一个配置树,而真正的UI渲染树是由Element构成。
  • 一个Widget对象可以对应多个Element对象,因为由一份配置(Widget),可以创建多个实例(Element)。

Flutter拥有丰富的布局widget,但是把握一些最常用的布局widget就可以了,毕竟我们最终想尽可能快构建应用并运行起来,而不是让自己淹没在整个完整的widget列表中,其他需要用到的再去翻阅文档即可。

布局分类

布局widget大致可分为两类:
  1. Single-child layout widgets,它们都有一个child属性,只能包含一个子级widget。

例如: Container、Padding、Center等等。

  1. Multi-child layout widgets,它们都有一个 children属性,可以包含多个子级widget。

例如: Row,Column,ListView或Stack等等。

常用组件

Container

也是一个widget,只有它能设置填充,边距,边框或背景色。
概要 :

  • 添加padding, margins, borders
  • 改变背景颜色或图片
  • 包含单个子widget,但该子widget可以是Row,Column,甚至是widget树的根
    Expanded widget控制沿着主轴方向的widget大小,具有一个flex属性,它是一个整数,用于确定widget的弹性系数,默认弹性系数是1。
    例如,创建一个由三个widget组成的行,其中中间widget的宽度是其他两个widget的两倍,将中间widget的弹性系数设置为2:
appBar: new AppBar(
  title: new Text(widget.title),
),
body: new Center(
  child: new Row(
    crossAxisAlignment: CrossAxisAlignment.center,
    children: [
      new Expanded(
        child: new Image.asset('images/pic1.jpg'),
      ),
      new Expanded(
        flex: 2,
        child: new Image.asset('images/pic2.jpg'),
      ),
      new Expanded(
      .....

最终结果:

GridView

网格组件,可滚动。自定义grid,或使用一下提供的grid之一:

  • GridView.count 允许您指定列数
  • GridView.extent 允许您指定项的最大像素宽度
ListView

相比Column,ListView是一种列状布局,如果其内容太长而无法适应可用空间,则会自动滚动,而且你可以设置滚动方向, 比如:

  • scrollDirection:Axis.horizontal/Axis. vertical水平/垂直滚动
  • reverse:true表示由下往上的滚动,
  • physics: NeverScrollableScrollPhysics()表示列表不能滚动

ListView还可以设置关屏时垃圾收集机制:addAutomaticKeepAlives: false。
并可以控制cache大小:cacheExtent:100.0,它是一个预加载概念,表示出现在可视区域上下各 cacheExtent 大小区域内的元素会被提前加载。
可以设置分割线:separatorBuilder:(,) => Divider()。
也可以通过mySliverChildDelegate构建自定义的ListView:

ListView.custom(
    childrenDelegate: mySliverChildDelegate
);

具体用法,推荐看这篇文章:Flutter 中 ListView 组件的子元素曝光统计

ListTile

相比Row,ListTile是一个易于使用的小部件,具有前后图标属性以及最多3行文本,并且能通过onTap和onLongPress回调,进行交互。

Stack

使用Stack来组织需要重叠的widget。widget可以完全或部分重叠底部widget,子列表中的第一个widget是base widget; 随后的子widget被覆盖在基础widget的顶部,Stack的内容不能滚动。Stack使用alignment属性和调整文本偏移。

Card

属于Single-child layout,可以使用SizedBox来限制Card的大小。
Card具有圆角和阴影,这使它有一个3D效果。可以通过更改Card的elevation属性来控制投影效果。Card内容不能滚动。

DefaultTextStyle.merge

DefaultTextStyle.merge可以允许您创建一个默认的文本样式,该样式会被其所有的子节点继承。

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    // ...

    var descTextStyle = new TextStyle(
      color: Colors.black,
      fontWeight: FontWeight.w800,
      fontFamily: 'Roboto',
      letterSpacing: 0.5,
      fontSize: 18.0,
      height: 2.0,
    );

    var iconList = DefaultTextStyle.merge(
      style: descTextStyle,
      child: new Container(
        padding: new EdgeInsets.all(20.0),
        child: new Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            new Column(
              children: [
                new Icon(Icons.kitchen, color: Colors.green[500]),
                new Text('PREP:'),
                new Text('25 min'),
              ],
            ),
            new Column(
              children: [
                new Icon(Icons.timer, color: Colors.green[500]),
                new Text('COOK:'),
                new Text('1 hr'),
              ],
            ),
            new Column(
              children: [
                new Icon(Icons.restaurant, color: Colors.green[500]),
                new Text('FEEDS:'),
                new Text('4-6'),
              ],
            ),
          ],
        ),
      ),
    );
    // ...
  }
}

相关文章

网友评论

    本文标题:[Flutter开发]02.如何构建一个Flutter布局

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