• 在实际开发中,当发现使用SizedBox或ConstrainedBox给子元素指定宽高,仍然没有效果,几乎可以断定父元素设置了限制。

  • 示例:

AppBar(
    title: Text(title),
    actions: <Widget>[
        SizedBox(
            width: 20,
            height: 20,
            child: CircularProgressIndicator(
                strokeWidth: 3,
                valueColor: AlwaysStoppedAnimation(Colors.white70),
            ),
        )
    ],
)
  • 因为AppBar中已经指定了action按钮的限制条件,所以我们要自定义loading按钮大小,就必须通过Unconstrained来去除父元素的限制,代码如下:
AppBar(
    title: Text(title),
    actions: <Widget>[
        unconstrainedBox(
            child: SizedBox(
                width: 20,
                height: 20,
                child: CircularProgressIndicator(
                    strokeWidth: 3,
                    valueColor: AlwaysStoppedAnimation(Colors.white70),
                )
            )
        )
    ]
)

装饰容器DecoratedBox

  • DecoratedBox可以在其子组件绘制前后绘制一些装饰Decoration,如背景、边框、渐变等。定义如下:
const DecoratedBox({
    Decoration decoration, // 将要绘制的装饰,类型为Decoration
    DecorationPosition position = DecorationPosition.background, // 此属性决定在哪里绘制Decoration
    Widget child
})

BoxDecoration

  • 通常直接使用BoxDecoration类,是Decoration的字类,实现了常用的装饰柜hi元素的绘制
BoxDecoration({
    Color color, // 颜色
    DecorationImage image, // 图片
    BoxBorder border, // 边框
    BorderRadiusGeometry borderRadius, // 圆角
    List<BoxShadow> boxShadow, // 阴影,可以指定多个
    Gradient gradient, // 渐变
    BlendMode backgroundBlendMode, // 背景混合模式
    BoxShape shape = BoxShape.rectangle, // 形状 
})
  • 示例
DecorateBox(
    decoration: BoxDecoration(
        gradient: LinearGradient(colors: [Colors.red, Colors.orange[700]]), // 背景渐变
        borderRadius: BorderRadius.circlular(3.0), // 3像素圆角
        boxShadow: [
            // 阴影
            BoxShadow(
                color: Colors.black54,
                offset: Offset(2.0, 2.0),
                blurRadius: 4.0
            )
        ]
    ),
    child: Padding(
        padding: EdgeInsets.symmetric(horizontal: 80.0, vertical: 18.0),
        child: Text("Login", style: TextStyle(color: Colors.white)),
    )
)

变化(Tranform)

  • 可以在其子组件绘制时对其应用一些矩阵变换来实现一些特效。

  • Matrix4是一个4D矩阵,通过它,可以实现各种矩阵操作

  • 示例:

Container(
    color: Colors.black,
    child: new Transform(
        alignment: Alignment.topRight, // 相对于坐标系原点的对齐方式
        transform: new Matrix4.skewY(0.3), // 沿Y轴倾斜0.3弧度
        child: new Container(
            padding: const EdgeInsets.all(8.0),
            color: Colors.deepOrange,
            child: const Text('Apartment for rent!'),
        ),
    ),
);

平移

DecoratedBox(
    decoration: BoxDecoration(color: Colors.red),
    // 默认原点为左上角,左移20像素,向上平移5
    child: Transfrom.translate(
        offset: Offset(-20.0, -5.0),
        child: Text("Hello, Man"),
    )
)
  • Transform.rotate()

Container

  • 一个组合类容器,本身不对应具体的RenderObject,

  • 是DecoratedBox、ConstrainedBox、Transform、Padding、Align等组件组合的一个多功能容器,因此只需要通过一个Container组件可以实现同时需要装饰、变换、限制的场景。

  • 定义:

Container({
    this.alignment,
    this.padding, // 容器内补白,属于decoration的装饰范围
    Color color, // 背景色
    Decoration decoration, // 背景装饰
    Decoration foregroundDecoration, // 前景装饰
    double width, // 容器的宽度
    double height, // 容器的高度
    BoxConstraints constraints, // 容器大小的限制条件
    this.margin // 容器的外补白。不属于decoration的装饰范围
    this.transform, //变换
    this.child,
})
  • 示例
Container(
  margin: EdgeInsets.only(top: 50.0, left: 120.0), //容器外填充
  constraints: BoxConstraints.tightFor(width: 200.0, height: 150.0), //卡片大小
  decoration: BoxDecoration(//背景装饰
      gradient: RadialGradient( //背景径向渐变
          colors: [Colors.red, Colors.orange],
          center: Alignment.topLeft,
          radius: .98
      ),
      boxShadow: [ //卡片阴影
        BoxShadow(
            color: Colors.black54,
            offset: Offset(2.0, 2.0),
            blurRadius: 4.0
        )
      ]
  ),
  transform: Matrix4.rotationZ(.2), //卡片倾斜变换
  alignment: Alignment.center, //卡片内文字居中
  child: Text( //卡片文字
    "5.20", style: TextStyle(color: Colors.white, fontSize: 40.0),
  ),
);
  • 容器大小可以通过width、height属性来指定,也可以通过constraints来指定;若它们同时存在,width和height优先,实际上Container内部会根据width、height来生成一个constraints
  • color和decoration是互斥的,若同时设置它们则会报错。实际上,当指定color时,Container内会自动创建一个decoration

Padding和Margin

  • 二者之区别
Container(
    margin: EdgeInsets.all(20.0), // 容器外补白
    color: Colors.orange,
    child: Text("Hello world"),
),
Container(
    padding: EdgeInsets.all(20.0), // 容器内补白
    color: Colors.orange,
    child: Text("Hello World"),
),
  • margin的留白是在容器外部,padding的留白是在容器内部
  • 事实上,Container内margin和padding都是通过Padding组件来实现的,上面的代码等价于:
Padding(
    padding: EdgeInsets.all(20.0),
    child: DecoratedBox(
        decoration: BoxDecoration(color: Colors.orange),
        child: Text("Hello World"),
    ),
),
DecoratedBox(
    decoration: BoxDecoration(color: Color.orange),
    child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Text("Hello WOrld!"),
    ),
),