7. Flutter - 基础组件 之 布局Widget

1. Align组件

  const Align({
    Key key,
    // 对齐方式
    this.alignment = Alignment.center,
    // 宽度因子,不设置的情况,会尽可能大
    this.widthFactor,
    // 高度因子,不设置的情况,会尽可能大
    this.heightFactor,
    // 要布局的子Widget
    Widget child,
  })
Alignment对齐方式设置

文档中已经为我们定义了一些常量:如下

  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);
  /// The bottom right corner.
  static const Alignment bottomRight = Alignment(1.0, 1.0);

centerAlignment(0.0, 0.0)topLeftAlignment(-1.0, -1.0),这些值均是以父视图为准进行的设置。父视图范围内取值为(-1.0, -1.0) ~ (1.0, 1.0),中心点为(0.0, 0.0)。当然我们也可以取值(0, 2),(3,0)等,这不过会超出父视图显示范围。

widthFactor和heightFactor作用
  • 子组件在父组件中的对齐方式必须有一个前提,就是父组件得知道自己的范围(宽度和高度);
  • 如果widthFactor和heightFactor不设置,那么默认Align会尽可能的大(尽可能占据自己所在的父组件);
  • 我们也可以对他们进行设置,比如widthFactor设置为5,那么相对于Align的宽度是子组件跨度的5倍;
  • 代码演示:

ps:Container为容器视图,主要为了设置背景色及大小,方便观察,后面会有介绍。

class AlignTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Container(
          margin: EdgeInsets.all(20),
          color: Colors.blue,
          child: Align(
            child: Icon(Icons.pets, size: 36, color: Colors.red),
            //左上
            alignment: Alignment(-1, -1),
            widthFactor: 5,
            heightFactor: 5,
          ),
        ),
        Container(
          padding: EdgeInsets.all(10),
          color: Colors.green,
          child: Align(
            child: Icon(Icons.pets, size: 36, color: Colors.red),
            //右下角
            alignment: Alignment(1, 1),
            widthFactor: 3,
            heightFactor: 3,
          ),
        )
      ],
    );
  }
}
  • 显示效果:


    Align效果演示.png

2. Center 组件

class Center extends Align {
  const Center({ 
      Key key, 
      double widthFactor, 
      double heightFactor, 
      Widget child 
  }) : super(key: key, widthFactor: widthFactor, heightFactor: heightFactor, child: child);
}

Center组件继承自Align,只是将alignment设置为Alignment.center,且Alignalignment属性默认为 Alignment.center
所以其实Align(alignment = Alignment.center)可以与 Center相互替换,效果是一样的。

3. Padding组件

Padding在其他端也是一个属性而已,但是在Flutter中是一个Widget,但是Flutter中没有Margin这样一个Widget,这是因为外边距也可以通过Padding来完成。
Padding通常用于设置子Widget到父Widget的边距(你可以称之为是父组件的内边距或子Widget的外边距)。

  • 代码演示:
class PaddingTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 300,
      height: 300,
      color: Colors.green,
      child: Padding(
        padding: EdgeInsets.all(20),
        child: Container(
            decoration: BoxDecoration(
                color: Colors.blue,
                border: Border.all(color: Colors.red, width: 3)),
            child: Text('测试')),
      ),
    );
  }
}

如下图,Padding的设置对于绿色视图,相当于内边距;而对于蓝色视图则是外边距。

显示效果

4. Container 组件

Container组件类似于iOS中的UIView,主要负责视图的承载,可以通过它设置背景色、边框、圆角等等。

Container({
  Key key,
  //AlignmentGeometry类型可选命名参数,容器内子Widget如何对其,使用其子类Alignment
  this.alignment,
  //EdgeInsetsGeometry类型可选命名参数,设置容器内边距
  this.padding,
  //Color类型可选命名参数,容器填充色
  Color color,
  //Decoration类型可选命名参数,绘制在child子Widget后面的装饰,使用BoxDecoration
  Decoration decoration,
  //Decoration类型可选命名参数,绘制在child子Widget前面的装饰,使用BoxDecoration
  this.foregroundDecoration,
  //double类型可选命名参数,容器的宽度
  double width,
  //double类型可选命名参数,容器的高度
  double height,
  //BoxConstraints类型可选命名参数,对child设置的Widget的约束
  BoxConstraints constraints,
  //EdgeInsetsGeometry类型可选命名参数,设置容器外边距
  this.margin,
  //Matrix4类型可选命名参数,在绘制容器之前要应用的转换矩阵
  this.transform,
  //Widget类型可选命名参数,容器包含的子Widget
  this.child,
})

容器的大小可以通过width、height属性来指定,也可以通过constraints来指定,如果同时存在时,width、height优先。实际上Container内部会根据width、height来生成一个constraints;
colordecoration是互斥的,不可同时设置。

  • BoxDecoration

