iOS- Flutter 容器类组件-Transform&Container

175 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 22 天,点击查看活动详情

Transform 变换

Transform 可以在其子组件绘制时对其应用一些矩阵变换来实现一些特效。Matrix4是一个4D矩阵,通过它可以实现各种矩阵操作,和iOS中的CGTransform类似。

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

平移

Transform.translate接收一个offset参数,可以在绘制时沿着x、y轴对子组件平移指定的距离。

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

缩放

Transform.scale可以对子组件进行缩小或放大

DecoratedBox(
  decoration:BoxDecoration(color: Colors.red),
  child: Transform.scale(
    scale: 1.5, //放大到1.5倍
    child: Text("Hello world")
  )
);

注意

  • Transform的变换是应用在绘制阶段,而不是应用在布局阶段,所以无论子组件应用和中变化,其占用的空间大小和在屏幕上的位置都是固定不变的,这些都是在布局阶段就固定的 。举例:
Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    DecoratedBox(
      decoration:BoxDecoration(color: Colors.red),
      child: Transform.scale(scale: 1.5,
          child: Text("Hello world")
      )
    ),
    Text("你好", style: TextStyle(color: Colors.green, fontSize: 18.0),)
  ],
)
由于第一个Text、应用变换后,在绘制时会放大,但占用的空间依旧为红色部分,所以第二个Text会紧挨着红色部分,最终文字重合。
  • 矩阵变化只会作用于绘制阶段,所以部分UI变化效果可以直接通过矩阵变化来实现UI视觉效果,而不需要去重新触发build流程,减少layout开销,优化性能。

RotatedBox

RotatedBox和Transform.rotate功能相似,他们都可以对子组件进行旋转变换,但是有一点不同:RotatedBox的变换是在layout阶段,会影响子组件的位置和大小。

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    DecoratedBox(
      decoration: BoxDecoration(color: Colors.red),
      //将Transform.rotate换成RotatedBox  
      child: RotatedBox(
        quarterTurns: 1, //旋转90度(1/4圈)
        child: Text("Hello world"),
      ),
    ),
    Text("你好", style: TextStyle(color: Colors.green, fontSize: 18.0),)
  ],
),

由于RotatedBox是作用于layout阶段,所以子组件会旋转90度(而不只是绘制的内容),decoration会作用到子组件所占用的实际空间上。

Container 容器组件

Container是一个组合类容器,本书不对应具体的RenderObject,它是DecoratedBox、ConstrainedBox、Transform、Padding、Align等组件组合的一个多功能容器。通过它可以同时实现装饰、变换、限制的场景。

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,
  ...
})

需要注意的是:

  • 容器大小可以通过width、height属性来指定,也可以通过constraints来指定;如果同时指定,width、height优先。实际上Container内部会根据width、height来生成一个constraints。
  • color和decoration是互斥的,如果同时设置会报错!实际上,当指定color时,Container内会自动创建一个decoration。

实例:

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),
  ),
 )

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: Colors.orange),
  child: Padding(
    padding: const EdgeInsets.all(20.0),
    child: Text("Hello world!"),
  ),
),