flutter布局详解及代码示例(上)

布局

基本布局

  • Row(水平布局):在水平(X轴)方向上排列子widget的列表。
  • Column(垂直布局):在垂直(Y轴)方向上排列子widget的列表。
  • Stack(可重叠布局):可以允许其子widget简单的堆叠(Z轴)在一起。
  • IndexedStack(单一显示可重叠布局):相比Stack后面编码的widget显示在Z轴上方,IndexedStack通过index可以控制显示哪个widget显示在Z轴的上方,注意,只显示一个。
  • ListView(滚动列表):最常用的滚动widget。

Row

  • 不带滚动属性,如果超出约束范围,在debug版本下会提示溢出。

代码

Row(
   crossAxisAlignment: CrossAxisAlignment.start,
   children: <Widget>[
       new Text('1'),
       new Text('2'),
       new Text('3'),
   	],
)

常用参数

mainAxisAlignment
  • X轴方向上的对齐方式
  • spaceBetween:沿X轴方向均分,子widget之间的空白区域相等,两侧贴边,比如只有两个子widget就在两边,三个就左中右这样。
  • spaceAround:沿X轴方向均分,左右两侧不贴边,有空白区域,但空白区域是子widget之间的空白区域的1/2。
  • spaceEvenly:沿X轴方向均分,左右两侧不贴边,有空白区域,空白区域和子widget之间的空白区域大小一致。
crossAxisAlignment
  • Y轴方向上的对齐方式
  • stretch:让子widget充满Y轴。
  • baseline:在Y轴上和基线适配,搭配textBaseline用
textBaseline
  • 文本内容的基线类型,就是文本的水平边界线,注意,只有水平
  • alphabetic:以字母字符底部的水平线对齐(不论中英文,都是用文字的最底部对齐)
  • ideographic:以表意字符的水平线对齐。(英文如pgj这些底部会比中文矮一些)
mainAxisSize
  • X轴方向应占用多少空间,默认最大化的占用主轴空间。
  • 若为MainAxisSize.min,则mainAxisAlignment只能为start。
verticalDirection
  • 垂直方向上的排列顺序
  • up:子widget从bottom开始往top排列;
  • down:子widget从top开始往bottom排列。
  • 搭配crossAxisAlignment的start和end属性有如下不同:
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
textDirection
  • 与verticalDirection类似,水平方向上的排列顺序
  • ltr:left to right,从左到右排列;
  • rtl:rigth to left,从右到左排列;
  • 同verticalDirection类似,搭配mainAxisAlignment使用,如下:
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Column

  • 不带滚动属性,如果超出约束范围,在debug版本下会提示溢出。

代码

Column(
   crossAxisAlignment: CrossAxisAlignment.start,
   children: <Widget>[
       new Text('1'),
       new Text('2'),
       new Text('3'),
   	],
)

常用参数

mainAxisAlignment
  • Y轴方向上的对齐方式
  • spaceBetween:沿Y轴方向均分,子widget之间的空白区域相等,比如只有两个子widget就在上下,三个就上中下这样。
  • spaceAround:沿Y轴方向均分,上下两侧不贴边,有空白区域,但空白区域是子widget之间的空白区域的1/2。
    • spaceEvenly:沿Y轴方向均分,上下两侧不贴边,有空白区域,空白区域和子widget之间的空白区域大小一致。
crossAxisAlignment
  • X轴方向上的对齐方式
  • stretch:让子widget充满X轴。
  • baseline:相当于start,因为textBaseline只有水平,因为没有文字是需要人歪头90度看的。
mainAxisSize
  • Y轴方向应占用多少空间,默认最大化的占用主轴空间。
  • 若为MainAxisSize.min,则mainAxisAlignment只能为start。
verticalDirection
  • 垂直方向上的排列顺序
  • up:子widget从bottom开始往top排列;
  • down:子widget从top开始往bottom排列。
  • 搭配mainAxisAlignment的start和end属性有如下不同:
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
textDirection
  • 与verticalDirection类似,水平方向上的排列顺序
  • ltr:left to right,从左到右排列;
  • rtl:rigth to left,从右到左排列;
  • 同verticalDirection类似,搭配crossAxisAlignment使用,如下:
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Stack

  • 可以子widget无视位置压在另一个子widget的布局
  • 内部使用Positioned定位子widget位置宽高
    • width,left和right三个属性不能同时使用,必须至少有一个属性是null;
    • height,top和bottom三个属性不能同时使用,必须至少有一个属性是null。