Container有一个非常重要的属性 decoration,他对应的类型是Decoration类型,但是它是一个抽象类。
在实际开发中,我们经常使用它的实现类BoxDecoration来进行实例化。

const BoxDecoration({
  //Color类型可选命名参数,填充背景色
  this.color,
  //DecorationImage类型可选命名参数,在背景或渐变上绘制的图像
  this.image,
  //BoxBorder类型可选命名参数,边框设置
  this.border,
  //BorderRadiusGeometry类型可选命名参数,设置圆角
  this.borderRadius,
  //List<BoxShadow>类型可选命名参数,盒子后面的盒子投射的阴影列表
  this.boxShadow,
  //Gradient类型可选命名参数,填充框时使用的渐变
  this.gradient,
  //BlendMode类型可选命名参数,应用于框的颜色或渐变背景的混合模式
  this.backgroundBlendMode,
  //BoxShape类型可选命名参数,将背景颜色、渐变和图像填充到并作为boxShadow投射的形状
  this.shape = BoxShape.rectangle,
})
示例代码:
class ContainerTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      // width: 400,
      // height: 400,
      padding: EdgeInsets.all(20),

      color: Colors.lightBlue,
      child: Container(
          width: 280,
          height: 280,
          //内边距
          // padding: EdgeInsets.all(100),
          //外边距
          // margin: EdgeInsets.all(80),
          // 不可与 decoration 同时设置
          // color: Colors.red,
          //变形:旋转
          transform: Matrix4.rotationZ(0.1),
          //装饰:设置颜色。渐变色、形状、阴影等。
          decoration: BoxDecoration(
              color: Colors.green,
              //渐变
              gradient: LinearGradient(
                  colors: [Colors.blue, Colors.red, Colors.green]),
              //形状
              shape: BoxShape.circle,
              //阴影
              boxShadow: [
                BoxShadow(offset: Offset(10, 10), color: Colors.grey)
              ],
              backgroundBlendMode: BlendMode.srcOver,
              border: Border.all(color: Colors.orange, width: 5)),
          child: Icon(
            Icons.people,
            color: Colors.orange,
            size: 100,
          )),
    );
  }
}
显示效果.png

5. Flex组件

Row组件和Column组件都继承自Flex组件。
Flex组件和Row、Column属性主要的区别就是多一个direction。
direction的值为Axis.horizontal的时候,则是Row
direction的值为Axis.vertical的时候,则是Column

  • 5.1 Row组件
 Row({
    Key key,
    //主轴对齐方式
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    //主轴大小(水平方向尽可能大)
    MainAxisSize mainAxisSize = MainAxisSize.max,
    //    交叉处对齐方式
    CrossAxisAlignment crossAxisAlignment =  CrossAxisAlignment.center,
     //   水平方向子widget布局顺序
    TextDirection textDirection,
     //表示Row纵轴(垂直)的对齐方向
    VerticalDirection verticalDirection = VerticalDirection.down,
    //    如果上面是baseline对齐方式
    TextBaseline textBaseline = TextBaseline.alphabetic,
    // 子widget列表
    List<Widget> children = const <Widget>[],
  })
  • mainAxisSize:表示Row在主轴(水平)方向占用的空间,默认是MainAxisSize.max,Row的宽度始终等于水平方向的最大宽度
    MainAxisSize.min表示尽可能少的占用水平空间,Row的实际宽度等于所有子widgets占用的的水平空间;
  • mainAxisAlignment:表示子Widgets在Row所占用的水平空间内对齐方式
    如果mainAxisSize值为MainAxisSize.min,则此属性无意义,因为子widgets的宽度等于Row的宽度
    只有当mainAxisSize的值为MainAxisSize.max时,此属性才有意义
    MainAxisAlignment.start表示沿textDirection的初始方向对齐,
    如textDirection取值为TextDirection.ltr时,则MainAxisAlignment.start表示左对齐,textDirection取值为TextDirection.rtl时表示从右对齐。
    而MainAxisAlignment.end和MainAxisAlignment.start正好相反;
    MainAxisAlignment.center表示居中对齐。
  • crossAxisAlignment:表示子Widgets在纵轴方向的对齐方式
    Row的高度等于子Widgets中最高的子元素高度
    它的取值和MainAxisAlignment一样(包含start、end、 center三个值)
    不同的是crossAxisAlignment的参考系是verticalDirection,即verticalDirection值为VerticalDirection.down时crossAxisAlignment.start指顶部对齐,verticalDirection值为VerticalDirection.up时,crossAxisAlignment.start指底部对齐;而crossAxisAlignment.end和crossAxisAlignment.start正好相反;
5.2 Column组件

Column组件与 Row组件使用方式完全一致,只是方向不同而已。

Column({
    Key key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    MainAxisSize mainAxisSize = MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
    TextDirection textDirection,
    VerticalDirection verticalDirection = VerticalDirection.down,
    TextBaseline textBaseline,
    List<Widget> children = const <Widget>[],
  })
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容