当前位置: 首页 > news >正文

【Flutter零基础入门 | Day03】常用功能与滚动组件

前言

在上一篇博客,我们了解了 Flutter 中的布局组建。基于布局组建,再结合今天学习的功能组建和滚动组件,就可以在 Flutter 中实现一个基本可用的页面。

目录

前言

功能组件

Text

style属性的使用

行数控制

TextSpan

Image

Image.asset()

Image.network()

TextField

UI 结构绘制

功能实现

滚动组件

SingleChildScrollView

滚动控制

ListView

默认构造模式

ListView.builder

ListView.separated

GridView

GridView.count()

GridView.extent()

GridView.builder()

总结


功能组件

Text

Text 组件用于在用户界面中显示文本,所有的文本显示都需要使用 Text 组件。如果需要在同一段文本中显示不同样式,可以使用 Text.rich 构造函数配合 TextSpan 实现。

Text 组件本身和其 TextStyle 中都有可能有 overflow 属性,此时 Text 组件优先级更高。

大量重复使用的文本样式建议统一定义,有助于保持一致性,提升性能。

属性类型作用说明
dataString必需。要显示的文本内容。
styleTextStyle文本样式,可设置颜色、大小、粗细等。
textAlignTextAlign文本在容器内的水平对齐方式,如.left.right
maxLinesint文本显示的最大行数。

style属性的使用

Text( style: TextStyle( fontSize: 30, color: Colors.blue, fontStyle: FontStyle.italic, fontWeight: FontWeight.bold, decoration: TextDecoration.underline, decorationColor: Colors.red, ), "Hello, Flutter!", ),

行数控制

当超出 maxLines 时,可以使用 overflow 属性,指定对超出文本的行为 (如自动转为省略号)。

