Flutter开发之Flex、FittedBox、Stack、Container布局教程

2019-09-1410:32:37APP与小程序开发Comments4,999 views字数 13315阅读模式

布局

Flex布局

Flutter中的Flex布局和Web的CSS中的Flex布局类似。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

在Flutter 中用于控制Flex布局的有Row,Column,Expanded,Flexible,Spacer,Flex这些控件。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

row水平布局

Flutter开发之Flex、FittedBox、Stack、Container布局教程
属性名类型默认值说明
mainAxisAlignmentMainAxisAlignmentMainAxisAlignment.start主轴的排列方式
mainAxisSizeMainAxisSizeMainAxisSize.max主轴占空间的大小
crossAxisAlignmentCrossAxisAlignmentCrossAxisAlignment.center次轴的排列方式
textDirectionTextDirectionnull确定children在水平方向的摆放顺序
verticalDirectionVerticalDirectionVerticalDirection.down确定children在垂直方向的摆放顺序
textBaselineTextBaselinenull文字基准线对齐

我们首先创建三个大小不一的Container文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html


class LyoutRowDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("水平布局"),
        ),
        body: Container(
          child: Row(
            children: <Widget>[
              Container(
                height: 100,
                width: 50,
                color: Colors.redAccent,
              ),
              Container(
                height: 50,
                width: 50,
                color: Colors.blueAccent,
              ),
              Container(
                color: Colors.black,
                height: 75,
                width: 75,
              )
            ],
          ),
        ));
  }
}
复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程
主轴排列方式MainAxisAlignment

子元素children的排列方式由这两个属性决定textDirection和verticalDirection。textDirection决定水平方向的排列方式TextDirection.ltr从左往右排列(把左当作起始位置),TextDirection.rtl从右往左排列(把右当作起始位置)。verticalDirection时水平方向的排列方式。当值为down(向下排列)时起始位置在顶部。当值为up(向上排列)是起始位置在底部。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

  • start (默认值) 根据textDirection属性排列方向。将children放置在主轴的起点

    textDirection属性值为rtl时右图

Flutter开发之Flex、FittedBox、Stack、Container布局教程
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • end根据textDirection属性排列方向。

    将children放置在主轴的末尾文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

    textDirection属性值为rtl时右图

Flutter开发之Flex、FittedBox、Stack、Container布局教程
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • center根据textDirection属性排列方向。

    将children放置在主轴的中心文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

    textDirection属性值为rtl时右图

Flutter开发之Flex、FittedBox、Stack、Container布局教程
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • spaceBetween根据textDirection属性排列方向。

    将主轴方向上的空白区域均分,使得children之间的空白区域相等,首尾child都靠近首尾,没有间隙文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

    textDirection属性值为rtl时右图

Flutter开发之Flex、FittedBox、Stack、Container布局教程
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • spaceAround根据textDirection属性排列方向。

    将主轴方向上的空白区域均分,使得children之间的空白区域相等,但是首尾空白区域为一半文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

    textDirection属性值为rtl时右图

Flutter开发之Flex、FittedBox、Stack、Container布局教程
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • spaceEvenly根据textDirection属性排列方向

    将主轴方向上的空白区域均分,使得children之间的空白区域相等,包括首尾空白区域文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

    textDirection属性值为rtl时右图

Flutter开发之Flex、FittedBox、Stack、Container布局教程
Flutter开发之Flex、FittedBox、Stack、Container布局教程
交叉轴的排列方式crossAxisAlignment

都以 mainAxisAlignment: MainAxisAlignment.start为例文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

  • start将子元素在交叉轴上起点对齐。设置verticalDirection为VerticalDirection.up右图。
