Flutter(3)-UI布局

2019-09-26  本文已影响0人  BoxJing

本篇文章主要讲解一下Flutter中的布局知识。

1. Alignment

把Alignment单独拿出来是因为在Container的布局有点繁琐,先从一个简单的代码看一下Container里面的alignment

class BoxRowDemo extends StatelessWidget {
  final TextStyle _textStyle = TextStyle(
    color: Colors.white,
    fontSize: 36.0,
  );
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.deepPurple,
//      alignment: Alignment(1.0,0.0),
      child: Text('一个阿狸',style: _textStyle,),
    );
  }
}

看到运行的效果图,想必已经大致知道了设个Alignment的的作用,Container的布局行为的先后顺序是这样的:

  1. 采用alignment
  2. 以child改变大小
  3. 用了width、height、constraints
  4. 适应父Widget
  5. 尽可能小

源码中可以看到Alignment的一些默认值:

  /// The top left corner.
  static const Alignment topLeft = Alignment(-1.0, -1.0);
  /// The center point along the top edge.
  static const Alignment topCenter = Alignment(0.0, -1.0);
  /// The top right corner.
  static const Alignment topRight = Alignment(1.0, -1.0);
  /// The center point along the left edge.
  static const Alignment centerLeft = Alignment(-1.0, 0.0);
  /// The center point, both horizontally and vertically.
  static const Alignment center = Alignment(0.0, 0.0);
  /// The center point along the right edge.
  static const Alignment centerRight = Alignment(1.0, 0.0);
  /// The bottom left corner.
  static const Alignment bottomLeft = Alignment(-1.0, 1.0);
  /// The center point along the bottom edge.
  static const Alignment bottomCenter = Alignment(0.0, 1.0);

2. Row

来直接看一个Row的简单代码,容器里放置3个不同大小的小容器:

class BoxRowDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.deepPurple,
      alignment: Alignment(0.0,0.0),
      child: Row(
        children: <Widget>[
          Container(
            color: Colors.red,
            width: 80,
            height: 80,
          ),
          Container(
            color: Colors.green,
            width: 60,
            height: 60,
          ),
          Container(
            color: Colors.blue,
            width: 100,
            height: 100,
          )
        ],
      ),
    );
  }
}

运行效果就跟我们预想的一样,是横向排列的。在这里有一个mainAxisAlignmentcrossAxisAlignment需要提一下,在RowColumn中有主轴和交叉轴这两个东西,这两个东西可以辅助我们更方便的布局,先来看个只有主轴mainAxisAlignment的代码:

class BoxRowDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.deepPurple,
      alignment: Alignment(0.0,0.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          Container(
            color: Colors.red,
            width: 80,
            height: 80,
          ),
          Container(
            color: Colors.green,
            width: 60,
            height: 60,
          ),
          Container(
            color: Colors.blue,
            width: 100,
            height: 100,
          )
        ],
      ),
    );
  }

看几个不同的主轴值运行效果图,图中白色线条和数字用来辅助解释,这样可以更直观的看到每个值的作用:


主轴的属性值有:

交叉轴crossAxisAlignment我们就来个简单的示例:

class BoxRowDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.deepPurple,
      alignment: Alignment(0.0,0.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Container(
            color: Colors.red,
            width: 80,
            height: 80,
          ),
          Container(
            color: Colors.green,
            width: 60,
            height: 60,
          ),
          Container(
            color: Colors.blue,
            width: 100,
            height: 100,
          )
        ],
      ),
    );
  }

看下运行效果图:



交叉轴的枚举值有:

class BoxBaseLineDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      crossAxisAlignment: CrossAxisAlignment.baseline,
      textBaseline: TextBaseline.alphabetic,
      children: <Widget>[
        Container(
            child: Text(
              '足记',
              style: TextStyle(fontSize: 15),
            ),
            color: Colors.red,
            height:40,
        ),
        Container(
          child: Text(
            'Fotoplace',
            style: TextStyle(fontSize: 60),
          ),
          color: Colors.purple,
          height: 80,
        ),
        Container(
            child: Text(
              'Box',
              style: TextStyle(fontSize: 30),
            ),
            color: Colors.blue,
            height: 80,
        ),
      ],
    );
  }
}

看一下运行效果就非常直接的看到作用,方便的将文字底部对齐了:


还有一个Expanded来一个示例:
class BoxExpandedDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      crossAxisAlignment: CrossAxisAlignment.baseline,
      textBaseline: TextBaseline.alphabetic,
      children: <Widget>[
        Expanded(
          child: Container(
            child: Text(
              '足记',
              style: TextStyle(fontSize: 15),
            ),
            color: Colors.red,
            height:40,
          ),
        ),
        Expanded(
          child: Container(
            child: Text(
              'Fotoplace',
              style: TextStyle(fontSize: 60),
            ),
            color: Colors.purple,
//            height: 80,
          ),
        ),
        Expanded(
          child: Container(
            child: Text(
              'Box',
              style: TextStyle(fontSize: 30),
            ),
            color: Colors.blue,
            height: 80,
          ),
        ),
      ],
    );
  }
}

看一下运行效果:


如果用Expanded也就意味着主轴方向不会有空余空间,一定会被子项分完,也有部分Expanded,部分非Expanded的子项,大家可以自行尝试尝试。

3. Column

上面的Row说清楚之后,Column就相对来说很简单了直接上个代码,改改值,自己看看效果就可以了:

class BoxColumnDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.deepPurple,
      alignment: Alignment(0.0,0.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Container(
            color: Colors.red,
            width: 80,
            height: 80,
          ),
          Container(
            color: Colors.green,
            width: 60,
            height: 60,
          ),
          Container(
            color: Colors.blue,
            width: 100,
            height: 100,
          )
        ],
      ),
    );
  }
}

4. Stack

Stack布局适合重叠式布局,来个带有位置Positioned的Stack布局示例:

class BoxStackDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Positioned(
          child: Container(
            color: Colors.red,
            width: 200,
            height: 200,
          ),
        ),
        Positioned(
          right: 0,
          child: Container(
            color: Colors.green,
            width: 100,
            height: 100,
          ),
        ),
        Positioned(
          left: 10,
          top: 30,
          child: Container(
            color: Colors.blue,
            width: 50,
            height: 50,
          ),
        ),
      ],
    );
  }
}

看一下运行结果,你会发现跟iOS中frame甚至只autolayout非常的像,在Stack布局中Positioned是经常会被用到的一个组件:

5. AspectRatio

AspectRatio主要用来设置一个比例,来一个示例看一下:

class BoxAspectRatioDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
        color: Colors.purple,
        alignment: Alignment(0.0,0.0),
        child: Container(
          color: Colors.blue,
          width: 168,
          child: AspectRatio(
            aspectRatio: 1/1,
            child: Icon(Icons.add,),
          ),
        )
    );
  }
}

可以方便的设置子项的一个比例大小,在根据屏幕大小的布局中会用得到。

无论在Flutter中的布局还是其他的布局,这个东西不是一篇文章就能够说的清楚的,这里只是简答的写了些基本的作用,我们在后面的不断开发中会不停的练习,用这些基本的布局完成美工高规格要求的UI。所有的代码都可以在Github:BoxJ/Flutter-daydayup中下载,本篇代码的文件夹是boxdemo_003,欢迎一起交流!

上一篇 下一篇

猜你喜欢

热点阅读