代码

Stack(
  alignment: Alignment(-1.0,0.0),//等价于Alignment.centerLeft
  children: <Widget>[
    Positioned(child: Container(width: 100.0,height: 100.0,color: Colors.red,),),
    Positioned(child: Container(width: 90.0,height: 90.0,color: Colors.green,),),
    Positioned(child: Container(width: 80.0,height: 80.0,color: Colors.blue,),),
    new Text('-1,0\ncenterLeft',textAlign: TextAlign.left,),
  ],
)

完整示例

Container(
    width: 200,
    height: 200,
    child: Stack(
        children: <Widget>[
        Positioned(
            // 若是不指定位置就是(0,0)
            // 若是不指定size就是子view的size
            // top: 50.0,
            // left: 50.0,
            child: Container(
                width: 200,
                height: 200,
            ),
        ),
        Positioned(
            top: 0.0,
            left: 190.0,
            child: Container(
            width: 10.0,
            height: 10.0,
            color: Colors.green,
            ),
        ),
        ],
    ),
);

常用参数

alignment
  • 可以传递AlignmentDirectional、Alignment、FractionalOffset三大类,主要用的是带方向的AlignmentDirectional。
textDirection
  • 搭配AlignmentDirectional的start或者end实现类似Row的mainAxisAlignment+textDirection的效果。
fit
  • loose:从Stack传递过来的约束被解除,即:
    • 当Stack大小被限制为300*400,子widget元素的大小将可设置为,宽:0到300,高:0到400。
  • expand:从Stack传递过来的约束被锁定到最大,即:
    • 当Stack大小被限制为300*400,子widget元素的大小将锁定为,宽:300,高:400。
  • passthrough:不改变子组件约束条件。和loose一致。
overflow
  • 是否裁剪溢出的子widget元素
  • clip:裁剪溢出部分
  • visible:显示溢出部分

IndexedStack

  • 相比Stack多了一个index参数,控制显示哪个子widget
  • 内部使用Positioned定位子widget位置宽高
    • width,left和right三个属性不能同时使用,必须至少有一个属性是null;
    • height,top和bottom三个属性不能同时使用,必须至少有一个属性是null。

代码

IndexedStack(
  sizing: StackFit.expand,
  index: 1,
  children: <Widget>[
    Positioned(child: Container(width: 100.0,height: 100.0,color: Colors.red,),),
    Positioned(child: Container(width: 130.0,height: 90.0,color: Colors.green,),),
    Positioned(child: Container(width: 80.0,height: 120.0,color: Colors.blue,),),
   ],
),

index就是children的length的区间之中的值。
比如上面的代码,就只显示index为1的子widget,也就是第二个。

常用参数
  • 因为只显示一个,所以Stack的常用参数基本用不到

ListView

    • listview需要拓展长度,比如是纵向的listview,就需要指定父view的height。
  • 可以理解为可以滚动的Column。
  • 有四种构造方式
    • List():默认构造;
      • 直接把子widget硬编码,如果子widget较多,有性能风险。
    • ListView.builder();
      • 不带分割线
      • 懒加载,只会渲染可见的条目。
    • ListView.separated;
      • 带分割线
      • separatorBuilder是必传参数,用于构造分割线view
      • 分割线返回的是一个widget(不必一定是Divider),所以可以自定义
    • ListView.custom。
      • 搭配SliverChildBuilderDelegate自定义实现不同类型子widget,比如子widget和分割线交替出现等复杂场景。

代码

/// 默认构造
ListView(
  children: [ 
    new Text('1'),
    Divider(),
    new Text('2'),
    Divider(),
    new Text('3'),
    Divider(),
  ],
),
/// ListView.builder()构造
final List<String> name = <String>['1','2','3',];
ListView.builder(
  itemCount: name.length,
  itemBuilder: (context, index) {
    return Text(name[index]);
  },
),
/// ListView.separated()构造
ListView.separated(
  itemBuilder: (context, index) {
    return Text(name[index]);
  },
  separatorBuilder: (context, index) {
    return Divider();//分割线
  },
  itemCount: name.length,
),
/// ListView.custom()
ListView.custom(
  childrenDelegate: SliverChildBuilderDelegate(
    (context, index) {
      return Text(name[index]);
    },
    childCount: name.length,
  ),
),

