美文网首页
Flutter基础控件篇[2]--布局

Flutter基础控件篇[2]--布局

作者: _会飞的鱼 | 来源:发表于2023-08-07 10:20 被阅读0次

Container容器控件,可以添加一个子控件,设置宽度高度,padding,margin,背景色、背景图、圆角、阴影 等属性,基本包含了容器控件的常用基本属性。
有些widget 自带padding属性,所以不必多套一层Padding部件。(比如ListView、GridView、Container、ScrollView、Button )
基本使用:

Widget build(BuildContext context) {
    return MaterialApp(
      home: Container(
          width: 200.0,
          height: 150.0,
          margin: const EdgeInsets.fromLTRB(25, 15, 0, 0),
          padding: const EdgeInsets.fromLTRB(10, 15, 10, 15),
          alignment: const Alignment(0, 0),
          decoration: const BoxDecoration(boxShadow: [
            //卡片阴影
            BoxShadow(
                color: Colors.black54,
                offset: Offset(5.0, 5.0),
                blurRadius: 7.0)
          ]),
          child: Image.network(
            "https://gips3.baidu.com/it/u=2498623727,1870741620&fm=3030&app=3030&f=JPEG?w=200&h=133&s=F31330C442402557123E451103005099",
            width: 200.0,
            height: 150.0,
          )),
    );
  }

常用属性:
width:宽度,如果设置具体值则为具体值,不设置则包裹子控件大小,设置为double.infinity一般会充满父控件或者充满屏幕(如果没有其他特别的约束条件);
height:高度,使用方法基本同width;
margin:设置控件与其他控件的外边距;
padding:设置内边距;
decoration:背景装饰;
alignment:设置子控件的方位,用Alignment属性值来表示,具体对应的方位如下:

Alignment topLeft = Alignment(-1.0, -1.0);
Alignment topCenter = Alignment(0.0, -1.0);
Alignment topRight = Alignment(1.0, -1.0);
Alignment centerLeft = Alignment(-1.0, 0.0);
Alignment center = Alignment(0.0, 0.0);
Alignment centerRight = Alignment(1.0, 0.0);
Alignment bottomLeft = Alignment(-1.0, 1.0);
Alignment bottomCenter = Alignment(0.0, 1.0);
Alignment bottomRight = Alignment(1.0, 1.0);

Column(纵向布局) and Row(横向布局)

Column(纵向布局)

类似iOS中的 tableview


WX20230808-094637.png
 Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("学习demo"),
      ),
      body: const Column(
        mainAxisAlignment:  MainAxisAlignment.start, //主轴方向上控件排列规则(居中 靠边 均匀分布等) 主轴是指竖直列表
          crossAxisAlignment: CrossAxisAlignment.start, //纵轴方向上控件排列规则(start左 center居中 end靠右边等)
          mainAxisSize: MainAxisSize.max, //主轴方向(纵向)占空间尽量大,(如果没有其他特别的约束条件则要么填满屏幕,要么填满父布局)
          verticalDirection:VerticalDirection.down, //控件顺序正常顺序,VerticalDirection.up则倒叙
          textBaseline: TextBaseline.alphabetic,
          children: <Widget>[
           Text('verticalDirection:VerticalDirection.up'),
           Text('crossAxisAlignment: CrossAxisAlignment.center'),
            Text('mainAxisAlignment: MainAxisAlignment.spaceEvenly'),
           Text('textBaseline: TextBaseline.ideographic'),
        ],
      ),
      //ZTListTitleView()
    );
  }

Row(横向布局)

和纵向布局属性差不多 要注意元素超出屏幕的控制


1.png
Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("学习demo"),
      ),
      body: Row(
        mainAxisSize:
            MainAxisSize.max, //主轴方向(横向)占空间尽量大,(如果没有其他特别的约束条件则要么填满屏幕,要么填满父布局)
        verticalDirection: VerticalDirection.down, //实测 up和down效果一样
        crossAxisAlignment: CrossAxisAlignment.center, //纵轴方向(纵向)上控件排列规则(居中 靠边等)
        mainAxisAlignment: MainAxisAlignment.spaceBetween, ////主轴方向上控件排列规则(居中 靠边 均匀分布等)
        textBaseline: TextBaseline.ideographic,
        textDirection: TextDirection.ltr, //从左到右排列
        children: <Widget>[
          Container(color: Colors.blue[100], width: 70, height: 70),
          Container(color: Colors.blue[200], width: 70, height: 70),
          Container(color: Colors.blue[300], width: 70, height: 70),
          Container(color: Colors.blue[400], width: 70, height: 70),
        ],
      ),
      //ZTListTitleView()
    );
  }

合并介绍