Flutter开发之Flex、FittedBox、Stack、Container布局教程
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • end将子元素在交叉轴上末尾对齐。设置verticalDirection为VerticalDirection.up右图。
Flutter开发之Flex、FittedBox、Stack、Container布局教程
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • center将子元素在交叉轴上居中对齐。设置verticalDirection无改变。
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • strentch将子元素在交叉轴上拉伸
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • baseline基准线对其适用于文字,我们首先创建文字的start。使用baseline。必须设置textBaseline属性。不同文字的文字基准线。主要是字母文字(如:英语)和表意文字(如:汉语)的基准线是不同的。必须告诉Flutter你使用的文字。
    Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      textBaseline: TextBaseline.alphabetic,
      children: [
        Text(
          'Flutter',
          style: TextStyle(
            color: Colors.yellow,
            fontSize: 30.0
          ),
        ),
        Text(
          'Flutter',
          style: TextStyle(
              color: Colors.blue,
              fontSize: 20.0
          ),
        ),
      ],
    );
    复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程

设置对齐方式为基准线文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Flutter开发之Flex、FittedBox、Stack、Container布局教程
主轴占用的空间mainAxisSize

mainAxisSize只有两个值一个是min一个是max。默认是max。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

当值为min时候。主轴缩紧,变为最小。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

如图:即使这时mainAxisAlignment:为MainAxisAlignment.spaceAround。主轴的长度仍为最小状态文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Flutter开发之Flex、FittedBox、Stack、Container布局教程

Column垂直布局

垂直布局与水平布局的属性和方法一致,唯一需要注意的是textDirection(水平排列方式)和verticalDirection(垂直排列方式)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: "垂直布局",
        home: Scaffold(
            appBar: AppBar(title: Text("垂直布局")),
            body: Center(
              child: Column(
			   mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.end,
                children: <Widget>[
                  Text("1",style: TextStyle(fontSize: 100),),
                  Expanded(
                    child: Text("2"),
                  ),
                  Text("33333"),
                  Text("4")
                ],
              ),
            )));
  }
}

复制代码

为了便于观看我们将1扩大文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Flutter开发之Flex、FittedBox、Stack、Container布局教程

Flex布局

我们查看以下源码便于理解文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

可以看到RowColumn都继承与Flex文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

class Row extends Flex 
class Column extends Flex   
复制代码

Row的构造函数可选命名参数(即{}包裹的参数)有8个。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

传入父级的super构造函数却有9个,多出了direction: Axis.horizontal文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Row({
    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>[],
  }) : super(
    children: children,
    key: key,
    direction: Axis.horizontal,
    mainAxisAlignment: mainAxisAlignment,
    mainAxisSize: mainAxisSize,
    crossAxisAlignment: crossAxisAlignment,
    textDirection: textDirection,
    verticalDirection: verticalDirection,
    textBaseline: textBaseline,
  );
}
复制代码

再Flex中属性direction实际上时主轴的方向。且被@required标注。它是必选的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Flex({
    Key key,
    @required this.direction,
    this.mainAxisAlignment = MainAxisAlignment.start,
    this.mainAxisSize = MainAxisSize.max,
    this.crossAxisAlignment = CrossAxisAlignment.center,
    this.textDirection,
    this.verticalDirection = VerticalDirection.down,
    this.textBaseline,
    List<Widget> children = const <Widget>[],
  }) : assert(direction != null),
       assert(mainAxisAlignment != null),
       assert(mainAxisSize != null),
       assert(crossAxisAlignment != null),
       assert(verticalDirection != null),
       assert(crossAxisAlignment != CrossAxisAlignment.baseline || textBaseline != null),
       super(key: key, children: children);
复制代码

Expanded

上面的例子我们遇到从未见过的一个widget。很容易就可以看出。Expanded会忽略子元素的大小并强制自动扩展使主轴填充父级可用的空白区域。Expanded必须是Row、Column、Flex的children。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

下面两个例子便于更好理解:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