详细代码

var lv1 = ListView(
    //主轴滚动方向:垂直vertical,竖直horizontal ,默认为垂直vertical,
    scrollDirection: Axis.vertical,
    //是否反向 默认为false,正常顺序从起始点开始正序,true为从末尾开始排列
    reverse: false,
    //滚动控制器,默认为null
    controller:null,
    //是否强制滚动(顶部或底部时是否可以滚动),默认是false,如果为true,Controller必须为null
    primary: false,
    //视图如何响应用户的手势滑动,有内置实现强制可以滚动 const AlwaysScrollableScrollPhysics();和强制不可以滚动const ScrollPhysics(),可忽略primary属性
    physics: const AlwaysScrollableScrollPhysics(),
    //默认为false,滚动视图在[滚动方向]中的范围是否应由正在查看的内容决定。
    shrinkWrap: true,
    //item的padding值
    padding: const EdgeInsets.all(10.0),
    //item交叉轴方向的大小,默认自适应,vertical时为高度,horizontal时为高度
    itemExtent: 50.0,
    //是否自动保存滑出屏幕外的字widget的状态,保证widget不被回收,可复用,false的手动保存。默认为true
    addAutomaticKeepAlives: true,
    //是否放置到重绘列表中,复杂widget可提高性能,默认为true
    addRepaintBoundaries: true,
    //缓存区大小,默认为250
    cacheExtent: 250.0,
    //默认构造函数中特有,直接将子widget放置内,一次性渲染完成,适合少量数据
    children: [
        new Text('测试1'),
        Divider(),
        new Text('测试2'),
        Divider(),
        new Text('测试3'),
        Divider(),
        new Text('测试4'),
        Divider(),
        new Text('测试5'),
        Divider(),
    ],
);

每个item不同的listview

  • 用switch-case返回不同的item来实现不同的item的view
import 'package:flutter/material.dart';

class MyListPage extends StatelessWidget {
  final List<Item> itemList = [
    Item(type: ItemType.button, data: ['Button 1', 'Button 2']),
    Item(type: ItemType.text, data: 'Hello World'),
    Item(
        type: ItemType.image,
        data: 'https://example.com/images/image.jpg'),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('My List Page'),
      ),
      body: ListView.builder(
        itemCount: itemList.length,
        itemBuilder: (BuildContext context, int index) {
          Item item = itemList[index];

          Widget itemWidget;

          // 根据item类型构建不同的widget
          switch (item.type) {
            case ItemType.button:
              List<String> buttonTexts = item.data;
              itemWidget = Row(
                children: [
                  ElevatedButton(
                    onPressed: () {},
                    child: Text(buttonTexts[0]),
                  ),
                  ElevatedButton(
                    onPressed: () {},
                    child: Text(buttonTexts[1]),
                  ),
                ],
              );
              break;

            case ItemType.text:
              String textData = item.data;
              itemWidget = Text(textData);
              break;

            case ItemType.image:
              String imageUrl = item.data;
              itemWidget = Image.network(imageUrl);
              break;
          }

          return ListTile(
            title: itemWidget,
          );
        },
      ),
    );
  }
}

class Item {
  final ItemType type;
  final dynamic data;

  Item({
    required this.type,
    required this.data,
  });
}

enum ItemType {
  button,
  text,
  image,
}

垂直滑动里嵌套水平滑动

class _PageBizCertificateState extends eState<PageBizCertificate> {

  final List<String> items = List.generate(20, (index) => 'Item $index');

  @override
  Widget pageBody(BuildContext context) {
    return ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) {
        return MyListItem(title: items[index]);
      },
    );
  }

  Widget MyListItem({required String title}) {
    return Container(
      padding: EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('第一行文本'),
          SizedBox(height: 8.0),
          MyHorizontalScrollList(),
          SizedBox(height: 8.0),
          Text('第三行文本'),
        ],
      ),
    );
  }

  Widget MyHorizontalScrollList() {
    return Container(
      height: 100.0,
      child: ListView.builder(
        scrollDirection: Axis.horizontal,
        itemCount: 10,
        itemBuilder: (context, index) {
          return Container(
            width: 100.0,
            margin: EdgeInsets.all(4.0),
            color: Colors.blue,
            child: Center(
              child: Text('水平项 $index'),
            ),
          );
        },
      ),
    );
  }

}

