【Flutter】 自学(五)-Flutter容器组件

1,157 阅读4分钟

Padding

Padding可以给其子节点添加填充(留白),使用padding属性,通过EdgeInsets设置

我们看看EdgeInsets提供的便捷方法:

  • fromLTRB(double left, double top, double right, double bottom):分别指定四个方向的填充。
  • all(double value) : 所有方向均使用相同数值的填充。
  • only({left, top, right ,bottom }):可以设置具体某个方向的填充(可以同时指定多个方向)。
  • symmetric({ vertical, horizontal }):用于设置对称方向的填充,vertical指top和bottom,horizontal指left和right。

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Container(
          width: 400,
          height: 400,
          color: Colors.red,
          child: Padding(
            padding: EdgeInsets.only(top:30),
            child: Container(
              color: Colors.blue,
            ),
          ),
        ));
  }
}

限制类容器

ConstrainedBox

ConstrainedBox用于对子组件添加额外的约束,比如最小高度,通过constraints属性,BoxConstraints设置

const BoxConstraints({
  this.minWidth = 0.0, //最小宽度
  this.maxWidth = double.infinity, //最大宽度
  this.minHeight = 0.0, //最小高度
  this.maxHeight = double.infinity //最大高度
})

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: ConstrainedBox(
          constraints: BoxConstraints(
            minHeight: 20,
            minWidth: 50,
            maxWidth: 100,
            maxHeight: 150,
          ),
          child: Container(
            width: 10,
            height: 200,
            color: Colors.red,
          ),
        ));
  }
}

最终显示是宽50,高150

UnconstrainedBox

UnconstrainedBox组件不对子组件做任何约束

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Container(
          width: 200,
          height: 200,
          child: UnconstrainedBox(
            child: Container(
              width: 300,
              height: 300,
              color: Colors.red,
            ),
          ),
        ));
  }
}

UnconstrainedBox虽然不限制其子控件的大小,但仍然受父控件的约束,超出父控件的区域将会截取。

SizedBox

SizedBox是具有固定宽高的组件

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: SizedBox(
          ///无限大
          width: double.infinity,
          height: double.infinity,
        ));
  }
}

SizedBox可以没有子组件,但仍然会占用空间,所以SizedBox非常适合控制2个组件之间的空隙,指定宽或者高即可

AspectRatio

AspectRatio组件是固定宽高比的组件,比如一个宽高比为1:2的盒子

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: AspectRatio(
          aspectRatio: 1 / 2,
          child: Container(
            color: Colors.red,
          ),
        ));
  }
}

FractionallySizedBox

FractionallySizedBox 可以根据父容器宽高的百分比来设置子组件宽高,比如当前控件的宽度占父组件的50%

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Container(
          width: 300,
          height: 300,
          color: Colors.red,
          child: FractionallySizedBox(
            widthFactor: 0.5,
            heightFactor: 0.5,
            alignment: Alignment.topLeft,
            child: Container(
              color: Colors.blue,
            ),
          ),
        ));
  }
}

widthFactor和heightFactor 大小是0-1

LimitedBox

LimitedBox组件是当不受父组件约束时限制它的尺寸,比如列表中,一般是用于指定最大宽高

 ListView(
  children: <Widget>[
    LimitedBox(
      maxHeight: 100,
      child: Container(
        color: Colors.green,
      ),
    ),
    LimitedBox(
      maxHeight: 100,
      child: Container(
        color: Colors.red,
      ),
    ),
  ],
)

装饰容器DecoratedBox

DecoratedBox可以在其子组件绘制前(或后)绘制一些装饰(Decoration),如背景、边框、渐变等,主要属性如下:

  • decoration:代表将要绘制的装饰,它的类型为Decoration
  • position:此属性决定在哪里绘制Decoration,它接收DecorationPosition的枚举类型,该枚举类有两个值:
    • background:在子组件之后绘制,即背景装饰。

    • foreground:在子组件之上绘制,即前景。

BoxDecoration

BoxDecoration({
  Color color, //颜色
  DecorationImage image,//图片
  BoxBorder border, //边框
  BorderRadiusGeometry borderRadius, //圆角
  List<BoxShadow> boxShadow, //阴影,可以指定多个
  Gradient gradient, //渐变
  BlendMode backgroundBlendMode, //背景混合模式
  BoxShape shape = BoxShape.rectangle, //形状
})

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: DecoratedBox(
          //在哪里绘制Decoration
          position: DecorationPosition.background,
          decoration: BoxDecoration(

              ///渐变
              gradient: LinearGradient(colors: [Colors.yellow, Colors.red]),
              //3像素圆角
              borderRadius: BorderRadius.all(Radius.circular(3.0)),
              boxShadow: [
                BoxShadow(
                  color: Colors.black,
                  //偏移量
                  offset: Offset(3, 3),
                  blurRadius: 4.0,
                )
              ]),
          child: FlatButton(
            child: Text(
              "This is FlatButton",
              style: TextStyle(color: Colors.white),
            ),
            onPressed: null,
          ),
        ));
  }
}

变换(Transform)

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Column(
          children: [
            Text("平移"),
            DecoratedBox(
              decoration: BoxDecoration(color: Colors.red),
              //默认原点为左上角,左移20像素,向上平移5像素
              child: Transform.translate(
                offset: Offset(-20.0, -5.0),
                child: Text("平移"),
              ),
            ),
            SizedBox(
              height: 20,
            ),
            Text("旋转"),
            DecoratedBox(
              decoration: BoxDecoration(color: Colors.red),
              child: Transform.rotate(
                //旋转90度
                angle: math.pi / 2,
                child: Text("旋转"),
              ),
            ),
            SizedBox(
              height: 20,
            ),
            Text("旋转2"),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                DecoratedBox(
                  decoration: BoxDecoration(color: Colors.red),
                  child: RotatedBox(
                    quarterTurns: 1,
                    child: Text("旋转2"),
                  ),
                ),
                Text(
                  "有区别吧",
                  style: TextStyle(color: Colors.green, fontSize: 18.0),
                )
              ],
            ),
            SizedBox(
              height: 20,
            ),
            Text("缩放"),
            DecoratedBox(
              decoration: BoxDecoration(color: Colors.red),
              child: Transform.scale(
                scale: 1.5, //放大到1.5倍
                child: Text("缩放"),
              ),
            )
          ],
        ));
  }
}

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

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

大小通过widthheight指定,内边距通过padding指定,外边距通过margin指定

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Column(
          children: [
            Container(
              width: 200,
              height: 200,
              color: Colors.red,
              alignment: Alignment.center,
              child: Text(
                "Hello World",
                style: TextStyle(color: Colors.white, fontSize: 18),
              ),
            ),
            Container(
              color: Colors.yellow,
              alignment: Alignment.center,
              padding: EdgeInsets.all(30),
              child: Text(
                "Hello World",
                style: TextStyle(color: Colors.black, fontSize: 18),
              ),
            ),
            Container(
              color: Colors.blue,
              alignment: Alignment.center,
              margin: EdgeInsets.all(30),
              child: Text(
                "Hello World",
                style: TextStyle(color: Colors.black, fontSize: 18),
              ),
            )
          ],
        ));
  }
}

注意:colordecoration是互斥的,如果同时设置它们则会报错!实际上,当指定color时,Container内会自动创建一个decoration