//当子元素只有一个Expanded时
class LyoutExpanded extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Expanded"),
      ),
      body: Center(
        child: Container(
          child: Column(
            children: <Widget>[
              Expanded(
                child: Container(
                  color: Colors.blue,
                  width: 100,//这个被忽略掉了
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程
class LyoutExpanded extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Expanded"),
      ),
      body: Center(
        child: Container(
          height: 50,//填充使主轴扩展至父级高度
          child: Column(
            children: <Widget>[
           Expanded(
                child: Container(
                  color: Colors.blue,
                  height: 100,//
                  width: 100,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程

Expanden还有一个属性为flex默认值为1。代表权重。当子元素有多个Expanden。按照权重值占据父级的高度(row时为水平宽度)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

<Widget>[
    Expanded(
        flex: 2,
        child: Container(
            color: Colors.blue,
            width: 100,
        ),
    ),
    Expanded(
        child: Container(
            color: Colors.red,
            width: 100,
        ),
    ),
    Expanded(
        child: Container(
            color: Colors.yellow,
            width: 100,
        ),
    ),
],
复制代码

我们可以看到蓝色的块时红和黄的二倍。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Flutter开发之Flex、FittedBox、Stack、Container布局教程

Flexible

Flexible组件可以使Row、Column、Flex等子组件在主轴方向有填充可用空间的能力(例如,Row在水平方向,Column在垂直方向),但是它与Expanded组件不同,它不强制子组件填充可用空间。同样Flexible组件必须是Row、Column、Flex等组件的children。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Flexiible 有属性fit当属性值FlexFit.tight时。Flexible和Expanded没有区别。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

从源码可以看出Expanded继承与Flexible文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

且引用 上级构造函数传入fit的值为FlexFit.tight。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

class Expanded extends Flexible
//省区其他源码
    

const Expanded({
    Key key,
    int flex = 1,
    @required Widget child,
  }) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);
}
    
复制代码

在Column的children中传入。属性fit:为FlexFit.tight,按照权值填充空白区域。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

<Widget>[
    Flexible(
        fit: FlexFit.tight,
        child: Container(
            color: Colors.blue,
            height: 100,
            width: 100,
        ),
    ),
    Flexible(
        fit: FlexFit.tight,
        flex: 2,
        child: Container(
            color: Colors.yellow,
            height: 100,
            width: 100,
        ),
    ),
],
复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程

一旦fit的值为FlexFit.loose(默认值)先按flex的值分主轴确定占主轴的大小,再按child调整元素的高度。不强制拉伸文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

例如第一个为tight强制扩展。第二个为loose不强制扩展。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

<Widget>[
    Flexible(
        fit: FlexFit.tight,
        child: Container(
            color: Colors.blue,
            height: 100,
            width: 100,
        ),
    ),
    Flexible(
        fit: FlexFit.loose,
        flex: 2,
        child: Container(
            color: Colors.yellow,
            height: 100,
            width: 100,
        ),
    ),
],
复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程

因为第二个为loose所以黄颜色的Container高度为100。而蓝色Container的 fit值为 tight,他的大小和上一个例子一致。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Spacer

Spacer创建一个可以调整的空白区域,可用于调整Flex容器(Row或者Colum)中widget之间的间距。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

一旦children里面包含了Spacer。mainAxisAlignment的属性值将起不到作用。Spacer已经占据了所有额外的空间,因此没有剩余的空间可以重新分配。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Row(
    mainAxisAlignment: MainAxisAlignment.end,//起不到作用
    children: <Widget>[
        Container(
            height: 100,
            width: 50,
            color: Colors.redAccent,
        ),
        Spacer(),
        Container(
            height: 50,
            width: 50,
            color: Colors.blueAccent,
        ),
        Container(
            color: Colors.black,
            height: 75,
            width: 75,
        )
    ],
),
复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程

缩放布局

绝大多数flutter的widget是盒子。可以将他们叠放,堆叠,嵌套。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

我们可以层级嵌套盒子,但是如果一个盒子不适合(大小不适合)另一个盒子。该如何解决?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Flutter开发之Flex、FittedBox、Stack、Container布局教程

为了解决这个问题Flutter提供了FittedBox,这个和移动端的ImageView类似。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

它实现的功能是使子元素缩放(fit)或者调整位置(alignment)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

  • BoxFit.contain(默认值)等比例扩大或缩小,但内容不会超过容器范围
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • BoxFit.cover按照比例逐步扩大至充满容器,内容有能会超过容器范围。当child比例与容器不同时,要么高度溢出容器,要么宽度溢出容器。
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • BoxFit.fill不保留比例强制拉伸(缩小)填充容器。
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • BoxFit.fitHeight保持比例确保高度在容器中显示完整。
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • BoxFit.fitWidth保持比例确保宽度在容器中显示完整。
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • BoxFit.none将child对齐在目标框内(默认剧中),并丢弃位于框外的部分,源文件不放大也不缩小。
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  • BoxFit.scaleDown将child对齐在目标框内(默认剧中),当child大于容器,则与contain一致。如果child小于容器,则与none一致
Flutter开发之Flex、FittedBox、Stack、Container布局教程

为了便于理解我们可以找一个图片进行测试文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

class Lyoutfitdemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("data")),
      body: Container(
        height: 250,
        width: 250,
        color: Colors.indigo[200],
        child: FittedBox(
          child: Image.asset('images/fittedbox.png')),
      ),
    );
  }
}
复制代码
  1. BoxFit.contain
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  1. BoxFit.cover
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  1. BoxFit.fill
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  1. BoxFit.fitHeight
Flutter开发之Flex、FittedBox、Stack、Container布局教程

5.BoxFit.fitWidth文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Flutter开发之Flex、FittedBox、Stack、Container布局教程
  1. BoxFit.none
Flutter开发之Flex、FittedBox、Stack、Container布局教程
  1. BoxFit.scaleDown
Flutter开发之Flex、FittedBox、Stack、Container布局教程
Flutter开发之Flex、FittedBox、Stack、Container布局教程

备注:不用创建FittedBox,Image含有属性fit。值效果和FittedBox一致。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

堆叠布局

Stack与web绝对定位布局模型类似。Stack不是按行或者列来布局的,而是按照特定顺序和位置堆叠。可以使用 PositionedAlign作为Stack的的定位。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

示例:使用层叠布局实现一个 图片渐变效果文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "渐变状态栏",
      home: Scaffold(
        body: Container(
          height: 400,
          child: Stack(
            fit: StackFit.expand,
            children: <Widget>[
              Image.asset(
                'images/Stack.png',
                fit: BoxFit.cover,
              ),
          
              const DecoratedBox(
                decoration: BoxDecoration(
                  gradient: LinearGradient(
                    begin: Alignment(0.0, -1.0),
                    end: Alignment(0.0, -0.4),
                    colors: <Color>[Color(0x90000000), Color(0x00000000)],
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
复制代码

图片渐变效果文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Flutter开发之Flex、FittedBox、Stack、Container布局教程
Flutter开发之Flex、FittedBox、Stack、Container布局教程

这是两个控件堆叠在一起的例子。当然子部件可以出现在父级内的任何位置。通过两种widget实现对位置的控制。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Align布局

Align为对齐部件,设置child的在父级的(如container、stack等)对齐方式,并根据child的尺寸调整自身的尺寸。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

本文的父级容器选用stack文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Alignment

其中有这几种属性文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

topLeft(左上),topCenter(顶部中央),topRight(右上),centerLeft,center,centerRight,bottomLeft,bottomCenter,bottomRight文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

class LayoutAlignDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("align部件"),
        ),
        body: Stack(
          children: <Widget>[
            Align(
              alignment: Alignment.topLeft,
              child: Container(
                width: 100,
                height: 100,
                color: Colors.red,
              ),
            ),
          ],
        ));
  }
}
复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程
Alignment.lerp(Alignment a, Alignment b, double t)

lerp方法有三个参数,前两个参数为Alignment类型,第三个参数为小数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

当t为0时,这个方法返回的值为a。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

当t为1时,返回b的值。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

当t为0.5时,这个widget位置就位于a和b指定的位置中间。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

所以这个t为一个偏移量。指定为a到b之间的偏移。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

//在Stack children中添加一个align
Align(
  alignment: Alignment.lerp(Alignment.bottomCenter, Alignment.center,0.5),//位于Alignment.bottomCenter和Alignment.center的中央
  child: Container(
  width: 100,
  height: 100,
  color: Colors.yellow,
   ),
),
复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程
偏移量对齐

上面介绍了相对于对其方式a和b的偏移对其。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

FractionalOffset 是另外一个偏移方法,它是相对于父部件左上角的偏移。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

创建偏移量FractionalOffset (dx,dy)。dx和dy的取值都是0~1。左上的位置为dx和dy都为0。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Align(
  alignment: FractionalOffset(0, 0.5),
  child: Container(
    width: 100,
    height: 100,
    color: Colors.red,
  ),
),
复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程

另外在源码中:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

class FractionalOffset extends Alignment
复制代码

FractionalOffset继承于Alignment所以Alignment的属性都可以使用,这样我们要使得widget位于左上也可以用使用FractionalOffset.topLeft文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html


class LayoutAlignDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("align部件"),
        ),
        body: Stack(
          children: <Widget>[
            Align(
              alignment: FractionalOffset(0, 0),
              child: Container(
                width: 100,
                height: 100,
                color: Colors.red,
              ),
            ),
            Align(
              alignment: FractionalOffset(0, 0.5),
              child: Container(
                width: 100,
                height: 100,
                color: Colors.red,
              ),
            ),
            Align(
              alignment: FractionalOffset(0, 1),
              child: Container(
                width: 100,
                height: 100,
                color: Colors.red,
              ),
            ),
            Align(
              alignment: Alignment.lerp(Alignment.bottomCenter, Alignment.center,0.5),
              child: Container(
                width: 100,
                height: 100,
                color: Colors.yellow,
              ),
            ),
            Align(
              alignment: FractionalOffset.topRight,
              child: Container(
                width: 100,
                height: 100,
                color: Colors.yellow,
              ),
            ),
          ],
        ));
  }
}

复制代码

与之相类似的还有Alignment(dx, dy),以父级容器的中心为坐标系原点。dx的取值范围为-1~1,dy的取值范围为-1~1。设置子元素的位置。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Positioned

Positioned 部件可以控制Stack中子元素的位置。Positioned 与Align不同的是Position必须是Stack的Children。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Position有topbottomleftrightheightwidth文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

topbottomleftright这些量都是子元素边界与父级某一边界的距离。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

也就是说当一个高度和长度固定容器,一旦我们确定left或right的一个量和bottom或top的一个量,其位置就可以确定。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

部分代码文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Stack(
    children: <Widget>[
        Positioned(
            top: 100,
            right: 100,
            width: 100,
            height: 100,
            child: Container(
                color: Colors.red,
            ),
        ),
    ],
)
复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程

源码分析文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

 const Positioned({
    Key key,
    this.left,
    this.top,
    this.right,
    this.bottom,
    this.width,
    this.height,
    @required Widget child,
  }) : assert(left == null || right == null || width == null),
       assert(top == null || bottom == null || height == null),
       super(key: key, child: child);
复制代码

在水平方向上如果assert(false)会抛出错误文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

而括号里的值为left == null || right == null || width == null文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

left ,right ,width 至少有一个值为null这个程序才不会报错。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

也就是说当width未指定(为空)使left和right是可以同时存在的。这时的容器的宽度会以据边界的距离(left和right)自动调整。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Stack(
    children: <Widget>[
        Positioned(
            top: 100,
            right: 100,
            left: 100,
            // width: 100,
            height: 100,
            child: Container(
                color: Colors.red,
            ),
        ),
    ],
)
复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程

IndexedStack

IndexedStack继承于Stack文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

class IndexedStack extends Stack
复制代码

他和Stack不同的是有一个index的属性,表示只显示第几个元素。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

IndexedStack(
    index: 1,//只显示第二个
    children: <Widget>[
        Positioned(
            top: 100,
            right: 100,
            left: 100,
            height: 100,
            child: Container(
                color: Colors.red,
            ),
        ),  
        Positioned(
            top: 500,
            right: 100,
            left: 100,
            height: 100,
            child: Container(
                color: Colors.red,
            ),
        ),
    ],
)
复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程

容器布局

Container可以创建一个矩形元素。可以用BoxDecoration进行装饰。背景,边框,阴影。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

class LyoutContainerdemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Container容器"),
      ),
      body: Container(
        height: 200,
        width: 200,
        child: Text("这是一个Container容器"),
        decoration: BoxDecoration(
          color: Colors.red[200],
          // shape: BoxShape.circle, //形状
          border: Border.all(width: 10.0),
          boxShadow: [
            BoxShadow(
              offset: Offset(0.0, 100.0), //模糊偏移量
              color: Color.fromRGBO(16, 20, 188, 1.0), //颜色
              blurRadius: 10, //模糊
              spreadRadius: -9.0, //在应用模糊之前阴影的膨胀量
            ),
          ],
        ),
      ),
    );
  }
}

