Flutter踩坑之路(三)一页面布局(基础布局)

前几篇博客,我们主要讲了Flutter中的基本组件,那么,我们这边博客就来讲一下Flutter中的页面布局。

页面布局包括基础布局处理、宽高尺寸处理、列表及表格布局、其他布局处理等。

基础布局

主要包括:Container(容器布局),Center(居中布局),Padding(填充布局),Align(对齐布局),Column(垂直布局),Row(水平布局),Expanded(配合Column,Row使用),FittedBox(缩放布局),Stack(层叠布局),OverflowBox(溢出父视图容器)。

Container(容器布局)

Container(容器布局)是一个组合Widget,内部有绘制Widget、定位Widget和尺寸Widget。

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

注:①容器的大小可以通过width、height来设定也可以通过constraints来指定;如果它们同时存在时,widthheight优先。

      ②color和decoration是相互排斥的,如果同时存在会报错!

Container的使用,示例代码如下所示:

Container(
        margin: EdgeInsets.only(top: 100.0, left: 80.0), //容器外填充
        width: 200.0,
        height: 150.0,//容器大小
//        constraints: BoxConstraints.tightFor(width: 200.0, height: 150.0), //容器大小
        decoration: BoxDecoration(//背景装饰
            gradient: RadialGradient( //背景径向渐变
                colors: [Colors.red, Colors.green],
                center: Alignment.center,
                radius:0.7
            ),
        ),
        transform: Matrix4.rotationZ(0.2), //容器倾斜变换
        alignment: Alignment.center, //容器内文字居中
        child: Text( //卡片文字
          "1314", style: TextStyle(color: Colors.white, fontSize: 40.0),
        ),

      )

效果如下图所示:

Center(居中布局)

Center(居中布局)将其子widget居中显示在自身内部的widget,继承自Align。只能有一个chlid,可以使子元素处于水平和垂直方向的中间位置。

Center定义

Center({ 
  Key key, 
   double widthFactor, //宽度因子
   double heightFactor, //高度因子
   Widget child //
 })

Center的使用,示例代码如下所示:

Center(
         child: Text('Center',style: TextStyle(
            color: Colors.grey,fontSize: 40.0
         ),),
      )

效果如下图所示:

Padding(填充布局)

Padding即为填充组件,用于处理容器与其子元素之间的间距。与padding属性对应的是margin属性,margin是处理容器与其他组件之间的间距。

Padding定义

Padding({
    Key key,
    @required this.padding,//内边距
    Widget child,
  }) : assert(padding != null),
       super(key: key, child: child);

注:padding类型为EdgeInsetsGeometry,填充值可以使用EdgeInsets方法。例如:EdgeInsets.all(6.0)将容器上下左右填充设置为6.0。

EdgeInsets

①.fromLTRB(double left,double double,double right,double bottom) :分别制定四个方向的填充

②.all(double value):所有方向都设置为同一个值

③.only({left,top,right,bottom}):设置某一方向的距离(可以同时指定多个方向)

④.symmetric({vertical,horizontal}):设置对称方向的填充:vertical指top和bottom,horizontal指left和right

Padding的使用,示例代码如下所示:

Padding(
           padding: EdgeInsets.all(20),//设置全方向
           child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                 Padding(
                     padding: EdgeInsets.only(top: 20),
                     child: Text('上面20',style: TextStyle(
                         color: Colors.red,fontSize: 20
                     ),),
                 ),
                Padding(
                 // left, top, right, bottom
                  padding: EdgeInsets.fromLTRB(5,50,7,20),
                  child: Text('左5上50右7下20',style: TextStyle(
                     color: Colors.green,fontSize: 20
                  ),),
                ),
                Padding(
                  //左右各10
                  padding: EdgeInsets.symmetric(horizontal: 10),
                  child: Text('左右20',style: TextStyle(
                      color: Colors.blueGrey,fontSize: 20
                  ),),
                ),
              ],
           ),
      )

