• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Flutter布局组件水平/垂直组件、叠加布局组件、流式布局组件

武飞扬头像
无知的小菜鸡
帮助1

前言

参考:老孟 Flutter教程

水平/垂直组件

Row 是将子组件以水平方式布局的组件, Column 是将子组件以垂直方式布局的组件。项目中 90% 的页面布局都可以通过 Row 和 Column 来实现。

将3个组件水平排列

Row(
  children: [
      Container(
        width: 100,
        height: 60,
        color: Colors.red,
      ),
      Container(
        width: 100,
        height: 60,
        color: Colors.green,
      ),
      Container(
        width: 100,
        height: 60,
        color: Colors.blue,
      )
    ],
);
学新通

学新通
将3个组件垂直排列

Column(
      children: [
        Container(
          width: 100,
          height: 60,
          color: Colors.red,
        ),
        Container(
          width: 100,
          height: 60,
          color: Colors.green,
        ),
        Container(
          width: 100,
          height: 60,
          color: Colors.blue,
        )
      ],
    );
学新通

主轴与交叉轴

在 Row 和 Column 中有一个非常重要的概念:主轴( MainAxis ) 和 交叉轴( CrossAxis ),主轴就是与组件布局方向一致的轴,交叉轴就是与主轴方向垂直的轴。

具体到 Row 组件,主轴 是水平方向,交叉轴 是垂直方向。而 Column 与 Row 正好相反,主轴 是垂直方向,交叉轴 是水平方向。

主轴尺寸

mainAxisSize 表示主轴尺寸,有 min 和 max 两种方式。默认是最大值,继承父元素的尺寸;最小值是包裹自身

主轴对齐与文本对齐的区别

  mainAxisAlignment: MainAxisAlignment.end,

学新通

 textDirection: TextDirection.rtl,

学新通
主轴的靠右对齐是整体靠右对齐,元素的顺序还是从做往右;文本的顺序会改变元素的顺序。

叠加布局组件

Stack

Stack 组件将子组件叠加显示,根据子组件的顺序依次向上叠加

Stack(
   children: [
     Container(
       width: 200,
       height: 200,
       color: Colors.red,
     ),
     Container(
       width: 100,
       height: 100,
       color: Colors.blue,
     ),
   ],
 );

学新通
未定位组件

  • 大小
    Stack 对未定位(不被 Positioned 包裹)子组件的大小由 fit 参数决定,默认值是 StackFit.loose ,表示子组件自己决定,StackFit.expand 表示尽可能的大
 fit:StackFit.expand,

设置完上面的属性后,最上面的组件会尽可能的大(充满父元素,自身的宽高将不会生效)

  • 对齐方式
    Stack 对未定位(不被 Positioned 包裹)子组件的对齐方式由 alignment 控制,默认左上角对齐
 alignment: AlignmentDirectional.center,

学新通

定位组件

Stack(
      children: [
        Container(
          width: 200,
          height: 200,
          color: Colors.red,
        ),
        Positioned(
          top: 20,
          left: 20,
          child: Container(
            width: 100,
            height: 100,
            color: Colors.blue,
          ),
        )
      ],
    );
学新通

学新通

IndexedStack

IndexedStack 通过 index 只显示指定索引的子组件

class _YcHomeBodyState extends State<YcHomeBody> {
  int _index = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        _buildIndexedStack(),
        _buildRow(),
      ],
    );
  }

  _buildIndexedStack() {
    return IndexedStack(
      index: _index,
      children: <Widget>[
        Center(
          child: Container(
            height: 300,
            width: 300,
            color: Colors.red,
            alignment: Alignment.center,
            child: const Icon(
              Icons.fastfood,
              size: 60,
              color: Colors.blue,
            ),
          ),
        ),
        Center(
          child: Container(
            height: 300,
            width: 300,
            color: Colors.green,
            alignment: Alignment.center,
            child: const Icon(
              Icons.cake,
              size: 60,
              color: Colors.blue,
            ),
          ),
        )
      ],
    );
  }

  _buildRow() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        IconButton(
          icon: const Icon(Icons.fastfood),
          onPressed: () {
            setState(() {
              _index = 0;
            });
          },
        ),
        IconButton(
          icon: const Icon(Icons.cake),
          onPressed: () {
            setState(() {
              _index = 1;
            });
          },
        )
      ],
    );
  }
}
学新通