这里mainAxis和crossAxis代表主轴方向和纵轴方向,Row(横向布局)主轴方向就是横向,纵轴方向就是纵向;Column(纵向布局)主轴方向就是纵向,纵轴方向就是横向;
几个常用属性:
mainAxisSize:

  • MainAxisSize.max:主轴方向占空间尽量大,(如果没有其他特别的约束条件则要么填满屏幕,要么填满父布局);
  • MainAxisSize.min:主轴方向占空间尽量小,基本就是包裹子控件的尺寸了

textDirection

  • TextDirection.ltr,从左到右排列;
  • TextDirection.rtl,从右到左排列;

textBaseline

  • TextBaseline.alphabetic,使用按照排列字母字符的基准线排列方式
  • TextBaseline.ideographic,使用按照表意字字符的基准线排列方式(比如中文);

表意字好像是说可以拆解结构的文字类型,通过各种部首的组合可以形成各种文字,例如中文。(这里有一个视频,简单了解什么是表意字)

verticalDirection

  • VerticalDirection.up,从下向上排列;
  • VerticalDirection.down,从上向下排列;

mainAxisAlignment:

  • start:将children放置在主轴的起点;
  • center:将children放置在主轴的中心;
  • end:将children放置在主轴的末尾;
  • spaceAround:将主轴方向上的空白区域均分,使得children之间的空白区域相等,但是首尾child的空白区域为1/2;
  • spaceBetween:将主轴方向上的空白区域均分,使得children之间的空白区域相等,首尾child都靠近首尾,没有间隙;
  • spaceEvenly:将主轴方向上的空白区域均分,使得children之间的空白区域相等,包括首尾child;

crossAxisAlignment:

  • start:将children放置在纵轴的起点;
  • center:将children放置在纵轴的中心;
  • end:将children放置在纵轴的末尾;

Wrap 流式布局

Wrap包裹子控件,也可以设置横向和纵向,它与Row和Column的区别在于:Row和Column只有一行或一列,子控件尺寸超出了就会显示不全,但是Wrap会自动换行。


WX20230808-095424.png
Widget build(BuildContext context) {
    return Wrap(
      direction: Axis.horizontal,
      //start end值受textDirection具体值的影响
      alignment: WrapAlignment.start,
      runAlignment: WrapAlignment.center, //纵轴方向对齐方式
      spacing: 15, //主轴方向间距15
      runSpacing: 10, //纵轴方向间距10
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(
          color: Colors.green[100],
          width: 70,
          height: 70,
        ),
        Container(color: Colors.green[200], width: 70, height: 70),
        Container(color: Colors.green[300], width: 180, height: 70),
        Container(color: Colors.green[400], width: 70, height: 70),
        Container(
          color: Colors.green[100],
          width: 70,
          height: 70,
        ),
        Container(color: Colors.green[200], width: 70, height: 70),
        Container(color: Colors.green[300], width: 70, height: 70),
        Container(color: Colors.green[400], width: 70, height: 70),
      ],
    );
  }

常用属性:direction:排列方向
Axis.horizontal 横向布局(主轴为横向)
Axis.vertical 纵向布局(主轴为纵向)
alignment:使用WrapAlignment的属性值,但是含义和Row、Column基本一致;
spacing:主轴方向子控件间距;
runSpacing:纵轴方向的间距(主轴是横向则纵轴是纵向,主轴是纵向则纵轴是横向);
runAlignment:纵轴方向的对齐方式;

注意 :crossAxisAlignment和runAlignment都表示纵轴方式的对齐方式,实测的结果似乎crossAxisAlignment并没有起作用,只有runAlignment起作用了

Stack 重叠布局

可以把子控件叠在一起来展示。Stack可以搭配Positioned控件一起使用,Positioned控件可以控制子控件在Stack中的具体位置(设置距离左上右下的具体参数)和控件大小(设置宽高),使用场景会非常多

Widget build(BuildContext context) {
    return Stack(
      fit: StackFit.loose,
      alignment: AlignmentDirectional.center,
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(
          width: 120,
          height: 120,
          color: Colors.cyan[200],
        ),
        Container(
          width: 90,
          height: 90,
          color: Colors.cyan[400],
        ),
        Container(
          width: 60,
          height: 60,
          color: Colors.cyan[600],
        ),
        Positioned(
          left: 100,
          top: 100,
          child: Container(
            width: 220,
            height: 220,
            color: Colors.cyan[800],
          ),
        ) //指定位置,超出stack范围,测试overflow属性
      ],
    );
  }

