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

2021-03-17  本文已影响0人  Aliv丶Zz

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,
          ),
        )
      ],
    );
  }
}

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是互斥的,不可同时设置。

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

 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>[],
  })
上一篇下一篇

猜你喜欢

热点阅读