参数列表

  • scrollDirection:主轴滚动方向;默认垂直滚动Axis.vertical,还可水平滚动Axis.horizontal
  • reverse:是否反向排列,默认false,即正序排列
  • controller:滚动控制器,默认为null
  • primary:是否强制滚动,默认false
  • physics:响应用户滑动。
    • NeverScrollableScrollPhysics(), // 禁止滑动
  • shrinkWrap:滚动视图在滚动方向中的范围是否应由正在查看的内容决定。默认为false
  • padding:距边框item边间距
  • cacheExtent:缓存大小,默认250.0
  • itemExtent:item在交叉轴方向上的长度;null时为自适应
  • addAutomaticKeepAlives:是否自动保存滑出屏幕外的字widget的状态,默认true,保存,可复用
  • addRepaintBoundaries:是否放置到重绘列表中;默认true,可提高性能
  • itemBuilder:builder和separated构造函数特有要传入参数,定义item的样式
  • separatorBuilder:separated构造函数特有要传入的参数,定义分割线的样式
  • itemCount:列表可滚动的item数量,默认构造没有
  • childrenDelegate:内部都是靠此类实现滚动和布局,但只有custom构造函数需要传入,其余都内部实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/195861.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

①实现基于session的登录流程:发送验证码、登录注册、校验登陆状态

个人简介&#xff1a;Java领域优质创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 登录功能 实现 实现基于session的登录流程&…

JS:获取当前日期是本年度的第几周

问题 根据当前的日期&#xff08;比如年月日&#xff09;&#xff0c;来得到当前日期属于本年度的第几周 解决 代码&#xff1a; // 获取当前日期是本年的第几周 //参数&#xff1a; a为年 b为月 c为日 function getYearWeek(a, b, c) {var date1 new Date(a, parseInt(b)…

通过火狐Firefox浏览器在设备间留言、传递备注消息

如果多台设备间没有都安装微信、飞书这种可以通过文件传输助手备注消息的APP&#xff0c;那么可通过火狐浏览器在设备间留言。 原理&#xff1a;火狐支持把当前设备的一个浏览器标签页发送到其他设备 那么我们只需要把要留言的文本记录到一个网页&#xff0c;然后发送到其他设…

【前端首屏加载速度优化(0): 谷歌浏览器时间参数】

DOMContentLoaded 浏览器已经完全加载了 HTML&#xff0c;DOM树构建完成&#xff0c;但是像是 <img> 和样式表等外部资源可能并没有下载完毕。 Load DOM树构建完成后&#xff0c;继续加载 html/css 中的外部资源&#xff0c;加载完成之后&#xff0c;视为页面加载完成。…

四川开启智能巡河形式,无人机水利行业应用再创新

在四川省某区域&#xff0c;复亚智能无人机系统以其独特的机场网格化部署得到成功应用&#xff0c;覆盖了该区域内多条市级、省级河流&#xff0c;成为水利行业的新亮点。这一先进系统以无人机水利行业应用为核心&#xff0c;通过网格化和信息化手段&#xff0c;实现了对水域环…

吉利展厅 | 透明OLED拼接2x2:科技与艺术的完美融合

产品&#xff1a;4块55寸OLED透明拼接屏 项目地点&#xff1a;南宁 项目时间&#xff1a;2023年11月 应用场景&#xff1a;吉利展厅 在2023年11月的南宁&#xff0c;吉利展厅以其独特的展示设计吸引了众多参观者的目光。其中最引人注目的亮点是展厅中央一个由四块55寸OLED透…

Mysql并发时常见的死锁及解决方法

使用数据库时&#xff0c;有时会出现死锁。对于实际应用来说&#xff0c;就是出现系统卡顿。 死锁是指两个或两个以上的事务在执行过程中&#xff0c;因争夺资源而造成的一种互相等待的现象。就是所谓的锁资源请求产生了回路现象&#xff0c;即死循环&#xff0c;此时称系统处于…

Jetpack Compose中适应性布局的新API

Jetpack Compose中适应性布局的新API 针对大屏幕优化的新组合件。 使用新的Material适应性布局&#xff0c;为手机、可折叠设备和平板电脑构建应用程序变得更加简单&#xff01;市场上各种不同尺寸的Android设备的存在挑战了构建应用程序时对屏幕尺寸的通常假设。开发者不应该…

AI辅助工具

任务拆解工具 Magic ToDo - GoblinTools 可用的AI搜索和对话工具&#xff1a;chatgpt 梦畅AI