常用属性:
alignment:设置子控件的方位,用AlignmentDirectional的值来表示,这个类里面的start和end受textDirection具体值的影响,TextDirection.ltr(左到右)对应start为左边,,TextDirection.rtl(右到左)对应start为右边,属性值具体对应的方位如下
AlignmentDirectional topStart = AlignmentDirectional(-1.0, -1.0);
AlignmentDirectional topCenter = AlignmentDirectional(0.0, -1.0);
AlignmentDirectional topEnd = AlignmentDirectional(1.0, -1.0);
AlignmentDirectional centerStart = AlignmentDirectional(-1.0, 0.0);
AlignmentDirectional center = AlignmentDirectional(0.0, 0.0);
AlignmentDirectional centerEnd = AlignmentDirectional(1.0, 0.0);
AlignmentDirectional bottomStart = AlignmentDirectional(-1.0, 1.0);
AlignmentDirectional bottomCenter = AlignmentDirectional(0.0, 1.0);
AlignmentDirectional bottomEnd = AlignmentDirectional(1.0, 1.0);
fit:子控件适应Stack控件尺寸的方式,这个属性对于非Positioned控件内的子控件起作用。
StackFit.loose:使用此属性时,对于非Positioned控件内的子控件,它的尺寸会小于Stack控件的尺寸,比如Stack的尺寸是300x600,那么子控件的尺寸宽度允许在0到300之间,高度允许在0到600之间;
StackFit.expand:使用此属性时,对于非Positioned控件内的子控件,它的尺寸会撑满Stack的尺寸。比如Stack的尺寸是300x600,那么子控件的尺寸宽度会是300,高度会是600;
StackFit.passthrough:对子控件的约束条件直接由Stack的父控件传递给Stack的子控件;

GridView

网格布局,类似于iOS的UICollectionView


WX20230808-100723.png
 Widget build(BuildContext context) {
    return GridView(
      scrollDirection: Axis.vertical,
      reverse: false,
      //      primary: true,
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3, //横轴三个子widget
          childAspectRatio: 1.3 //宽高比为1
          ),
      children: <Widget>[
        Container(
          color: Colors.blue[300],
          margin: EdgeInsets.fromLTRB(5, 5, 5, 5),
          width: 70,
          height: 70,
        ),
        Container(
          color: Colors.blue[300],
          margin: EdgeInsets.fromLTRB(5, 5, 5, 5),
          width: 70,
          height: 70,
        ),
        Container(
          color: Colors.blue[300],
          margin: EdgeInsets.fromLTRB(5, 5, 5, 5),
          width: 70,
          height: 70,
        ),
        Container(
          color: Colors.blue[300],
          margin: EdgeInsets.fromLTRB(5, 5, 5, 5),
          width: 70,
          height: 70,
        ),
        Container(
          color: Colors.blue[300],
          margin: EdgeInsets.fromLTRB(5, 5, 5, 5),
          width: 70,
          height: 70,
        ),
        Container(
          color: Colors.blue[300],
          margin: EdgeInsets.fromLTRB(5, 5, 5, 5),
          width: 70,
          height: 70,
        ),
      ],
    );
  }

scrollDirection: 滚动方向,Axis.vertical(竖直方向);Axis.horizontal(水平方向);
reverse:子控件排序是否反转;
controller: 滚动控制器,监听和控制滚动用到,比如写下拉加载更多之类的功能就可以用到这个。可以参考ScrollController 滚动监听及控制
shrinkWrap:该属性表示是否根据子组件的总长度来设置GridView的长度,默认值为false 。默认情况下,GridView的会在滚动方向尽可能多的占用空间。当GridView在一个无边界(滚动方向上)的容器中时,shrinkWrap必须为true。
gridDelegate: 控制子控件排列规则的参数,包括配置子控件横纵方向间距,纵轴方向子控件个数,子控件宽高比例等参数,详细文档参考GridView

ListView

1. ListView.builder
QQ20230808-101821.png
ListView.builder(
    itemCount: data.length,
    itemExtent: 50.0, //强制高度为50.0
    itemBuilder: (BuildContext context, int index) {
      return ListTile(title: Text("$index"));
    }
);

itemBuilder作为列表项的布局构建器,具体构建每个位置上的item布局,并展示相应的内容。itemCount配置列表的item条数,可以根据具体的数据来灵活配置。

2. ListView.separated

相对于ListView.builder,ListView.separated增加了一个分割线的构造器separatorBuilder,分割线在实际开发中也是很常用到的。

ListView.separated(
          itemBuilder: (BuildContext context, int index) {
            return Container(
                height: 60,
                child: TextButton(
                    onPressed: () {},
                    child: Text(
                      "哈哈",
                    )));
          },
          separatorBuilder: (BuildContext context, int index) {
            return Container(
              height: 1,
              color: Color(0xffe2e8ed),
            );
          },
          itemCount: 39),

