01-1 拥有单个子元素的布局 widget

[toc]

拥有单个子元素的布局 widget

Padding

包裹子 widget 为其添加间距,Padding Widget 的大小是 child 的大小加上 padding。

  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("PaddingWidget"),),
        body: Padding(
//          padding: const EdgeInsets.all(20),// 上左下右 padding 都是 20
          padding: const EdgeInsets.only(left: 20,top: 50,right: 80,bottom: 100),//分别设置
          child: Text("Content"),
        ),
      ),
    );
  }

Center

将 child 放在垂直水平都居中的位置显示。如果没有指定 Center Widget 的大小,那么它就会尽可能的大,类似 match_parent 。如果指定 widthFactor 和 heightFactor 那么它的大小就根据指定的值来设定。例如:widthFactor 指定为 2.0, Center Widget 的宽为 child 宽的 2 倍。

  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("PaddingWidget"),),
        body: Center(
          widthFactor: 2.0,// 宽度为 child 宽的 2 倍
          heightFactor: 2.0,
          child: Container(
            width: 100, // 指定宽度为 100
            height: 100,
            color: Colors.pinkAccent,
          ),
        ),
      ),
    );
  }

Align

将子 widget 根据指定的对齐方式放置在 Align Widget 中,Align Widget 大小计算方式与 Center Widget 相同。

对齐方式 AlignmentGeometry 类型参数可以通过三种方式设置

  1. Alignment 的常量。如:Alignment.topRight 于 Align Widget 上右对齐
  2. Alignment 构造。以 Align Widget 为中心为原点(0,0),参数 x 是 0.5 * child 宽的倍数。y 是 0.5 * child 高的倍数。x 和 y 的取值范围为[-1,1]。
  3. FractionalOffset。以 Align Widget 的左顶点为原点(0,0),参数 x 是 child 宽的倍数。y 是 child 高的倍数。x 和 y 的取值范围为[0,1]。
 Widget build(BuildContext context) {
    TextStyle txtStyle = TextStyle( //文本样式
      fontWeight: FontWeight.bold,
      fontSize: 18.0,
    );
    
    Widget getAlignWidthAlign(AlignmentGeometry align,Color childColor){
      return Align(
        widthFactor: 2.0,
        heightFactor: 2.0,
        alignment: align,
        child: Container(
          width: 50,
          height: 50,
          color: childColor,
        ),
      );
    }
    
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("AlignWidget"),),
        body: Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            Padding(
              padding: const EdgeInsets.all(20),
              child: Text("Const" ,style: txtStyle,),
            ),
            Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                getAlignWidthAlign(Alignment.topLeft, Colors.pinkAccent),
                getAlignWidthAlign(Alignment.center, Colors.lightBlueAccent),
                getAlignWidthAlign(Alignment.bottomRight, Colors.lightGreenAccent)
              ],
            ),
            Padding(
              padding: const EdgeInsets.all(20),
              child: Text("Alignment Constructors" ,style: txtStyle,),
            ),
            Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                // 原点 即 center 
                getAlignWidthAlign(Alignment(0, 0), Colors.pinkAccent),
                //参数是二分之一 child 宽高的倍数
                // 从中心点向右移动 child 宽度的一半 ,向下移动 child 高度的一半 ,即 rightBottom
                getAlignWidthAlign(Alignment(1, 1), Colors.lightBlueAccent),
                getAlignWidthAlign(Alignment(-1, -1), Colors.lightGreenAccent)
              ],
            ),
            Padding(
              padding: const EdgeInsets.all(20),
              child: Text("FractionalOffset" ,style: txtStyle,),
            ),
            Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                //参数是 child 宽高的倍数
                //原点 即 leftTop
                getAlignWidthAlign(FractionalOffset(0, 0), Colors.pinkAccent),
                //向右移动 child 宽度和高度的 0.5 倍,即 center
                getAlignWidthAlign(FractionalOffset(0.5, 0.5), Colors.lightBlueAccent),
                getAlignWidthAlign(FractionalOffset(1, 1), Colors.lightGreenAccent)
              ],
            ),
          ],

        ),
      ),
    );
  }

ConstrainedBox

为 child 添加一个 ConstrainedBox 约束来指定 child 的 minWidth、minHeight、maxWidth、maxHeight。 child 的最终尺寸由 child 的原始 尺寸和约束同时决定,例如 child 宽为 x :

  • x < minWidth => minWidth
  • x > maxWidth => maxWidth
  • minWidth < x < maxWidth => x

高同理。

  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("ConstrainedBox Demo"),),
        body: ConstrainedBox(
            constraints: BoxConstraints(
              minWidth: 50,
              minHeight: 50,
              maxWidth: 200,
              maxHeight: 200,
            ),
            child: Container(
              width: 100, // 指定宽度为 100
              height: 100,
              color: Colors.pinkAccent,
            ),
        ),
      ),
    );
  }

Transform