核心是通过两个返回组件的函数来决定最终渲染什么组件。

学新通

流式布局组件

Wrap 为子组件进行水平或者垂直方向布局,且当空间用完时,Wrap 会自动换行,也就是流式布局。

Wrap(
      children: List.generate(10, (index) {
        double w = 50.0   10.0 * index;
        return Container(
          width: w,
          height: 50,
          color: Colors.primaries[index],
          child: Text('$index'),
        );
      }),
    );
  }

学新通
direction
direction 属性控制布局方向,默认为水平方向

direction:Axis.vertical ,

学新通
alignment 和 crossAxisAlignment

alignment 属性控制主轴对齐方式,crossAxisAlignment 属性控制交叉轴对齐方式,对齐方式只对有剩余空间的行或者列起作用
这个与flex弹性布局基本是一致的

spacing 和 runSpacing
spacing 是主轴方向上的间隔,runSpacing是交叉轴上的间隔

spacing: 10,
runSpacing: 50,

学新通
textDirection
文本对齐方式,前面说了,这里不提了

verticalDirection
属性表示 Wrap 交叉轴方向上子组件的方向,取值范围是 up(向上) 和 down(向下)

  • up:可以理解为从上往下落,先落下的在最下面
 verticalDirection:VerticalDirection.up,

学新通

  • down:可以理解为从下往上出,先出来的在上面
verticalDirection:VerticalDirection.down,

学新通

案例

学新通
从布局图可以看出整体上是一列,一列有多行。每一行的内容基本一致,分别是图标、标题、后置,因此可以封装成一个单独的组件。消息中心的后置和其他行的内容不一样,内容可以单独拆成一个组件。

文章中的这个案例还是很重要并且基础的,讲解了组件的拆分、组合。

行组件

// 行组件,只是展示不需要状态
class _MyItem extends StatelessWidget {
  final IconData iconData; //图标
  final Color iconColor; //图标颜色
  final String title; //标题
  final Widget suffix; //后缀

  //类的构造函数
  const _MyItem(
      {required Key key, //每一个组件的key,标识唯一
      required this.iconData,
      required this.iconColor,
      required this.title,
      required this.suffix})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    // Row组件没有宽度,外层套一个SizedBox
    return  SizedBox(
      height: 45,
      child: Row(
        children:  [
          //用来占位,充当padding
          const SizedBox(width: 40,),
          //图标
          Icon(iconData,color: iconColor),
          const SizedBox(width: 30,),
          //标题,Expanded自动填充剩余空间
          Expanded(child: Text(title)),
          const SizedBox(width: 10,),
          //后缀
          suffix,
          const SizedBox(width: 15,),
        ],
      ),
    );
  }
}
学新通

后缀

后缀可以分成带红色背景的组件和灰色字体的组件

  • 红色背景组件
//红色字体组件
class _NotificationsText extends StatelessWidget {
  //文字
  final String text;
  const _NotificationsText(this.text, {Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 10),
      //装饰,盒子装饰
      decoration: const BoxDecoration(
          shape: BoxShape.rectangle, //外形是矩形
          borderRadius: BorderRadius.all(
            Radius.circular(10),
          ),
          color: Colors.red),
      //文本
      child: Text(text,style: const TextStyle(color: Colors.white),),
    );
  }
}
学新通
  • 灰色字体组件
//灰色字体组件
class _Suffix extends StatelessWidget{
  final String text;
  const _Suffix(this.text,{Key?key}) :super(key:key);
  @override
  Widget build(BuildContext context) {
    return Text(text,style: TextStyle(color: Colors.grey.withOpacity(.5)),)
  }
}

组装

 return Column(
          children:  const [
             _MyItem(
              iconData: Icons.notifications,
              iconColor: Colors.blue,
              title: '消息中心',
              suffix: _NotificationsText('2'),
            ),
            _MyItem(
              iconData: Icons.thumb_up,
              iconColor: Colors.green,
              title: '我赞过的',
              suffix: _Suffix('121篇',),
            )
          ],
    );
  }
学新通

效果
学新通
左侧是原图,右侧是成果图

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgakjik
系列文章
更多 icon
同类精品
更多 icon
继续加载