ListView主要属性:
itemExtent: 此参数如果不为null,则会强制children的“长度”为itemExtent的值;这里的“长度”是指滚动方向上子组件的长度,也就是说如果滚动方向是垂直方向,则itemExtent代表子组件的高度;如果滚动方向为水平方向,则itemExtent就代表子组件的宽度。在ListView中,指定itemExtent比让子组件自己决定自身长度会更高效,这是因为指定itemExtent后,滚动系统可以提前知道列表的长度,而无需每次构建子组件时都去再计算一下,尤其是在滚动位置频繁变化时(滚动系统需要频繁去计算列表高度);
itemCount: item条数;
itemBuilder、separatorBuilder的作用在上面代码中都能看得比较清晰;
其他的包括scrollDirection、reverse、controller、shrinkWrap、addRepaintBoundaries、addAutomaticKeepAlives等等这些基本上和GridView是一样的,直接参考上面GridView就可以了。

SingleChildScrollView

单一子控件的滚动布局,跟Android的ScrollView基本一样,Android的ScrollView也是只能有一个子控件,不然就会报错。
基本使用很简单:

Widget build(BuildContext context) {
    return SingleChildScrollView(
      scrollDirection: Axis.vertical,
      reverse:false,
      controller:controller,
      child: Column(
        children: <Widget>[
            //...
        ],
      ),
    );
  } 

InkWell

InkWell有的叫溅墨效果,有的叫水波纹效果。使用场景是给一些无点击事件的部件添加点击事件时使用(也支持长按、双击等事件),同时你也可以去修改它的颜色和形状。

InkWell(
  borderRadius: BorderRadius.circular(8.0), // 圆角
  splashColor: Colors.transparent, // 溅墨色(波纹色)
  highlightColor: Colors.transparent, // 点击时的背景色(高亮色)
  onTap: () {},// 点击事件
  child: Container(),
);

不过有时你会发现并不是包一层InkWell就一定会有溅墨效果。主要原因是溅墨效果是在一个背景效果,并不是覆盖的前景效果。所以InkWell中的child一旦有设置背景图或背景色,那么就会遮住这个溅墨效果。如果你需要这个溅墨效果,有两种方式实现。
1、包一层 Material,将背景色设置在 Material中的color里。

Material(
  color: Colors.white,
  child: InkWell(),
)

2、使用Stack布局,将InkWell放置在上层。这种适用于给图片添加点击效果,比如Banner图的点击。

        Stack(
            children: <Widget>[
              Positioned.fill(
                child: Image(),
              ),
              Positioned.fill(
                child: Material(
                  color: Colors.transparent,
                  child: InkWell(
                    splashColor: Color(0X40FFFFFF),
                    highlightColor: Colors.transparent,
                    onTap: () {},
                  ),
                ),
              )
            ],
          )

相关文章

  • Flutter基础控件篇[2]--布局

    前言 接着Flutter基础控件篇[1],这一篇主要记录Flutter容器控件的使用,也就是常用的布局控件(Lay...

  • flutter(六,页面布局篇)

    Tags: flutter Flutter页面布局篇 [TOC] 1. 布局及装饰组件说明 2. 基础布局处理 2...

  • Flutter 布局控件技术文章(转)

    Flutter 布局控件完结篇 Flutter攻略 Widgets 目录-中文翻译 Flutter Widget ...

  • Flutter基础控件篇[3]

    前言 接Flutter基础控件篇[2],继续往下罗列。这一篇主要记录Table、ListView、GridView...

  • Flutter 布局

    flutter布局 flutter部分分两种,一种是单个子控件的布局一种是多个子控件的布局 常用的单个子控件布局 ...

  • Flutter 容器布局 Container Widget

    Flutter 基础布局 Container Widget Container将会是我们以后最常用的控件之一,Co...

  • Flutter技术分享

    一.布局 Flutter 里面有100多个控件,核心就是一切皆组件。 flutter常用的布局widget有Con...

  • Flutter 控件学习记笔记

    Flutter 控件学习记笔记 1 自适应宽度流式布局 也就是使用Wrap包裹的列表; 2 水波纹点击控件 使用I...

  • Flutter领航系列篇02

    上一回 Flutter领航系列篇01 我们对Flutter进行了基本的介绍。学了基础控件Scaffold和Text...

  • 基本的Material Design布局结构

    Flutter应用的用户界面是由布局控件(不可见的)和展示控件(可见的)协同完成的,布局控件就像是建筑里的框架,而...

网友评论

      本文标题:Flutter基础控件篇[2]--布局

      本文链接:https://www.haomeiwen.com/subject/ywqgpdtx.html