效果如下图所示:

Align(对齐布局)

Align组件即为对齐组件,可以将组件按指定方式对齐,也可以根据组件的大小调整自己的大小。

Align定义

Align({
    Key key,
    this.alignment = Alignment.center,
    this.widthFactor,//宽度
    this.heightFactor,//高度
    Widget child,
  })

  各参数含义:

 1.alignment:对齐方式,一般会使用系统默认提供的9种方式:

①bottomCenter(0.5,1.0) 底部中心

②bottomLeft(0.0,1.0) 左下角

③bottomRight(1.0,1.0) 右下角

④center(0.5,0.5) 水平垂直中心

⑤centerLeft(0.0,0.5) 左边缘中心

⑥centerRight(0.0,1.0) 右边缘中心

⑦topCenter(0.5,0.0)顶部中心

⑧topLeft(0.0,0.0) 左上角

⑨topRight(1.5,0.0) 右上角

Alignment实际上是包含了两个属性的,其中第一个参数,-1.0是左边对齐,1.0是右边对齐,第二个参数,-1.0是顶部对齐,1.0是底部对齐。根据这个规则,我们也可以自定义我们需要的对齐方式

2.widthFactor:宽度因子,如果设置的话,Align的宽度就是child的宽度乘以这个值,不能为负数。

3.heightFactor:高度因子,如果设置的话,Align的高度就是child的高度乘以这个值,不能为负数。

Align的使用,示例代码如下所示:

 children: <Widget>[
            Align(
               alignment: Alignment.center,
               child: Text('中间'),
            ),
           Align(
             alignment: Alignment.topLeft,
             child: Text('左上角'),
           ),
           Align(
             alignment: Alignment.topCenter,
             child: Text('顶部中心'),
           ),
           Align(
             alignment: Alignment.topRight,
             child: Text('右上角'),
           ),
           Align(
             alignment: Alignment.bottomLeft,
             child: Text('左下角'),
           ),
           Align(
             alignment: Alignment.bottomCenter,
             child: Text('底部中心'),
           ),
           Align(
             alignment: Alignment.bottomRight,
             child: Text('右下角'),
           ),
           Align(
             alignment: Alignment.centerLeft,
             child: Text('左边缘中心'),
           ),
           Align(
             alignment: Alignment.centerRight,
             child: Text('右边缘中心'),
           ),
         ],

效果如下图所示:

Column(垂直布局)

Column(垂直布局)是一种常用的布局方式,继承自Flex,是在垂直方向排列其子组件。对Column来说,垂直方向是主轴,水平方向是次轴。

Column定义

Column({
    Key key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    MainAxisSize mainAxisSize = MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
    TextDirection textDirection,
    VerticalDirection verticalDirection = VerticalDirection.down,
    TextBaseline textBaseline,
    List<Widget> children = const <Widget>[],
  })

各参数含义:

1.MainAxisAlignment:主轴的排列方式。

①MainAxisAlignment.start 默认值,靠上

②MainAxisAlignment.center居中

③.MainAxisAlignment.end靠下

④MainAxisAlignment.spaceAround自己填充,等待分配空间给子集,子集各自居中对齐

⑤MainAxisAlignment.spaceBetween自己填充,等待分配空间给子集,子集两侧对齐

⑥MainAxisAlignment.spaceEvenly自己填充,等待分配空间给子集,子集同一中线居中对齐

2.CrossAxisAlignment:次轴的排列方式

①CrossAxisAlignment.strech  会使子控件宽度调到最大

②CrossAxisAlignment.start     会使子控件向左对齐

③CrossAxisAlignment.center   默认值,子控件居中

④CrossAxisAlignment.end     会使子控件向右对齐

⑤CrossAxisAlignment.baseline  按文本水平线对齐,与TextBaseline搭配使用

3.MainAxisSize:主轴占据的空间。取值max为最大,min最小

①MainAxisSize.min 默认值,自适应children