为 child 添加平移(translate)、缩放(scale)、旋转(rotate)三种转变。

  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("Transform Widget"),),
        body: Transform.translate(// translate 平移
          //offset x 轴方向平移 100, y 轴方向平移100
          offset: Offset(100, 100), 
          child:  Container(
            width: 100, // 指定宽度为 100
            height: 100,
            color: Colors.pinkAccent,
          ),
        ),
      ),
    );
  }
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("Transform Widget"),),
        body: Center(
          child: Transform.rotate(
            //origin 旋转的中心点,默认 child 中点
            origin: Offset(0, 100), //原点向下移动 100 即底边中点
            angle: 45,//顺时针旋转 45度
            child:  Container(
              width: 100, // 指定宽度为 100
              height: 200,
              color: Colors.pinkAccent,
            ),
        ),
        ),
      ),
    );
  }
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar( title: Text("Transform Widget"), ),
          body: Center(
            child: Transform.scale(
              //缩放 倍数
              scale: 2,
              // 默认缩放中点是 child 中点,即 center
              //alignment 和 origin 可以改变缩放中点
              alignment: Alignment.topRight,//缩放中点为右顶点
              origin: Offset(-50, 100),// 将缩放中点左移 50 下移100
              child: Container(
                width: 100, // 指定宽度为 100
                height: 200,
                color: Colors.pinkAccent,
              ),
            ),
          )),
    );
  }

alignment 和 origin 同时存在时缩放中点定位先计算 alignment 再计算 origin。有趣的是当 origin 的 offset 移动超过了 child 的范围时,offset 对缩放中点的影响并不是原来的 x 轴 正右负左,y轴 正下负上。

如图 4 ,alignment 为右顶点,offset(50,100) 此时向右移动超出 child 的范围,x 轴的移动变成了 向左移动 150 (child宽(100) + 50)。

Container

作为最常用的拥有单个子元素的布局 widget,首先 Container 会尽可能的大,类似 match_parent。然后它整合了上面介绍的 widget 功能,可以同时添加 padding、margin、constraints、transform,还可添加 decoration 装饰。

BoxDecoration 盒装饰可以添加边框、边框圆角、背景颜色、背景图片等。

  Widget build(BuildContext context) {

    return MaterialApp(

      home: Scaffold(
        appBar: AppBar(
          title: Text('Container'),
        ),
        body: Container(
            width: 300,
            height: 300,// 宽高
            constraints: BoxConstraints.loose(Size(200, 200)),//约束 Container 宽高不能超过 200
            alignment: Alignment.bottomRight,// Container 中 child 的对齐为右下
            margin: const EdgeInsets.all(30.0),// Container 边距
            padding: const EdgeInsets.all(20.0),// Container 距 child 的间距
            decoration: BoxDecoration(
                border: Border.all( // Container 的边框
                    color: Colors.red,
                    width: 15.0
                ),
                //shape: BoxShape.circle,//shape 为 circle 时不能设置 borderRadius
                // color: Colors.yellow[300], //Container 背景颜色
                borderRadius: const BorderRadius.all(const Radius.circular(30.0)) // 边框圆角
            ),
            transform: Matrix4.translationValues(50, 50, 0),// Container 平移
            child: Container(
              width: 100, // 指定宽度为 100
              height: 100,
              color: Colors.pinkAccent,
            )
        ),
      ),
    );
  }

FittedBox

根据缩放选项(fit)对child 进行缩放,还可以利用 对齐(alignment)来设置 child 的位置。

BoxFit 的枚举值如下,Image 也是用这些枚举值来控制缩放的。

缩放选项 说明 效果
BoxFit.contain 等比缩放,显示的尽可能大
BoxFit.cover 尽可能小,但仍覆盖整个 box
BoxFit.fill 不考虑缩放比例,单纯填满整个 box
BoxFit.fitHeight 等比缩放,使 child 的高和 box 一致
BoxFit.fitWidth 宽一致
BoxFit.none 啥都不做
BoxFit.scaleDown 等比将 child 缩小到 box 可以装下它,如果 box 原本就可以装下它就啥都不做
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("FittedBoxWidget"),),
        body:Container(
          width: 200,
          height: 200,
          child: FittedBox(
            fit: BoxFit.fitWidth,//适应宽度
            alignment: Alignment.topCenter,//上中对齐
            child: Container(
              width: 100, // 指定宽度为 100
              height: 50,
              color: Colors.pinkAccent,
            ),
          ),
        ),
      ),
    );
  }

AspectRatio

按照指定的宽高比设置 child 的大小

  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("AspectRatioWidget"),
        ),
        body: Container(
          // AspectRatio 的 parent 不能指定宽度。
          // 指定宽度后 aspectRatio 失效,怎么设置都会填满 parent
          height: 300,
          child: AspectRatio(
            aspectRatio: 0.5,// 宽高比   1 / 2
            child: Container( // AspectRatio 的 child 指定宽高无效
              width: 1,
              height: 1,
              color: Colors.pinkAccent,
            ),
          ),
        ),
      ),
    );
  }

Baseline

设置一条基线,使 child 根据基线类型与基线对齐。

基线类型(baselineType)

  • TextBaseline.alphabetic :文字底部 , 例如 good 即 g 的底部
  • TextBaseline.ideographic : 文字基线

baselineType 当child 是 Text 时 生效, 如果不是 Text ,则 child 的底部跟 基线对齐。

  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("BaselineWidget"),
        ),
        body: Container(
          width: 200,
          height: 200,
          margin: const EdgeInsets.all(20),
          child: Baseline(
            //基线位置
            baseline: 90,
            //child 是 Text 时 生效; 如果不是 Text ,则 child 的底部跟 基线对齐
            baselineType: TextBaseline.ideographic,
            child: Container(
              width: 100,
              height: 100,
              color: Colors.pinkAccent,
            ),
          ),
        ),
      ),
    );
  }

你可能感兴趣的:(01-1 拥有单个子元素的布局 widget)