《山水间的家》第二季收官,国台酒业解锁中国式浪漫

执笔 | 洪大大 编辑 | 萧 萧 近日&#xff0c;由国台酒特别支持的大型文旅探访节目《山水间的家》第二季在总台央视综合频道&#xff08;CCTV-1&#xff09;正式收官。 第二季节目以家庭为视角切入&#xff0c;先后走进江苏、四川、重庆、江西、湖北、贵州、浙江等地24个特色…

TS版LangChain实战:基于文档的增强检索(RAG) | 京东云技术团队

LangChain LangChain是一个以 LLM &#xff08;大语言模型&#xff09;模型为核心的开发框架&#xff0c;LangChain的主要特性&#xff1a; 可以连接多种数据源&#xff0c;比如网页链接、本地PDF文件、向量数据库等允许语言模型与其环境交互封装了Model I/O&#xff08;输入…

实用又好用Mybatis-Plus版的EasyCode模板

1&#xff1a;插件下载 Plugins中搜索EasyCode,并且下载安装 2&#xff1a;模板编写 2.1&#xff1a;entity.vm.java模板 ##引入宏定义 $!{define.vm}##使用宏定义设置回调&#xff08;保存位置与文件后缀&#xff09; #save("/entity", "DO.java")##使…

03 项目运行

前面两篇文章对项目架构+源码架构做了分析,这篇文章先将服务部署一下,能够让大家有个直观的感受。 组件资源 项目运行的各种组件已经为你准备好了,有需要的直接百度云盘下载: 链接:https://pan.baidu.com/s/1hN6qf20gamMHPmA_qXwsLg提取码:o4k9MySQL数据库创建 找到的…

四川天蝶电子商务有限公司真实可靠吗?

随着数字经济的不断发展&#xff0c;抖音电商服务日益成为企业拓展销售渠道、提升品牌影响力的关键一环。在这样的大背景下&#xff0c;四川天蝶电子商务有限公司凭借其专业的服务能力和创新的技术手段&#xff0c;迅速崛起为抖音电商服务领域的领军企业。 四川天蝶电子商务有限…

Ubuntu系统Springboot项目Nginx安装(编译安装方式)

1.下载 nginx官网下载 Index of /download/ 2.解压 这里我下载的1.25.3版本&#xff0c;系统是ubuntu 解压 tar -zxvf nginx-1.25.3.tar.gz 3.编译安装 安装前需要执行安装一些系统依赖 3.1安装PCRE库 ubuntu&#xff1a;执行以下命令 sudo apt-get install libpcre…

每日一练2023.11.28———N个数求和【PTA】

题目链接&#xff1a; L1-009 N个数求和 题目要求&#xff1a; 本题的要求很简单&#xff0c;就是求N个数字的和。麻烦的是&#xff0c;这些数字是以有理数分子/分母的形式给出的&#xff0c;你输出的和也必须是有理数的形式。 输入格式&#xff1a; 输入第一行给出一个正整…

【影刀RPA_写入日期到飞书表格】

飞书将日期写入多维表格&#xff0c;日期格式需要时毫秒级的时间戳才行。

已知两个链表L1和L2分别表示两个集合,其中元素递增排列。请设计一个算法,用于求出L1与L2的交集,并存放在L1链表中

已知两个链表L1和L2分别表示两个集合&#xff0c;其中元素递增排列。请设计一个算法&#xff0c;用于求出L1与L2的交集&#xff0c;并存放在L1链表中。 代码思路&#xff1a; 我们创建一个辅助链表L3&#xff0c;用于存储L1和L2链表的交集&#xff0c;用s遍历L3各个元素 用p和…

常见加密算法

常见加密算法 加密算法是一种用数学方法对数据进行变换的技术&#xff0c;目的是保护数据的安全&#xff0c;防止被未经授权的人读取或修改。加密算法可以分为三大类&#xff1a;对称加密算法、非对称加密算法和哈希算法&#xff08;也叫摘要算法&#xff09;。 哈希算法 哈…

C++之STL库:string类(用法列举和总结)

前言 大家在学习STL库的时候一定要学会看英文文档&#xff0c;俗话说熟能生巧&#xff0c;所以还得多练&#xff01;在使用string类之前&#xff0c;要包含头文件#include <string>和using namespace std; 文档链接&#xff1a;string - C Reference 一、string——构造…
最新文章