Text( style: TextStyle(color: Colors.blue, fontSize: 30), maxLines: 2, overflow: TextOverflow.ellipsis, "今天天气不错今天天气不...", // 过长省略 ),

TextSpan

通过使用 Text.rich() 构造函数并传入 TextSpan 组件,可以实现对文本形式的单独设置。其中外层设置的是全局样式,内层设置的是相对样式。

Text.rich( TextSpan( style: TextStyle( fontSize: 30, color: Colors.red, fontWeight: FontWeight.bold, decoration: TextDecoration.underline, decorationColor: Colors.yellow, decorationThickness: 3, ), text: "Hello ", children: [ TextSpan( style: TextStyle(color: Colors.green), text: "Flutter", ), TextSpan(text: "!"), ], ), ),

Image

Image 组件是用于在用户界面中显示图片的核心组件。

分类

分类作用说明
Image.asset()加载项目资源目录 (assets) 中的图片。需要在 pubspec.yaml 文件中声明资源路径
Image.network()直接从网络地址加载图片。
Image.file()加载设备本地存储中的图片文件。
Image.memory()加载内存中的图片数据。

常用属性

分类类型作用说明
width / heightdouble设置图片显示区域的宽度和高度
fitBoxFit控制图片如何适应其显示区域,如拉伸、裁剪或保持原比例
alignmentAlignmentGeometry图片在其显示区域内的对齐方式
repeatImageRepeat当图片小于显示区域时,设置是否以及如何重复平铺图片

Image.asset()

步骤

  1. 配置 pubspec.yaml 文件,在 flutter.assets 配置项下配置要读取的图片名,或直接加载整个文件夹。配置 pubspec.yaml 时,要额外注意缩进问题。
flutter: uses-material-design: true assets: - lib/images/
  1. 在文件中添加 Image 组件,并在其中传入图片文件路径。要注意的是,由于配置文件修改过,而当前运行的程序没有这个配置,无法识别到新添加的路径,需要重新启动一次程序。
Container( alignment: Alignment.center, width: double.infinity, height: double.infinity, color: Colors.amber, child: Image.asset( "lib/images/github.png", width: 100, height: 100, // fit: BoxFit.contain, // fit: BoxFit.cover, // fit: BoxFit.fill, fit: BoxFit.fitHeight, ), ),

Image.network()

相比asset()network()配置相对简单,不需要添加资源文件或设置资源路径,只需要传入资源地址,并保证网络畅通即可。

在 Web 环境下不需要关心网络权限,但是在如 安卓、IOS、鸿蒙 等环境都需要确保软件具有网络权限。

Container( alignment: Alignment.center, width: double.infinity, height: double.infinity, color: Colors.amber, child: Image.network( "https://inews.gtimg.com/news_ls/OSBSD0f6k8Md_QZ3W7JJunUuywoclkUuurTrwDgmYq-YwAA_870492/0", width: 300, height: 300, fit: BoxFit.fill, ), ),

TextField

TextField 是用来实现文本输入的核心组件,使用时需要控制其中的内容。使用 TextField 时,必须使用有状态组件,因为 TextField 需要管理自己的状态,而只有有状态组件才能管理自己的状态。

其核心属性如下:

属性作用说明
controller文本编辑器控制器,用于获取、设置文档内容以及监听内容变化
decoration控制输入框的外观,如标签、提示文字、图标、边框等
style定义输入文本的样式
maxLines最大行数
onChanged输入内容发生变化时执行的回调函数
onSubmitted用户提交输入时的回调函数

UI 结构绘制

decoration 使用的类型为InputDecoration。设定背景颜色时,需要同时设定 fillColor 和 filled,前者用于设定背景颜色,后者用于允许显示背景颜色。hinitText 用于设置输入框的提示文本。同时,通过 obscureText 属性可以控制是否显示文本框内实际内容。

在 decoration 中,通过其中的 border 属性,可以控制输入框的边框信息,如是否圆角、是否有边框等。通过 borderSide,可以控制是否显示输入框的边框;通过 borderRadius 可以控制输入框的圆角。

在 decoration 中,通过 contentPadding 属性,可以控制输入框中内容的 padding。

使用obscureText属性,可以设定是否显示实际内容,通常用于密码输入框。

Container( padding: EdgeInsets.all(20), color: Colors.white, child: Column( children: [ TextField( decoration: InputDecoration( contentPadding: EdgeInsets.only(left: 20), border: OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.circular(25), ), fillColor: const Color.fromARGB(255, 255, 246, 164), filled: true, hintText: "请输入账号", ), ), SizedBox(height: 10), TextField( obscureText: true, decoration: InputDecoration( contentPadding: EdgeInsets.only(left: 20), border: OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.circular(25), ), fillColor: const Color.fromARGB(255, 255, 246, 164), filled: true, hintText: "请输入密码", ), ), SizedBox(height: 10), Container( height: 50, width: double.infinity, decoration: BoxDecoration( color: Colors.black, borderRadius: BorderRadius.circular(25), ), child: TextButton( onPressed: () {}, child: Text("提交", style: TextStyle(color: Colors.white)), ), ), ], ), ),

效果如下:

功能实现

controller

为获取 TextField 中的内容,需要为 TextField 的 controller 属性传入一个TextEditingController类型组件,以实现获取输入框内容的功能。

通常在有状态组件的对内类中声明控制器,并在相关的方法中通过该控制器获取组件中的内容并对组件进行操作。

class MainPage extends StatefulWidget { ... } // 在内部类中定义控制器 class _MainPageState extends State<MainPage> { TextEditingController _phoneController = TextEditingController(); TextEditingController _passwordController = TextEditingController(); @override Widget build(BuildContext context) { TextField( controller: _phoneController, ), TextField( controller: _passwordController, ), Container( child: TextButton( onPressed: () { print("登录-账号-${_phoneController.text}"); print("登录-密码-${_passwordController.text}"); }, child: Text("提交", style: TextStyle(color: Colors.white)), ), ), } }

onChanged 和 onSubmit

onChanged 回调方法在输入框中内容发生变化时调用,onSubmit 方法在输入框中内容提交时进行调用。在浏览器中,通过在输入框中回车触发 onSubmit 函数;在手机端通过键盘上的提交按钮触发 onSubmit 函数。

TextField( onChanged: (value) { print("onChanged: $value"); }, onSubmitted: (value) { print("onSubmitted: $value"); }, ),

滚动组件

组件特点使用场景
SingleChildScrollView让单个组件可以滚动,所有内容一次性全部渲染长表单、设置页、内容量不固定但总量不多的页面
ListView线性列表,可以通过 builder 实现懒加载,性能优异聊天记录、新闻、常见的单列滚动的数据列表
GridView网格布局列表,支持懒加载,可以固定列数图片墙、商品网格、应用图标列表
CustomScrollView复杂布局方案,通过组合多个 Sliver 组件实现滚动电商首页、社交 App 个人主页多个滚动紧密联动
PageView整页滚动效果,支持横向和纵向应用引导页、图片轮播页、书籍翻页

SingleChildScrollView

SingleChildScrollView 组件用于包裹一个子组件,让单个子组件具备滚动能力。

通过 List.generate 方法可以快速生成一系列组件。

Column( children: List.generate(100, (index) { return Container( margin: EdgeInsets.only(top: 10), width: double.infinity, height: 100, alignment: Alignment.center, color: Colors.blue, child: Text( "我是第${index + 1}个", style: TextStyle(color: Colors.white, fontSize: 30), ), ); }), ),

生成完后效果如下,可以看到提示 “Buttom overflowed by 10326 pixels”,即内容超出页面 (因内容无法滚动查看):

通过 SingleChildScrollView,可以使单个子组件具备滚动功能。同时可以设置 padding 内边距属性。

滚动控制

通过 SingleChildScrollView 的 controller 属性,可以给组件绑定对应的 ScrollController 对象。使用 Controller 组件,可以控制 SingleChildScrollView 的滚动位置等。

去底部 / 顶部的实现

ListView

ListView 组件是用于构建可滚动列表的核心部件,且提供了流畅的滚动体验。

该组件提供多种构造函数, 如默认构造函数、ListView.builder、ListView.separated。

除默认构造函数为非懒加载,其他构造方式都采用按需渲染的懒加载模式,只构建当前可见区域的列表项,极大提升长列表性能。

ListView 中同样存在 controller 属性,其接受值类型与 SingleChildSrcollView 相同,控制滚动方式也相同。

默认构造模式

默认构造函数会一次性构建所有选项,适用于静态数量有限数据一次性构建所有表项。

ListView( padding: EdgeInsets.all(10), children: List.generate(100, (index) { return Container( margin: EdgeInsets.only(top: 10), width: double.infinity, height: 80, alignment: Alignment.center, decoration: BoxDecoration(color: Colors.blue), child: Text( "第${index + 1}个", style: TextStyle(color: Colors.white, fontSize: 30), ), ); }), ),

ListView.builder

builder 模式是处理长列表或动态数据的首选和推荐方式。

其接受一个itemBuilder 回调函数来按需构建列表项,通过itemCount控制列表长度。回调函数需要传入两个参数,分别是构建 UI 上下文 BuilderContext 和 当前组件下标 index。每次构建新表项时,都会调用 itemBuilder。

优势:按需构建,不会在初始化时将所有列表项都创建,而是根据用户的滚动行为动态地创建和销毁列表项。

ListView.separated

ListView.separated 模式相当于在 ListView.builder 的基础上,额外提供了构建分割线的能力。对于该构造方法,需要同时提供 itemBuilder、separatorBuilder、itemCount 三个属性。separatorBuilder 提供一个回调函数,用于构建分割线组件。

ListView.separated( itemBuilder: (BuildContext context, int i) { return Container( width: double.infinity, height: 80, alignment: Alignment.center, decoration: BoxDecoration(color: Colors.blue), child: Text( "第${i + 1}个", style: TextStyle(color: Colors.white, fontSize: 30), ), ); }, separatorBuilder: (BuildContext context, int i) { return Container( height: 10, width: double.infinity, color: Colors.pink, ); }, itemCount: 100, ),

GridView

用于创建二维可滚动网格布局的核心组件,可以通过 scrollDirection 属性设置滚动的方向。

GridView 提供多种构建方式,如:

  • GridView.count() - 基于固定列数的网格布局 (最常用)
  • GridView.entent() - 基于固定子项的最大宽度 / 高度的网格布局 (最常用)
  • GridView.builder() - 懒加载策略,用于网格项数量巨大或动态生成的情况,需要接收 gridDelegate 布局委托属性。gridDelegate 可接收的属性类型如下:
    • SliverGridDelegateWithFixedCrossAxisCount:固定列数
    • SliverGridDelegateWithFixedCrossAxisExtent:最大宽度
    • 在 GridView.builder 中,在 gridDelegate 中声明主轴间距和交叉轴间距。

同时 GridView 存在默认构造方式,但是写起来过于繁琐,通常不使用。

GridView.count()

通过该方法,可以构造固定列数网络。GridView.count 以列数为优先。指定网格列数后,Flutter自动计算列的宽度,在空间内均匀排列。要注意的是,当滚动方向发生变化时,网格中组件的大小会随着横 / 纵空间大小到的不同而发生变化。

GridView.count( // 修改滚动方向为横向 // 修改以后每个组件都会变大一点点, 因为固定空间放三个组件 // 而竖向比横向空间更大 scrollDirection: Axis.horizontal, padding: EdgeInsets.all(10), mainAxisSpacing: 10, crossAxisSpacing: 10, crossAxisCount: 3, children: List.generate(100, (index) { return Container( alignment: Alignment.center, decoration: BoxDecoration(color: Colors.blue), child: Text( "第${index + 1}个", style: TextStyle(color: Colors.white), ), ); }), ),

GridView.extent()

使用 GridView.extent 指定子项的最大宽度或高度。GridView.extent 通过 maxCrossAxisExtent 设置子项最大宽度 / 高度来计算横向或纵向有多少列。

GridView.extent( scrollDirection: Axis.vertical, // 由当前方向的最大宽度 / 高度决定该方向的组件数量 maxCrossAxisExtent: 200, mainAxisSpacing: 10, crossAxisSpacing: 10, padding: EdgeInsets.all(10), children: List.generate(100, (index) { return Container( alignment: Alignment.center, decoration: BoxDecoration(color: Colors.blue), child: Text( "第${index + 1}个", style: TextStyle(color: Colors.white), ), ); }), ),

GridView.builder()

使用 GridView.builder 实现动态长网络,该构造方式对组件懒加载,只渲染可见区域。使用时,需要接收布局委托 (通过列数 (类似 count ) 还是宽高 (类似 extent ) 进行网格限制),同时类似 ListView,传入 itemBuilder 构造函数和 itemCount。

在 GridView.builder 中,在 gridDelegate 布局属性中声明主轴间距和交叉轴间距。同时,还可以使用 childAspectRatio 控制子组件宽高比。

GridView.builder( padding: EdgeInsets.all(10), // 布局委托, 此时为固定列数模式 gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, mainAxisSpacing: 10, crossAxisSpacing: 10, childAspectRatio: 2, ), itemCount: 100, itemBuilder: (BuildContext buildContext, int index) { return Container( alignment: Alignment.center, decoration: BoxDecoration(color: Colors.blue), child: Text( "第${index + 1}个", style: TextStyle(color: Colors.white), ), ); }, ),

总结

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

http://www.jsqmd.com/news/1090602/

相关文章:

  • 【claude code实践】 写好第一条提示词:用清晰目标减少返工
  • 鸿蒙 ArkTS 实战:Study Seat Log 从状态建模到交互闭环完整解析
  • 安全组网建设怎么选
  • 终极指南:如何在Mac上禁用Turbo Boost以降低温度和风扇噪音
  • Burp Suite Repeater实战指南:HTTP请求精细调试与渗透测试技巧
  • 【RuoYi-Vue-Plus】源码探秘:OSS配置从数据库到Redis的缓存同步机制
  • MSP430 Timer_A定时器深度解析:从PWM生成到捕获比较实战
  • 推荐系统基础算法简介
  • Win11Debloat:免费快速的Windows系统优化终极方案
  • ChatGPT Plus订阅取消后仍扣费?:2024年Q2真实案例拆解——Stripe账单延迟同步、OpenAI后台状态不同步、第三方渠道(如微软商店)独立续费链路揭秘
  • 2026嵌入式培训机构怎么选?全国机构对比了7家之后,我为什么只推荐金橙智能
  • Embedding Model(嵌入模型)完整讲解:句子转向量全过程
  • Qt 铁甲阅读器-搜索
  • 魔兽世界玩家必备:免费API查询与智能宏生成工具完全指南
  • Go语言的sync.Map缓存使用
  • AI应用开发平台排行榜:企业选型必看指南
  • 深度解读阿里云百炼 HappyHorse 1.1 视频生成大模型——能力解析与 Python/Java 工程化接入实战
  • 从零搭建内网渗透靶场:VMware虚拟网络配置与域环境攻防实战
  • 6.Mysql锁机制与优化实践以及MVCC底层原理剖析
  • 本地离线批量 OCR 实战:证件、发票、铭牌一键提取结构化信息
  • 如何在Amlogic电视盒上安装Debian系统:2025年终极开源解决方案
  • 如何用AI瞄准助手Aimmy快速提升游戏水平:终极配置指南
  • 英雄联盟皮肤库终极指南:一站式获取所有官方皮肤与炫彩资源
  • 3分钟掌握Chrome画中画扩展:免费提升多任务效率的终极指南
  • 重塑硬件价值:OpenCore Legacy Patcher如何让老Mac重获新生
  • 惠普暗影精灵性能控制终极指南:OmenSuperHub开源工具完全解析
  • 大数据专业课难度高?挂科率到底什么水平?过来人告诉你!
  • Web3 漏洞复盘:Verus 跨链桥 1158 万美元“数据结构错位“事件
  • Plus 到底值不值 20 美金?
  • Android13文件访问权限重构:从MANAGE_EXTERNAL_STORAGE到细粒度媒体权限的实战解析