复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程

为了演示功能,这个图片效果做的比较夸张。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

附上一个好看的效果文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Flutter开发之Flex、FittedBox、Stack、Container布局教程" data-data-original="https://user-gold-cdn.xitu.io/2019/9/10/16d1a3823ed8bd00?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" src="https://www.cainiaoxueyuan.com/wp-content/themes/begin/img/loading.png"height="20" data-width="338" data-height="717" />

相似于Css的盒子布局,我们也可以通过Margin给盒子设置外边距。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

Container(
    margin: EdgeInsets.all(50.0),//外边距50.0
    height: 200,
    width: 200,
    decoration: BoxDecoration(
        color: Colors.red[600],
        border: Border.all(width: 2.0),
        boxShadow: [
            BoxShadow(
                offset: Offset(2.0, 9.0), //偏移量
                color: Colors.red[200], //颜色
                blurRadius: 10, //模糊
                spreadRadius: -1.0, //在应用模糊之前阴影的膨胀量
            ),
        ],
    ),
),
复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程

Padding布局

用于处理容器与子元素之间的距离。与Padding对应的是margin属性。margin用于处理与其他组件之间的距离。Padding部件和容器内的pading属性的效果实际上是一致的,当同时出现,真实的padding将是两者相加。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

class LayoutPaddingDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Padding 布局"),
      ),
      body: Container(
        padding: EdgeInsets.all(20.0),//#1这两处的属性效果是一致的
        decoration: BoxDecoration(
            color: Colors.yellow,
            border: Border.all(color: Colors.white, width: 8.0)),//白色边框
        child: Padding(
          child: Container(
            decoration: BoxDecoration(
            color: Colors.red,
            border: Border.all(color: Colors.white, width: 8.0)),//白色边框
          ),
          padding: EdgeInsets.all(10.0),//#1这两处的属性效果是一致的
        ),
      ),
    );
  }
}

复制代码
Flutter开发之Flex、FittedBox、Stack、Container布局教程

写在后面

Flutter中涉及到布局的Widget有30多种,一样的效果的ui,实现的途径有很多中。本篇就重点涉及几个常用的部件。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

作者:李鑫鑫
链接:https://juejin.im/post/5d77565de51d45620771f156
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html

文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/16437.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/xcx/16437.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定