Flutter中widget(一)--单子元素布局

以下内容为自学笔记,若有幸被大神看到,望指正其不准,补充其不足。万分感谢!!!

注:

  • 简单介绍了18个布局,主要控制绘制,定位,约束和大小的;
  • 本篇略长,可根据目录选择性阅读,18种结构都差不多,可以详细看Container。
  • 系统还提供了几个裁剪形状的单元素的布局,有兴趣的可以自行去看源码,他们的父类都是一样的。

一、简介

限定子widget在视图中的位置,大小,间距,对齐方式或背景等。

系统提供18个实现类,如下:

布局类描述
Container一个拥有绘制、定位、调整大小的 widget。
Padding一个widget, 会给其子widget添加指定的填充
Center将其子widget居中显示在自身内部的widget
Align一个widget,它可以将其子widget对齐,并可以根据子widget的大小自动调整大小。
FittedBox按自己的大小调整其子widget的大小和位置。
AspectRatio一个widget,试图将子widget的大小指定为某个特定的长宽比
ConstrainedBox对其子项施加额外约束的widget
Baseline根据子项的基线对它们的位置进行定位的widget。
FractionallySizedBox一个widget,它将子部件的大小调整到总可用空间的一小部分。关于布局算法的更多细节,见RenderFractionallySizedOverflowBox
IntrinsicHeight一个widget,根据子部件的固有高度调整整个子部件的大小。
IntrinsicWidth一个widget,根据子部件的固有宽度调整整个子部件的大小。
LimitedBox一个当其自身不受约束时才限制其大小的盒子
Offstage一个布局widget,可以控制其子widget的显示和隐藏。
OverflowBox对子部件施加的约束与从父部件获得的约束不同,可能允许子部件溢出父部件。
SizedBox一个特定大小的盒子。这个widget强制它的孩子有一个特定的宽度和高度。如果宽度或高度为NULL,则此widget将调整自身大小以匹配该维度中的孩子的大小。
SizedOverflowBox一个特定大小的widget,但是会将它的原始约束传递给它的孩子,它可能会溢出。
Transform在绘制子widget之前应用转换的widget。
CustomSingleChildLayout一个自定义的拥有单个子widget的布局

二、Container

(一)概述

  • 控制子widget的绘制,大小,定位,填充,约束等的容器;
  • 其父类为:StatelessWidget
  • 是功能比较全面的一个布局widget,绘制也会比较繁琐。

(二)属性介绍

名称类型作用
alignmentAlignmentGeometrychild在容器内的对齐方式
paddingEdgeInsetsGeometrychild在容器内的内间距
marginEdgeInsetsGeometry容器与父类的间距
colorColor背景颜色
decorationDecoration背景装饰,不能与color属性同时设置,默认不传,值为color的颜色,
foregroundDecorationDecoration前景装饰,会遮住child,可设置颜色透明度使其可见
widthdouble容器的宽度
heightdouble容器的高度
constraintsBoxConstraints容器宽高的限制
transformMatrix4在绘制容器之前应用的转换矩阵。

1、alignment

  • child的对齐方式,参数类型为AlignmentGeometry

  • AlignmentGeometry为抽象类,系统提供了以下三个实现类可供使用:

    • Alignment:一个具有方便常量的类,固定位置对齐方式,不带有方向性;

      九个常量成员:

      • topLeft :左上对齐;

      • topCenter:顶部居中对齐;

      • topRight:右上对齐;

      • centerLeft:垂直居中靠左对齐;

      • center:居中;

      • centerRight :垂直居中靠右对齐;

      • bottomLeft:左下对齐;

      • bottomCenter:底部居中对齐;

      • bottomRight:右下对齐;

      • 构造函数直接传做标指定位置,如:Alignment(0.0,0.0)为居中。

      • 使用:

        new Container(
          //child在容器内的对齐方式
          alignment: Alignment.topLeft,//或Alignment(-1.0,-1.0)
          color: Colors.white,
          width: 100.0,
          height: 100.0,
          child: Container(
            color: Colors.lightBlueAccent,
            child: new Text('-1,-1\ntopLeft'),
          ),
        ),
        
      • 效果图,坐标图
        在这里插入图片描述

  • AlignmentDirectional:带方向性的对齐方式;

    • 此对齐方式,带有方向性,能与textDirction配合使用改变对齐方式。

    • 单独使用效果与Alignment效果一样。

    • 常量成员有9个:topStarttopCentertopEndcenterStartcentercenterEndbottomStartbottomCenterbottomEnd,start表示左边,end表示右边。

    • 构造函数:

      //这里的start和y就是开始的坐标
      const AlignmentDirectional(this.start, this.y)
        : assert(start != null),
          assert(y != null);
      
    • 使用方法:

      new Container(
        //child在容器内的对齐方式
        alignment: AlignmentDirectional.topLeft,//AlignmentDirectional(-1.0,-1.0)
        color: Colors.white,
        width: 100.0,
        height: 100.0,
        child: Container(
          color: Colors.lightBlueAccent,
          child: new Text('-1,-1\ntopStart'),
        ),
      ),
      
    • 坐标图:
      在这里插入图片描述

    • FractionalOffset

      • Alignment的子类,不同点就是将坐标偏移了,使用构造函数时传入坐标点要注意。

      • 偏移规则从构造函数可以看出:

        const FractionalOffset(double dx, double dy)
           : assert(dx != null),
             assert(dy != null),
             super(dx * 2.0 - 1.0, dy * 2.0 - 1.0);//偏移规则
        
      • 提供了和Alignment名字一样的九个常量成员,效果也一样,就是坐标发生了偏移。

      • 坐标图
        在这里插入图片描述