②MainAxisSize.max 填充父控件竖屏,需要搭配MainAxisAlignment使用才有效果

4.VerticalDirection

①VerticalDirection.down   默认值,按照默认方式

②VerticalDirection.up   CrossAxisAlignment.start和CrossAxisAlignment.end相反

5.TextBaseline

①TextBaseline.alphabetic    用于对齐字母字符底部的水平线

②TextBaseline.ideographic   用于对齐表意字符的水平线

Column的使用,示例代码如下所示:

Column(
           mainAxisAlignment: MainAxisAlignment.spaceAround,
           crossAxisAlignment: CrossAxisAlignment.start,
           textDirection: TextDirection.rtl,
           children: <Widget>[
             Text('垂直布局一',style: TextStyle(
                 fontSize: 12
             ),),
             Text('垂直布局二',style: TextStyle(
                 fontSize: 15
             ),),
             Text('垂直布局三',style: TextStyle(
                 fontSize: 20
             ),),
           ],
         ),

效果如下图所示:

Row(水平布局)

Row(水平布局)是一种常用的布局方式,使用Row组件来完成子组件在水平方向的排列。在Row组件中,水平方向是主轴,垂直方向是次轴。Row的属性和Column的属性是一样的,我们这就不细说了,直接上例子了。

Row的使用,示例代码如下所示:

Row(
           mainAxisAlignment: MainAxisAlignment.spaceAround,
           crossAxisAlignment: CrossAxisAlignment.start,
           textDirection: TextDirection.ltr,
           children: <Widget>[
             Text('水平布局一',style: TextStyle(
                 fontSize: 12
             ),),
             Text('水平布局二',style: TextStyle(
                 fontSize: 15
             ),),
             Text('水平布局三',style: TextStyle(
                 fontSize: 20
             ),),
           ],
         ),

效果如下图所示:

Expanded(配合Column,Row使用)

Expanded组件可以使Row、Column、Flex等子组件在其主轴上方向展开并填充可用的空间。

注:Expanded组件必须用在Row、Column、Flex内。

Expanded的定义

Expanded({
    Key key,
    int flex = 1,
    @required Widget child,
  }) 

注:在Row中使用Expanded的时候,无法指定Expanded中的子组件的宽度width,但可以指定其高度height。同理,在Column中使用Expanded的时候,无法指定Expanded中的子组件的高度height,可以指定宽度width。

Expanded的使用,示例代码如下所示:

Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Expanded(flex: 2, child: IconContainer(Icons.radio)),
              SizedBox(width: 10),
              Expanded(flex: 3, child: IconContainer(Icons.hotel)),
            ],
          )

效果如下图所示:

FittedBox(缩放布局)

FittedBox组件主要做两件事,缩放(Scale)和位置调整(Position)

FittedBox的定义

FittedBox({
    Key key,
    this.fit = BoxFit.contain,
    this.alignment = Alignment.center,
    Widget child,
  })

FittedBox中有fit和alignment两个重要属性。

fit:缩放的方式,默认的属性是BoxFit.contain,child在FittedBox范围内,尽可能大,但是不会超出其尺寸。Fit的各属性:

①.BoxFit.none 没有任何填充模式

②.BoxFit.fill 不按宽高比填充模式,内容不会超出容器范围。

③.BoxFit.contain 按宽高比填充模式,内容不会超出容器范围。

④.BoxFit.cover 按原始尺寸填充整个容器模式,内容有可能会超出容器范围。

⑤.BoxFit.fitWidth及BoxFit.fitHeight分别是按宽/高填充整个容器的模式,内容不会超过容器范围。

⑥.BoxFit.scaleDown会根据情况缩小范围,有时和BoxFit.contain一样,有时和BoxFit.none一样,内容不会超过容器范围。

alignment:设置对齐方式,默认的属性是Alignment.center,居中显示child。

FittedBox的使用,示例代码如下所示:

FittedBox(
             fit: BoxFit.contain,
             alignment: Alignment.topCenter,
             child: Text('缩放布局',style: TextStyle(
                color: Colors.red,fontSize: 13.0
             ),),
          )

效果如小图所示:

①.BoxFit.contain

②.BoxFit.fill

③.BoxFit.cover

④.BoxFit.fitWidth

⑤.BoxFit.fitHeight

⑥.BoxFit.scaleDown

Stack、Positioned(堆叠布局)

Stack组件的每一个子组件要么定位,要么不定位,定位的子组件是用Positioned组件包裹的。Stack组件本身包含所有不定位的子组件,子组件根据alignment属性定位(默认为左上角)。

Stack的定义

Stack({
    Key key,
    this.alignment = AlignmentDirectional.topStart,
    this.textDirection,
    this.fit = StackFit.loose,
    this.overflow = Overflow.clip,
    List<Widget> children = const <Widget>[],
  })

alignment:对齐方式,默认是左上角(topStart)。

textDirection:文本的方向,绝大部分不需要处理。

fit:用于没有定位的子组件去适应Stack的大小。StackFit.loose表示使用子组件的大小,StackFit.expand表示括伸到Stack的大小

overflow:显示超出Stack显示空间的子组件;值为Overflow.clip时,超出部分会被裁剪(隐藏),值为Overflow.visible时则不会

Positioned组件是用来定位的,根据Stack的四个角来确定子组件的位置。

Positioned的定义

Positioned({
    Key key,
    this.left,
    this.top,
    this.right,
    this.bottom,
    this.width,
    this.height,
    @required Widget child,
  })

left、top、right、bottom分别代表离Stack左、上、右、下四边的距离。width和height用于指定需要定位元素的宽度和高度。

注:Positioned的width、height用于配合left、top、right、bottom来定位组件。例如,在水平方向时,你只能指定left、right、width三个属性中的两个,指定了left和width后,right会自动算出(left+width),如果同时指定三个属性的话会报错,垂直方向也是这样。

Stack、Positioned的使用,示例代码如下:

Stack(
            alignment: Alignment.center, //指定未定位或部分定位widget的对齐方式
            children: <Widget>[
              Container(
                child: Icon(Icons.hotel),
              ),
              Positioned(
                left: 20.0,
                child: Icon(Icons.home),
              ),
              Positioned(
                top: 20.0,
                child: Icon(Icons.search,color: Colors.red,),
              )
            ],
          )

效果如下图所示:

OverflowBox(溢出父视图容器)

OverflowBox组件由其minWidth、minHeight、maxWidth、maxHeight四个属性给子组件划定了一个矩形的范围。子组件不能超出OverflowBox组件范围,但是可以溢出父组件范围显示。

OverflowBox定义

OverflowBox({
    Key key,
    this.alignment = Alignment.center,
    this.minWidth,
    this.maxWidth,
    this.minHeight,
    this.maxHeight,
    Widget child,
  })

属性含义:

alignment:对齐方式。

minWidth:允许child的最小宽度。如果child宽度小于这个值,则按照最小宽度进行显示。

maxWidth:允许child的最大宽度。如果child宽度大于这个值,则按照最大宽度进行展示。

minHeight:允许child的最小高度。如果child高度小于这个值,则按照最小高度进行显示。

maxHeight:允许child的最大高度。如果child高度大于这个值,则按照最大高度进行展示。

其中,最小以及最大宽高度,如果为null的时候,就取父节点的constraint代替。

OverflowBox的使用,示例代码如下:

Container(
          color: Colors.red,
          width: 100.0,
          height: 100.0,
          padding: EdgeInsets.all(50.0),
          child: OverflowBox(
            alignment: Alignment.topLeft,
            maxWidth: 350.0,
            maxHeight: 350.0,
            child: Container(
              color: Colors.blue,
              width: 200.0,
              height: 200.0,
            ),
          ),
        )

效果如下图所示:

到这里关于页面布局的讲解就结束,希望大家多多支持。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值