2、padding和margin

  1. padding:内边距,child与容器边的间距。
  2. margin:外边距,容器与父容器的间距。
  • 两个属性参数类型都是EdgeInsetsGeometry,系统提供了以下两个实现类可供使用:

    • EdgeInsets常用,在四个基本方向中的每个方向上的一组不可变的偏移量。

      • 提供了几个常量构造方法:

        //1.创建一个指定左侧、顶部、右侧和底部的偏移量的对象
        const EdgeInsets.fromLTRB(this.left, this.top, this.right, this.bottom);
        //2.创建一个偏移量都为value值的对象
        const EdgeInsets.all(double value)
            : left = value, top = value, right = value, bottom = value;
        //3。创建一个给某一个或多个位置指定偏移量的对象
        const EdgeInsets.only({
          this.left = 0.0, this.right = 0.0,
          this.top = 0.0, this.bottom = 0.0
        });
        //4.创建一个没有偏移量的对象
        static const EdgeInsets zero = EdgeInsets.only();
        //5.创建一个对称的垂直或水平方向上偏移的对象
        const EdgeInsets.symmetric({ double vertical = 0.0,double horizontal = 0.0 })
          : left = horizontal, top = vertical, right = horizontal, bottom = vertical;
        //6.创建匹配给定窗口填充的insets。
        /// If you need the current system padding or view insets in the context of a
        /// widget, consider using [MediaQuery.of] to obtain these values rather than
        /// using the value from [dart:ui.window], so that you get notified of
        /// changes.
        EdgeInsets.fromWindowPadding(ui.WindowPadding padding, double devicePixelRatio)
          : left = padding.left / devicePixelRatio,
            top = padding.top / devicePixelRatio,
            right = padding.right / devicePixelRatio,
            bottom = padding.bottom / devicePixelRatio;
        
      • 使用方式:

        new Container(
          alignment: FractionalOffset.center,
          color: Colors.white,
          width: 300.0,
          height: 300.0,
          //child与容器内的间距
          padding: EdgeInsets.all(10.0),
          //外边距
          margin: EdgeInsets.all(10.0),
          child: Container(
            alignment: Alignment.center,
            width: 300.0,
            height: 300.0,
            color: Colors.lightBlueAccent,
            child: new Text(
              'The lightBlue is text.'
                  '\nThe white is container.'
                  '\nThe gray is parentContainer.',
              textAlign: TextAlign.center,
            ),
          ),
        ),
        
      • 效果图:
        在这里插入图片描述

    • EdgeInsetsDirectional

      • 带方向(水平)的控制偏移量,

      • 在四个基本方向中的每个方向上的不可变偏移量集,但其水平分量依赖于写入方向

      • 这可以表示文本左填充extDirection.ltr和文本右填充TextDirection.rtl,而不需要知道当前文本的方向。

      • 提供构造函数:

        //1.创建一个从开始、顶部、结束和底部的偏移量创建insets。
        //start表示偏移的开始方向,end表示结束方向的偏移量
        const EdgeInsetsDirectional.fromSTEB(this.start, this.top, 			
                                             this.end,this.bottom);
        //2.创建一个仅使用给定的非零值的insets。
        const EdgeInsetsDirectional.only({
            this.start = 0.0,
            this.top = 0.0,
            this.end = 0.0,
            this.bottom = 0.0
          });
        //3.创建一个每个方向偏移量都为0的对象
        static const EdgeInsetsDirectional zero = EdgeInsetsDirectional.only();
        
        

3、color、decoration和foregroundDecoration

  1. color:背景颜色,不可与decoration同时使用。

  2. decoration`:背景装饰

    • 不设置时默认使用color值作为颜色。不可与color同时使用;
    • 参数类型为Decoration
  3. foregroundDecoration:前景装饰

    • 参数类型为Decoration
  • Decoration为抽象类,系统提供了以下4个实现类:

    • BoxDecoration:绘制一个不可变的矩形或圆形框

      • 该框有边框、一个主体,并且可以投射盒子后面的阴影。
      • 盒子的主体是分层绘制的。最下面的一层是color填充框,上面是gradient,它也填充了这个框,最后是image,它的精确对齐由DecorationImage类控制。border涂在主体上,箱形阴影boxShadow会在它下面绘制。
      • 它的构造方法和参数说明如下:
      const BoxDecoration({
         //填充框的背景颜色;如果为空,则不会绘制背景颜色
         this.color,
         //使填充框有渐变效果;此属性作用在color上,即此属性不为空,则忽略color
         //参数类型:Gradient,有三个实现类:
         //线性LinearGradient、圆形RadialGradient和扫描SweepGradient
         this.gradient,
         //在背景color和渐变gradient上面绘制图片;如果为空,则不会绘制背景图片
         //图片的形状有shape决定
         //参数类型:DecorationImage
         this.image,
         //在color、渐变和图片上方绘制边框;如果为空,则不会绘制边框
         //形状由shape和borderRadius决定
         //参数类型:BoxBorder,有两个实现类Border(无方向)和BorderDirectional(有方向)
         this.border,
         //边框的半径,只适合shape为矩形时。如果shape为圆形circle,则此属性必须为空
         //参数类型:BorderRadiusGeometry,两个实现类BorderRadius和BorderRadiusDirectional
         this.borderRadius,
         //盒子后面的盒子投射的阴影列表,阴影跟随shape的形状
         //参数类型:List<BoxShadow>,含有BoxShadow类型的集合
         this.boxShadow,
         //在画布上作画时使用的算法;默认为BlendMode.srcOver
         //参数类型:BlendMode的枚举值
         this.backgroundBlendMode,
         //填充框的形状,包含矩形rectangle和圆形circle两种;默认为矩形rectangle
         //此属性必不能为空
         //参数类型:BoxShape的枚举值
         this.shape = BoxShape.rectangle,
       }) : assert(shape != null),
            assert(
              identical(backgroundBlendMode, null) || color != null || gradient != null,
               'backgroundBlendMode applies to BoxDecoration\'s background color or '
               'gradient, but no color or gradient were provided.'
            );
      
      • 使用:
      new Container(
        color: Color(0xFFC5CAE9),
        alignment: FractionalOffset.center,
        width: 300.0,height: 300.0,
        child: new Container(
          width: 300.0,height: 300.0,
          alignment: FractionalOffset.center,
          padding: EdgeInsets.all(10.0),
          margin: EdgeInsets.all(10.0),
          //背景颜色,不可以decoration以前设置,因为decoration不设置时默认使用这个color颜色
      //    color: Colors.white,
          //背景装饰,不能与color属性同时出现,即在child后面,可设置颜色,形状,图片等
          decoration: BoxDecoration(
            //背景颜色,最底层
            color: Colors.brown,
            //渐变,第二层
            gradient: LinearGradient(//线性渐变
              //渐变的颜色集合
              colors: [Colors.red, Colors.green, Colors.blue],
            ),
            //背景图片,第三层
            image: DecorationImage(image: AssetImage('images/b.jpg')),
            //边框,第四层
            border: Border(
              left: BorderSide(width: 4.0),
              right: BorderSide(color: Colors.purpleAccent,width: 4.0),
              top: BorderSide(color: Colors.yellowAccent,width: 4.0),
              bottom: BorderSide(color: Colors.pink,width: 4.0),
            ),
            //画布上绘画使用的算法,默认为srcOver,我也不懂原理
            backgroundBlendMode: BlendMode.srcOver,
            //边框圆角半径,shape为圆形时不能设置,而且边框不同颜色设置时也不能设置圆角
      //      borderRadius: BorderRadius.all(Radius.circular(20.0)),
            //阴影集合
            boxShadow: [
              BoxShadow(
                //阴影的颜色
                color: const Color(0xFF000000),
                //x轴和y轴的偏移量
                offset: Offset(1.0, 1.0),
                //高斯函数与盒子形状卷积的标准偏差。
                blurRadius: 1.0,
                //在使用模糊效果之前,框的膨胀量。
                spreadRadius: 1.0,
              )
            ],
            //形状,矩形
            shape: BoxShape.rectangle,
          ),
          //前景装饰,即在child前面,会遮住child,可以更改颜色透明度来使其可见
          foregroundDecoration: BoxDecoration(
            gradient: RadialGradient(//圆形渐变,还有个扫描式渐变SweepGradient
              colors: [Colors.red, Colors.green, Colors.blue],
            ),
            //边框
            border: Border.all(width: 5.0, color: Colors.white),
            //边框的角度,圆形时不能设置圆角半径
      //      borderRadius: BorderRadius.all(Radius.circular(20.0)),
            //形状,圆形
            shape: BoxShape.circle,
          ),
          child: Container(
            color: Colors.lightBlueAccent,
            child: new Text(
             'The lightBlue is text.\nThe center is container.\nThe gray is parentContainer.',
          	textAlign: TextAlign.center,
            ),
          ),
        ),
      ),
      
      • 效果:
        在这里插入图片描述
    • ShapeDecoration:绘制一个不可变的任意形状。

      • 该框有边框、一个主体,并且可以投射盒子后面的阴影。
      • 提供了一种绘制边框的方法,可以选择填充颜色或渐变,可以选择在其中绘制图像,也可以选择投射阴影。
      • 提供的构造方法如下:
       const ShapeDecoration({
          //颜色,与渐变gradient冲突,至少有一个为null
          //如果为null则不设置颜色
          this.color,
          //图片,如果为null则不设置图片
          this.image,
          //渐变,与颜色color冲突,至少有一个为null
          //如果为null则不设置渐变
          this.gradient,
          //阴影,如果为null则不设置阴影
          this.shadows,
          //必写属性,而且必不能为null
          //填充[颜色]、[渐变]和[图像]的形状,并作为[阴影]投射。
          //提供了8个实现类,如下:
        	//Border:一个具有上下左右四个边的盒子
          //BorderDirectional:一个有四个边的盒子,边的侧面(左右两边)根据阅读方向翻转,使用这个会报错,很惭愧,没有找到原因
          //CircleBorder:在可用空间内适合圆形的边框。
          //UnderlineInputBorder:容器的底部绘制一条水平线,并定义容器的形状。常用于InputDecoration
          //OutlineInputBorder:容器周围绘制一个圆角矩形。常用于InputDecoration
          //RoundedRectangleBorder:带有圆角的矩形边框。
          //StadiumBorder:体育场形状,即长边两边是半圆
          //BeveledRectangleBorder:有扁平或“斜角”的矩形边框。
          @required this.shape,
        }) : assert(!(color != null && gradient != null)),//冲突设置
             assert(shape != null);
      
      • 使用:
      new Container(
        color: Color(0xFFC5CAE9),
        alignment: AlignmentDirectional.center,
        width: 300.0,height: 300.0,
        child: new Container(
          width: 300.0,height: 300.0,
          alignment: AlignmentDirectional.center,
          margin: EdgeInsets.all(10.0),
          padding: EdgeInsets.all(10.0),
      
          //背景装饰,不能与color属性同时出现,即在child后面,可设置颜色,形状,图片等
          decoration: ShapeDecoration(
            //颜色,最底层,与渐变gradient冲突
      //      color: Colors.brown,
            //渐变,第二层
            gradient: LinearGradient(colors: [Colors.red, Colors.green, Colors.blue]),
            //背景图片,第三层
            image: DecorationImage(
                image: AssetImage('images/b.jpg'), fit: BoxFit.cover),
            //阴影集合
            /*shadows: [],*/
            //形状
            shape: Border.all(
                  color: Colors.red,//边框颜色
                  width: 4.0,//边框宽度
                )
              	+//加号可以使这三个边框从内向外叠加,以下都是可以叠加的
                Border.all(color: Colors.green, width: 4.0,) 
              	+
                Border.all(color: Colors.blue, width: 4.0,
              
             //圆形边框
             /* CircleBorder(
             		side: BorderSide( color: Colors.green,width: 4.0)
             		) +
                 CircleBorder(
                 	 side: BorderSide(color: Colors.red, width: 4.0)
                 )
                 */
              
            //在底部画条水平线。可以改变形状,
            /*UnderlineInputBorder(
                 borderSide: BorderSide(color: Colors.purpleAccent, width: 14.0),
                 borderRadius: BorderRadius.all(Radius.circular(7.0)),
               )+
               UnderlineInputBorder(
                 borderSide: BorderSide(color: Colors.lightBlueAccent, width: 14.0),
                 borderRadius: BorderRadius.all(Radius.circular(7.0)),
               )*/
              
            //容器周围绘制一个圆角矩形
            /* OutlineInputBorder(
            	    borderSide: BorderSide(color: Colors.purpleAccent,width: 5.0),
            	    borderRadius: BorderRadius.all(Radius.circular(20.0)),
            	  )*/
              
             //带有圆角的矩形边框
             /* RoundedRectangleBorder(
                  side: BorderSide(color: Colors.purpleAccent, width: 5.0),
                  borderRadius: BorderRadius.all(Radius.circular(20.0)),
                )*/    
              
            //体育场边框
            /*StadiumBorder(
           	   side: BorderSide(color: Colors.purpleAccent,width: 5.0),
           	 )*/
                 
            //斜角边框
            /*BeveledRectangleBorder(
           	   side: BorderSide(color: Colors.purpleAccent,width: 5.0),
           	   borderRadius: BorderRadius.all(Radius.circular(20.0)),
           	 )*/ 
              
          ),
          child: Container(
            color: Colors.lightBlueAccent,
            child: new Text(
              'The lightBlue is text.\nThe center is container.\nThe gray is parentContainer.',
              textAlign: TextAlign.center,
            ),
          ),
        ),
      ),
      
      • 效果:
        在这里插入图片描述
    • FlutterLogoDecoration

      • 绘制一个不变的Flutter的logo和标签。
      • 构造函数如下:
      const FlutterLogoDecoration({
          //这两个是logo的颜色,提倡使用默认的
          this.lightColor = const Color(0xFF42A5F5), // Colors.blue[400]
          this.darkColor = const Color(0xFF0D47A1), // Colors.blue[900]
          //Flutter文本标签的颜色
          this.textColor = const Color(0xFF616161),
          //logo样式,分三种FlutterLogoStyle的枚举值,如下:
          //markOnly:默认值,表示只显示logo,不显示标签
         	//horizontal:表示从左到右显示logo和标签
          //stacked:
          this.style = FlutterLogoStyle.markOnly,
          //距离边框的间距
          this.margin = EdgeInsets.zero,
        }) : assert(lightColor != null),
             assert(darkColor != null),
             assert(textColor != null),
             assert(style != null),
             assert(margin != null),
             _position = style == FlutterLogoStyle.markOnly ? 0.0 : style == FlutterLogoStyle.horizontal ? 1.0 : -1.0, 
             _opacity = 1.0;
      
      • 使用
      decoration: FlutterLogoDecoration(
         lightColor: const Color(0xFF42A5F5),
         darkColor : const Color(0xFF0D47A1),
         textColor : const Color(0xFF616161),
         style: FlutterLogoStyle.stacked,
         margin : EdgeInsets.zero,
       ),
      
      • 效果:
        在这里插入图片描述
    • UnderlineTabIndicator

      • 使用TabBar.indicator属性时,在选定的选项卡下方画一条水平线。
      • 构造函数如下
       const UnderlineTabIndicator({
           //边框宽度和颜色
          this.borderSide = const BorderSide(width: 2.0, color: Colors.white),
          this.insets = EdgeInsets.zero,//距选项卡的间距
        }) : assert(borderSide != null), assert(insets != null);
      
      • 使用
      new TabBar(
          labelColor: Colors.yellowAccent,
          unselectedLabelColor: Colors.white,
          tabs: myTabs,
          controller: _tabController,
          //紫色
          indicator: UnderlineTabIndicator(
            borderSide: BorderSide(color: Colors.purpleAccent, width: 4.0),
            insets: EdgeInsets.zero,
          ),
        ),
      ),
      
      • 效果
        在这里插入图片描述

4、constraints

  • 对容器宽高的限制,同时作用在child上

  • 可设置容器最大宽高和最小宽高;

  • 参数类型为:BoxConstraints,其构造函数如下:

    const BoxConstraints({
      //最小宽高的限制,默认是0,不可为负
      this.minWidth = 0.0,this.minHeight = 0.0,
      //最大宽高的限制,默认为double.infinity,不可为负
      this.maxWidth = double.infinity,this.maxHeight = double.infinity
    });
    
  • 使用

new Container(
  color: Color(0xFFC5CAE9),
  alignment: AlignmentDirectional.center,
  width: 300.0,
  height: 300.0,
  child: new Container(
    alignment: Alignment.center,
    width: 300.0,
    height: 300.0,
    margin: EdgeInsets.all(10.0),            
    padding: EdgeInsets.all(10.0),
    decoration: BoxDecoration(
      image: DecorationImage(
          image: AssetImage('images/b.jpg'), fit: BoxFit.cover),
       border: Border(
          left: BorderSide(width: 4.0),
          right: BorderSide(color: Colors.purpleAccent, width: 4.0),
          top: BorderSide(color: Colors.yellowAccent,width: 4.0),
          bottom: BorderSide(color: Colors.pink,width: 4.0),
        ),
         shape: BoxShape.rectangle,
     ),

     //宽高的限制
     constraints: BoxConstraints(
       maxWidth: 250.0,
       maxHeight: 300.0,
     ),
       
     child: Container(
       alignment: Alignment.center,
       width: 300.0,
       height: 300.0,
       color: Colors.lightBlueAccent,
       child: new Text(
         'The lightBlue is text.\nThe center is container.\nThe gray is parentContainer.',
          textAlign: TextAlign.center,
          ),
        ),
    ),
),
  • 效果:
    在这里插入图片描述

5、transform

  • 在绘制容器之前应用的转换矩阵。
  • 提供了一些方法,将容器旋转,平移等效果。
  • 参数类型为:Matrix4,构造函数如下:
//延X轴旋转,参数为弧度
factory Matrix4.rotationX(double radians)
//延Y轴旋转
factory Matrix4.rotationY(double radians)
//延Z轴旋转
factory Matrix4.rotationZ(double radians)
//延给定的空间向量方向平移,参数为xyz方向的空间向量  参数为像素
factory Matrix4.translation(Vector3 translation)
//延给定的X,Y,Z方向平移
factory Matrix4.translationValues(double x, double y, double z)
//延空间向量方向缩放
factory Matrix4.diagonal3(Vector3 scale)
//延给定的X,Y,Z方法缩放,参数为这个三个方向的缩放大小
factory Matrix4.diagonal3Values(double x, double y, double z)
//绕X轴的斜矩阵
factory Matrix4.skewX(double alpha)
//绕Y轴的斜矩阵
factory Matrix4.skewY(double beta) 	
//绕X轴和Y轴的斜矩阵
factory Matrix4.skew(double alpha, double beta) 
  • 使用
Container(
  color: Color(0xFFC5CAE9),
  width: 250.0,height: 200.0,
  alignment: Alignment.center,
  child: Container(
    color: Colors.cyanAccent,
    child: Text('transform参数'),
    transform: Matrix4.diagonal3(Vector3.all(1.5)),
  ),
)
  • 效果如下:
    在这里插入图片描述

(三)绘制流程

  • 源码
 @override
  Widget build(BuildContext context) {
    Widget current = child;
    //先画child
	//首先判断child是否为空,和约束是否为空或是否正确(最小约束是否大于等于最大约束,
    //如果返回true,则将LimitedBox赋值给current,即child,并为其设置约束
    //返回false,则使用当前设置的child和约束
    if (child == null && (constraints == null || !constraints.isTight)) {
      current = LimitedBox(
        maxWidth: 0.0,
        maxHeight: 0.0,
        child: ConstrainedBox(constraints: const BoxConstraints.expand())
      );
    }
    //再画alignment
	//判断对齐方式,不为空则设置对齐方式
    if (alignment != null)
      current = Align(alignment: alignment, child: current);
    //再画padding
	//这里设置间距,首先判断边框decoration的padding,如果没有直接使用容器的padding,
    //如果有,则将容器的padding和边框的padding相加设置给child
    final EdgeInsetsGeometry effectivePadding = _paddingIncludingDecoration;
    if (effectivePadding != null)
      current = Padding(padding: effectivePadding, child: current);
	//再画decoration背景
    if (decoration != null)
      current = DecoratedBox(decoration: decoration, child: current);
	//再画前景
    if (foregroundDecoration != null) {
      current = DecoratedBox(
        decoration: foregroundDecoration,
        position: DecorationPosition.foreground,
        child: current
      );
    }
	//再画约束
    if (constraints != null)
      current = ConstrainedBox(constraints: constraints, child: current);
	//再画margin,由此可看出margin也是有Padding实现
    if (margin != null)
      current = Padding(padding: margin, child: current);
	//再画旋转规则
    if (transform != null)
      current = Transform(transform: transform, child: current);
	//完成
    return current;
  }
  • 图示:从内到外绘制
    在这里插入图片描述

三、定位型布局

1、Padding

  • 为child提供内边距的布局。功能比较单一
  • 父类为SingleChildRenderObjectWidget,大部分单子元素布局的父类,提供了单个child的存储布局,不提供实际的更新逻辑
  • 构造函数如下:
const Padding({Key key,
  //必传参数,并且必不为空,
  //与Container的padding属性一样,详情请看上面介绍
  @required this.padding,
  Widget child,
}) : assert(padding != null),
     super(key: key, child: child);

2、Align和Center

  • Align:将child在内部对齐,并可以调整其大小。

    • 父类为:SingleChildRenderObjectWidget
    • 构造函数如下:
    const Align({Key key,
      //对齐方式,详情请移步Container的alignment属性,两者一样
      this.alignment = Alignment.center,
      //宽度因子,如果设置并且Align没有约束时,Align的宽度就是child的宽度乘以这个值,不能为负数。
      this.widthFactor,
      //高度因子,如果设置并且Align没有约束时,Align的高度就是child的高度乘以这个值,不能为负数。     
      this.heightFactor,
      Widget child
    }) : assert(alignment != null),
         assert(widthFactor == null || widthFactor >= 0.0),
         assert(heightFactor == null || heightFactor >= 0.0),
         super(key: key, child: child);
    
    • widthFactorheightFactornull时,

      • 当其有限制条件的时候,Align会根据限制条件尽量的扩展自己的尺寸;
      • 当没有限制条件的时候,会调整到child的尺寸;
    • widthFactor或者heightFactor不为null时,

      • 当其有限制条件的时候,Align会根据限制条件尽量的扩展自己的尺寸;
      • 当没有限制条件的时候,Aligin会根据factor属性,扩展自己的尺寸,例如widthFactor为2.0的时候,那么,Align的宽度将会是child的两倍。
    • 使用:

      Container(
        color: Color(0xFFC5CAE9),
      // width: 150.0, height: 150.0,
        child: new Align(
          alignment: Alignment.center,
          //宽高因子,觉得Align的大小,与child对应的宽高相乘
          widthFactor: 2.0, heightFactor: 2.0,
          child: Container(
            color: Colors.cyanAccent,
            width: 100.0, height: 20.0,
            child: Text('This is Padding'),
          ),
        ),
      )
      
    • 效果:
      在这里插入图片描述

  • Center:将child居中显示

    • 父类为:Align,只不过是将alignment设置为Alignment.center
    • Align一样使用。

3、Baseline

  • 根据child的基线定位child距顶部的距离的布局控件。
  • 父类为:SingleChildRenderObjectWidget
  • 构造函数如下:
const Baseline({Key key,
  //child的基线距离此框顶部的逻辑像素的数量。              
  @required this.baseline,
  //child的基线类型,TextBaseline的枚举值,如下:
  //TextBaseline.alphabetic  对齐字母字符的字形底部的水平线。
  //TextBaseline.ideographic  对齐表意文字的水平线。            
  @required this.baselineType,
  Widget child
}) : assert(baseline != null),
     assert(baselineType != null),
     super(key: key, child: child);

  • 使用
Container(
  color: Color(0xFFC5CAE9),
  width: 200.0,
  height: 60.0,
  child: new Baseline(
    baseline: 0.0,
    baselineType: TextBaseline.alphabetic,
    child: new Container(
      color: Colors.cyanAccent,
      child: new Text('this is Baseline yjd基线p'),
    ),
  ),
)
  • 效果
    在这里插入图片描述

四、约束型布局

1、LimitedBox

  • child只有在不受约束的情况下才限制其大小的盒子。
  • 限制child的最大宽和高;
  • 通常使用在列表中,以试图匹配它们父级的大小,以便它们在列表中表现得合理;
  • 当在Row横向列表中,高度不受约束;当在Column中,宽度不约束;
  • 构造函数如下:
const LimitedBox({ Key key,
   //限定的最大宽、高,默认值是double.infinity,不能为负数。              
  this.maxWidth = double.infinity,
  this.maxHeight = double.infinity,
  Widget child,
}) : assert(maxWidth != null && maxWidth >= 0.0),
     assert(maxHeight != null && maxHeight >= 0.0),
     super(key: key, child: child);
  • 使用:
Column(
  children: <Widget>[
    Container(color: Color(0xFFC5CAE9),width: 100.0, height: 100.0),
    LimitedBox( 
      maxWidth: 40.0,maxHeight: 14.0,
      child: Container(
        width: 130.0,height: 70.0,
        alignment: Alignment.center,
        color: Colors.cyanAccent,
        child: Text('This is Transform'),
      ),
    ),
  ],
)
//--------------Row-----------------------
Row(
  children: <Widget>[
    Container(color: Color(0xFFC5CAE9),width: 100.0, height: 100.0),
    LimitedBox(
      //限定的最大宽、高,默认值是double.infinity,不能为负数。
      maxWidth: 40.0,maxHeight: 14.0,
      child: Container(
        width: 130.0,height: 70.0,
        alignment: Alignment.center,
        color: Colors.cyanAccent,
        child: Text('This is Transform'),
      ),
    ),
  ],
)
  • 效果
    在这里插入图片描述

2、ConstrainedBox

  • 对child施加额外的约束,对其宽高的最大值和最小值进行了限制;
  • 构造函数如下:
ConstrainedBox({
    Key key,
   	//必传参数,且不可为空,详情请看Container的constraints属性。
    @required this.constraints,
    Widget child
  }) : assert(constraints != null),
       assert(constraints.debugAssertIsValid()),
       super(key: key, child: child);
  • 使用
ConstrainedBox(
  constraints:BoxConstraints(
    //child最小不会小于这对值
    minHeight: 20.0, minWidth: 80.0,
    //child最大不会超过这对值
    maxHeight: 40.0,maxWidth: 150.0,
  ),
  child: Container(
    width: 200.0,height: 70.0,
    alignment: Alignment.center,
    color: Colors.cyanAccent,
    child: Text('This is ConstrainedBox'),
  ),
)
  • 效果
    在这里插入图片描述

3、FittedBox(包含定位)

  • 根据fit设置值,在自己体内对孩子进行缩放和定位。
  • 父类为:SingleChildRenderObjectWidget
  • 如果没有外部约束,则FittedBox与child的大小一致,指定的缩放和定位将失效
  • 如果有外部约束,则将自身大小按外部约束调整,child则响应指定的缩放和定位设置
  • 构造函数如下:
const FittedBox({Key key,
  //child缩放放置的方式,参数值为BoxFit的枚举值,不可为空默认为BoxFit.contain               
  this.fit = BoxFit.contain,
  //对齐方式,同上面介绍               
  this.alignment = Alignment.center,
  Widget child,
}) : assert(fit != null),
     assert(alignment != null),
     super(key: key, child: child);
  • BoxFit的枚举值如下:
enum BoxFit {
  ///child将按照FitBox的宽高比充满目标框,child将会变形
  fill,
  ///尽可能大的将child完全包含在目标框中。不改变child的宽高比
  ///即不改变child宽高比下,同时延长child的宽高,当第一个边达到目标框对应边的大小时,则停止延长
  contain,
  ///尽可能小的将child覆盖整个目标框。不改变child的宽高比,但会丢弃溢出部分
  ///即不改变child宽高比下,同时延长child的宽高,当最后的边达到目标框对应边的大小时,则停止延长
  cover,
  ///不改变child的宽高比,将child的宽填满目标框的宽,但高如果溢出将会丢弃溢出部分
  fitWidth,
  ///不改变child的宽高比,将child的高填满目标框的高,但宽如果溢出将会丢弃溢出部分
  fitHeight,
  ///child尺寸不变,将child对齐在目标框中(默认为居中),但如果child宽高大于目标框,则会丢弃溢出部分
  none,
  ///将child对齐在目标框中(默认为居中),
  ///如果child的宽或高大于目标框时,即需要缩放,则效果同contain
  ///如果child宽和高小于目标框时,即不需要缩放,则效果同none
  scaleDown,
}
  • 使用
Container(
  color: Color(0xFFC5CAE9),
  //如果不设置宽高(即没有外部约束),
  //则FittedBox的大小将与child大小一致,所设置的fit和alignment将不起作用
  width: 200.0,height: 80.0,
  child: new FittedBox(
    fit: BoxFit.scaleDown, //调整child大小的方式
    alignment: Alignment.center, //child的对齐方式
    child: new Container(
      width: 220.0,
      height: 100.0,
      color: Colors.purpleAccent,
      child: new Text('FittedBox'),
    ),
  ),
  • 效果
    在这里插入图片描述

4、AspectRatio

  • 根据指定的宽高比来调整child的大小
  • 父类为:SingleChildRenderObjectWidget
  • 注意事项:
    • AspectRatio父布局同时指定了宽和高时,则其设置的宽高比aspectRatio将失效;
    • aspectRatio与父布局的宽或高其中的一个配合使用才会生效。
    • 当其自身有约束时:
      • 如果约束值范围,包含AspectRatio根据宽高比算出的大小时,则使用计算出的尺寸;
      • 如果约束值范围,不包含根据宽高比算的的尺寸时,则放弃使用计算出的尺寸,而使用约束值。
  • 构造函数如下:
const AspectRatio({Key key,
  //必传参数,并且能为空;调整child要使用的宽高比                 
  @required this.aspectRatio,
  Widget child
}) : assert(aspectRatio != null),
     super(key: key, child: child);
  • 使用
Container(
  color: Color(0xFFC5CAE9),
  padding: EdgeInsets.all(4.0),
//    width:200.0,
  height: 40.0,
  //当设置约束时,AspectRatio最终尺寸不在这个范围内时,则以约束为准
//    constraints: BoxConstraints(maxWidth: 110.0,maxHeight: 35.0),
  child: new AspectRatio(
    aspectRatio: 3.0, //宽高比(宽/高),等于1时相当于宽高相等,将child按这个比值设置大小
    child: new Container(
      alignment: Alignment.center,
      color: Colors.cyanAccent,
      child: new Text('AspectRatio'),
    ),
  ),
)
  • 效果
    在这里插入图片描述

5、SizedBox

  • 创建一个指定宽高的框,将child的大小固定
  • 父类为:SingleChildRenderObjectWidget
  • 设置宽和高时,取决于父框有没有限制
    • 当父框有限制时:则依赖父框限制设置其大小,
    • 当父框没有限制时:则使用设置的宽高
  • 构造函数如下:
const SizedBox({ Key key, 
    //指定child的宽,高            
	this.width,.height, 
    Widget child }): super(key: key, child: child);
//child在父框允许的范围填充
const SizedBox.expand({ Key key, Widget child })
  : width = double.infinity,
    height = double.infinity,
    super(key: key, child: child);
//child在父类的范围内尽可能的小,即没有
const SizedBox.shrink({ Key key, Widget child })
  : width = 0.0,
    height = 0.0,
    super(key: key, child: child);
//通过Size将宽高传给child
SizedBox.fromSize({ Key key, 
  Widget child,                  
  Size size,//Size内包含宽和高
}): width = size?.width,
    height = size?.height,
    super(key: key, child: child);
  • 使用:
Container(
  width: 180.0,
  height: 100.0,
  padding: EdgeInsets.all(5.0),
  color: Colors.red,//红色大背景
  alignment: Alignment.center,
  child: Container(
    color: Color(0xFFC5CAE9),//灰色,SizedBox的父框颜色
    padding: EdgeInsets.all(10.0),
    child: new SizedBox(
      width: 120.0,
      height: 50.0,
      child: Container(
        color: Colors.cyanAccent,//SizeBox的child颜色,也相当于Size的Box的颜色
      ),
    ),
  ),
)
  • 效果如下:
    在这里插入图片描述

6、OverflowBox(带定位)

  • 对子部件施加的约束与从父部件获得的约束不同,可能允许子部件溢出父部件。
  • 父类为:SingleChildRenderObjectWidget
  • 构造函数如下:
const OverflowBox({Key key,   
  this.alignment = Alignment.center,//对齐方式
  this.minWidth,//对child的最小宽度约束,如果为null(默认),则使用父元素的约束
  this.maxWidth,//对child的最大宽度约束,如果为null(默认),则使用父元素的约束
  this.minHeight,//对child的最小高度约束,如果为null(默认),则使用父元素的约束
  this.maxHeight,//对child的最大高度约束,如果为null(默认),则使用父元素的约束
  Widget child,
}) : super(key: key, child: child);
  • 使用
Container(
  width: 200.0,height: 200.0,
  padding: EdgeInsets.all(5.0),//内边距5
  color: Color(0xFFC5CAE9),//父框背景色--灰色
  child: new OverflowBox(
    alignment: Alignment.topLeft,//左上对齐
    maxWidth: 300.0,
    maxHeight: 250.0,
    child: new Container(
      color: Colors.cyanAccent,//相当于OverflowBox背景色---浅蓝色
      width: 150.0, height: 300.0,
    ),
  ),
),
  • 效果如下:
    在这里插入图片描述

7、SizedOverflowBox(带定位)

  • 具有特定大小的小部件,但将其原始约束传递给子部件,然后子部件可能会溢出。
  • 与6相似,但效果未出来!!!!!放弃吧。。。。。

8、FractionallySizedBox(带定位)

  • 将child的大小调整到总可用空间的一小部分。超出会溢出
  • 父类为:SingleChildRenderObjectWidget
  • 构造函数如下:
    • 当宽高因子不为空时,最终指定给child的大小为,约束的宽高 乘以对应的宽高因子。
const FractionallySizedBox({Key key,
  this.alignment = Alignment.center,//对齐方式默认居中
  this.widthFactor,//宽因子,不可为负
  this.heightFactor,//高因子,不可为负
  Widget child,
}) : assert(alignment != null),
     assert(widthFactor == null || widthFactor >= 0.0),
     assert(heightFactor == null || heightFactor >= 0.0),
     super(key: key, child: child);
  • 使用
Container(
  width: 150.0,height: 100.0,
  padding: EdgeInsets.all(5.0),
  color: Color(0xFFC5CAE9),//父框颜色 灰色
  child: new FractionallySizedBox(
    alignment : Alignment.topLeft,//左上对齐
    //宽高因子 
    widthFactor:0.5, heightFactor:0.5,
    child: new Container(
      alignment: Alignment.center,
      color: Colors.cyanAccent,
    ),
  ),
)
  • 效果 如下
    在这里插入图片描述

9、IntrinsicHeight

  • 一个小部件,它根据一个child的固有高度调整child组的高度
  • 父类为:SingleChildRenderObjectWidget
  • 官方说很有用,但效率低,因为在最终布局阶段之前添加了一个推测布局传递,因此 不建议使用。
  • 他的作用,是将可能高度不受限制的child,调整到一个合适并且合理的尺寸。
  • 构造函数如下:
const IntrinsicHeight({Key key,  
   //只有一个child属性                    
   Widget child 
}) : super(key: key, child: child);
  • 使用:
new IntrinsicHeight(
  child: new Row(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    children: <Widget>[
        new Container(color: Colors.blue, width: 100.0),
	    new Container(color: Colors.red, width: 50.0, height: 50.0),
	    new Container(color: Colors.cyanAccent, width: 70.0, height: 70.0),
	    new Container(color: Colors.yellow, width: 130.0),
    ],
  ),
)
  • 效果:
    在这里插入图片描述

10、IntrinsicWidth

  • 一个小部件,它根据一个child的固有宽度调整child组的宽度
  • 父类为:SingleChildRenderObjectWidget
  • IntrinsicHeight类似,存在效率问题,建议能不用就不用;
  • 构造函数如下:
    • stepHeight:不为空时
      • 当设置的值小于等于child的总高度时,则将把IntrinsicWidth的高度设置成stepHeight倍数,使最终值接近child的总高度;如例中:此值为100,则最终值为100*3=300
      • 当设置高度大于child总高度时,最终就是设置的值。
    • stepWidth:不为空时:
      • 当设置的值小于等于child组内固定值中最大的值时,则将把IntrinsicWidth的宽度设置成stepWidth倍数,使最终值接近child的最大值;如例:此值为40,则最终值为40*2 =80
      • 当设置高度大于child宽度最大值时,最终就是设置的值。
const IntrinsicWidth({ Key key,
  //参数类型为double
  //如果不为null,则强制child宽度为该值,   
  //或该值的/*倍数*/(该值大小小于等于child内总宽度时),使其大小接近近child内总宽度         
  this.stepWidth, 
  //如果不为null,则强制child高度为该值,
  //或该值的/*倍数*/(该值大小小于等于child内总高度时),使其大小接近近child内总高度                 
  this.stepHeight, 
  Widget child 
}): super(key: key, child: child);
  • 使用
Container(
  color:Color(0xFFC5CAE9),
  child: new IntrinsicWidth(
    //
    stepHeight: 27.0,
    stepWidth: 10.0,
    child: new Column(
      children: <Widget>[
        new Container(color: Colors.blue, height: 60.0),
        new Container(color: Colors.cyanAccent, width: 50.0, height: 50.0),
        new Container(color: Colors.red, width: 70.0, height: 70.0),
        new Container(color: Colors.yellow, height: 90.0),
      ],
    ),
  ),
)
  • 效果如下
    在这里插入图片描述

五、Offstage

  • 控制child是否隐藏,默认是隐藏
  • 父类为:SingleChildRenderObjectWidget
  • 构造函数如下:通过参数offstage决定
    • 当offstage为true,当前控件不会被绘制在屏幕上,不会响应点击事件,也不会占用空间;
    • 当Offstage不可见的时候,如果child有动画,应该手动停掉,Offstage并不会停掉动画;
    • 当offstage为false,当前控件则跟平常用的控件一样渲染绘制。
const Offstage({ Key key, 
  //通过这个参数控制child的是否隐藏,默认为true隐藏              
  this.offstage = true, 
  Widget child }): assert(offstage != null),super(key: key, child: child);
  • 使用
class _SingleChildFullPageState extends State<SingleChildFullPage> {
  bool offstage = false;
  var hint = '隐藏';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar( title: Text('Offstage')),
      body: Column(
        children: <Widget>[
          RaisedButton(
            //点击更改offstage属性,即点击隐藏或显示Offstage的child
            onPressed: () {
              setState(() {
                offstage = !offstage;
                hint = offstage ? '显示' : '隐藏';
              });
            },
            child: Text(hint),
          ),
          Offstage(
            offstage: offstage,
            child: Container(color: Colors.cyanAccent,child: Text('Offstage')),
          ),
        ],
      ),
    );
  }
}
  • 效果如下:
    在这里插入图片描述

六、Transform(带定位)

  • 在绘制容器之前做转换矩阵;
  • 可以对child做平移、旋转、缩放等操作。
  • 父类为:SingleChildRenderObjectWidget
  • 构造函数如下:
//默认构造函数
const Transform({Key key,
  //必填参数,且不能为空,参数类型为Matrix4(变形矩阵)           
  @required this.transform,
  this.origin,//平移的偏移量
  this.alignment,//对齐方式
  this.transformHitTests = true,//是否在执行hit测试时应用转换。默认为true
  Widget child,}) : assert(transform != null), super(key: key, child: child);

//旋转功能的构造函数
Transform.rotate({Key key,
  //必填参数,旋转的角度                
  @required double angle,
  this.origin,
  this.alignment = Alignment.center,
  this.transformHitTests = true,
  Widget child,}) : transform = Matrix4.rotationZ(angle),super(key: key, child: child);

//平移功能的构造函数
Transform.translate({Key key,
  //必填,平移的偏移量                   
  @required Offset offset,
  this.transformHitTests = true,
  Widget child,
}) : transform = Matrix4.translationValues(offset.dx, offset.dy, 0.0),
     origin = null,alignment = null,super(key: key, child: child);

//缩放功能的构造函数
Transform.scale({Key key,
  //必填 缩放大小        
  @required double scale,
  this.origin,
  this.alignment = Alignment.center,
  this.transformHitTests = true,
  Widget child,
}) : transform = Matrix4.diagonal3Values(scale, scale, 1.0),
     super(key: key, child: child);
  • 使用,以默认构造为例,延Z轴旋转,其他的直接传参即可
Container(
  color:Color(0xFFC5CAE9),
   width: 250.0,
   height: 200.0,
   alignment: Alignment.center,
   child: Transform(
     transform: Matrix4.rotationZ(0.5),
     child: Container(
       color: Colors.blue,
       width: 100.0,
       alignment: Alignment.center,
       height: 100.0,
       child: Text('Transform'),
    ),
  ),
)
  • 效果如下
    在这里插入图片描述

七、CustomSingleChildLayout

  • 通过一个代理来控制child的布局,也可理解为自定义的单元素布局。
  • 这个代理delegate可以控制child的约束constaints和位置;在parent的尺寸不依赖child的情况下,还可以对顶parent的尺寸。
  • 父类为:SingleChildRenderObjectWidget
  • 构造函数:
const CustomSingleChildLayout({Key key,
  //必传非空参数,一个代理,类型为SingleChildLayoutDelegate,
  //需要自己自定义实现类                             
  @required this.delegate,
  Widget child
}) : assert(delegate != null),
     super(key: key, child: child);
  • SingleChildLayoutDelegate抽象类
abstract class SingleChildLayoutDelegate {
  //提供的构造函数,可以传一个监听,来监听relayout
  const SingleChildLayoutDelegate({ Listenable relayout }) : _relayout = relayout;
  final Listenable _relayout;

  //传入约束的此对象的大小。
  //默认为满足给定约束的最大大小。
  Size getSize(BoxConstraints constraints) => constraints.biggest;

  //传入约束的child的约束。
  //在布局过程中,child会得到这个函数返回的布局约束。child需要为自己选择一个满足这些约束的大小。
  //默认为传入的指定的约束。
  BoxConstraints getConstraintsForChild(BoxConstraints constraints) => constraints;

  /**
   * 放置child的位置
   * @param size       父元素的大小
   * @param childSize  子元素的大小
   * 
   * 默认将子元素定位在父元素的左上角。
   */
  Offset getPositionForChild(Size size, Size childSize) => Offset.zero;

  /**
   * 判断是否需要重新布局的。
   * 我们在自定义写delegate的时候,可以选择需要进行修改的属性进行重写,并给予相应的布局属性即可。
   * 返回true时,则需要relayout。false时不需要
   * 
   * @param oldDelegate   老的布局,可以依据这个与新布局对比,不一样则返回true
   */
  bool shouldRelayout(covariant SingleChildLayoutDelegate oldDelegate);
}
  • 布局源码
@override
void performLayout() {
  //首先通过传来的代理,获取设置尺寸大小
  size = _getSize(constraints);
  if (child != null) { //child不为空时
    //通过传来的代理,获取设置child的约束
    final BoxConstraints childConstraints = delegate.getConstraintsForChild(constraints);
    assert(childConstraints.debugAssertIsValid(isAppliedConstraint: true));
    child.layout(childConstraints, parentUsesSize: !childConstraints.isTight);
    final BoxParentData childParentData = child.parentData;
    //通过传来的代理,获取设置位置
    childParentData.offset = delegate.getPositionForChild(size, childConstraints.isTight ? childConstraints.smallest : child.size);
  }
}
  • 使用
//这个只针对了尺寸做了设置
class FixedSizeLayoutDelegate extends SingleChildLayoutDelegate {
  FixedSizeLayoutDelegate(this.size);
  final Size size;
  @override
  Size getSize(BoxConstraints constraints) => size;
  //创建仅受给定大小约束的框约束。
  @override
  BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
    return new BoxConstraints.tight(size);
  }
  //这个只针对了尺寸,当尺寸改变时,才会relayout
  @override
  bool shouldRelayout(FixedSizeLayoutDelegate oldDelegate) {
    return size != oldDelegate.size;
  }
}
//-----------------------------------------------------
Container(
  color: Color(0xFFC5CAE9),
  width: 200.0,height: 150.0,
  alignment: Alignment.center,
  child: new CustomSingleChildLayout(
    delegate: FixedSizeLayoutDelegate(
      Size(170.0, 20.0),
    ),
    child: Container(
      child: Text('CustomSingleChildLayout'),color: Colors.cyanAccent),
  ),
)
  • 效果
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值