作者:李俊才 (jcLee95):https://blog.csdn.net/qq_28550263
邮箱 :291148484@163.com
本文地址:https://blog.csdn.net/qq_28550263/article/details/133411883
1. 功能描述
ListTile 组件表示一个包含一到三行文本的列表项,它可以选择带有图标或其它组件。
需要特别说明的是,虽然
ListTile
经常与ListView
一起使用,但它并不仅限于ListView
。实际上,可以在许多其他布局中使用ListTile
,以创建各种不同的用户界面元素。例如,可以将ListTile
放置在Column
、Row
、Card
等其他布局中,以创建自定义的列表项或卡片。
2. 主要属性
ListTile 组件有以下常用属性:
属性 | 描述 |
---|---|
leading | 列表项的前导部分,通常是一个图标或自定义小部件。 |
title | 列表项的主要标题文本。 |
subtitle | 列表项的副标题文本。 |
trailing | 列表项的尾部部分,通常包含右侧图标或控件。 |
isThreeLine | 布尔值,指示是否为三行列表项。如果为 true ,则可以显示额外的文本行。否则,只有一行文本。 |
dense | 布尔值,指示是否启用紧凑模式,紧凑模式下,文本和图标的大小将减小。 |
visualDensity | 控制布局紧凑性的视觉密度。 |
shape | 定义列表项的形状的形状对象。 |
style | 文本的样式。 |
selectedColor | 选定时的背景颜色。 |
iconColor | 图标的颜色。 |
textColor | 文本的颜色。 |
titleTextStyle | 标题文本的样式。 |
subtitleTextStyle | 副标题文本的样式。 |
leadingAndTrailingTextStyle | 前导和尾部部分文本的样式。 |
contentPadding | 内容的内边距。 |
enabled | 布尔值,指示列表项是否可用。如果为 false ,则列表项将不可点击。 |
onTap | 点击列表项时触发的回调函数。 |
onLongPress | 长按列表项时触发的回调函数。 |
onFocusChange | 获得或失去焦点时触发的回调函数。 |
mouseCursor | 指针悬停在列表项上时的鼠标指针样式。 |
selected | 布尔值,指示列表项是否已选择。 |
focusColor | 获取焦点时的背景颜色。 |
hoverColor | 鼠标悬停时的背景颜色。 |
splashColor | 点击列表项时的水波纹颜色。 |
focusNode | 用于处理焦点状态的 FocusNode 对象。 |
autofocus | 布尔值,指示列表项是否自动获取焦点。 |
tileColor | 列表项的背景颜色。 |
selectedTileColor | 选中列表项时的背景颜色。 |
enableFeedback | 是否启用触觉反馈。 |
horizontalTitleGap | 标题与前导/尾部之间的水平间距。 |
minVerticalPadding | 最小垂直内边距。 |
minLeadingWidth | 最小前导宽度。 |
titleAlignment | 标题文本的对齐方式。 |
3. ListTile的组成元素
-
前导部分(leading):通常是显示在
ListTile
左侧的部分,可以是一个图标(Icon
)、缩略图(Image
)或其他前导元素。 -
主标题(title):通常是
ListTile
的主要文本内容,显示在前导部分(如果有的话)的右侧,用于描述列表项的主要信息。 -
副标题(subtitle):可选项,显示在主标题下面,用于显示列表项的附加信息或次要信息。
-
尾部部分(trailing):通常是显示在
ListTile
右侧的部分,可以是一个图标(Icon
)、按钮或其他尾部元素。
这些是 ListTile
的基本组成部分,可以根据需要自定义和组合这些元素,以创建符合你设计需求的列表项。
4. 案例:一个简单的购物车UI
import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {return const MaterialApp(home: ShoppingCartScreen(),);}
}class ShoppingCartScreen extends StatelessWidget {const ShoppingCartScreen({super.key});Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('购物车'),),body: ListView.builder(itemCount: 9,itemBuilder: (context, index) {return ShoppingCartItem(productName: '商品$index',productDescription: '商品$index的一些描述',productQuantity: 1, // 产品数量productImageUrl:'https://gw.alicdn.com/bao/uploaded/i4/1711217080/O1CN018eotkR22Ah1q4eDcs_!!1711217080.jpg_300x300q90.jpg', // 替换为你的网络图片 URL);},),);}
}class ShoppingCartItem extends StatefulWidget {final String productName;final String productDescription;final int productQuantity;final String productImageUrl;const ShoppingCartItem({Key? key,required this.productName,required this.productDescription,required this.productQuantity,required this.productImageUrl,}) : super(key: key);State<ShoppingCartItem> createState() => _ShoppingCartItemState();
}class _ShoppingCartItemState extends State<ShoppingCartItem> {bool isChecked = false;Widget build(BuildContext context) {return Card(child: ListTile(leading: Checkbox(value: isChecked,onChanged: (value) {setState(() {isChecked = value!;});},),title: Text(widget.productName),subtitle: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [Text(widget.productDescription),Text('数量:${widget.productQuantity}'),],),trailing: Image.network(widget.productImageUrl,width: 50,height: 50,fit: BoxFit.cover,),),);}
}
效果如下:
5. 案例2:一个新闻列表
import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {return const MaterialApp(home: NewsListScreen(),);}
}class NewsListScreen extends StatefulWidget {const NewsListScreen({super.key});State<NewsListScreen> createState() => _NewsListScreenState();
}class _NewsListScreenState extends State<NewsListScreen> {List<String> newsList = List.generate(5, (index) => '新闻标题 $index');Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('新闻列表'), // 设置页面标题),body: ListView.builder(itemCount: newsList.length, // 使用列表的长度itemBuilder: (context, index) {return NewsListItem(headline: newsList[index], // 新闻标题description: '新闻描述 $index', // 新闻描述imageUrl:'https://pics6.baidu.com/feed/5ab5c9ea15ce36d3733d7035255cf48be950b132.jpeg@f_auto?token=29586d3d429228d0a2c251be0f9a8a67', // 替换为你的新闻图片网络 URLonDelete: () {// 处理删除事件setState(() {newsList.removeAt(index); // 移除对应索引的新闻标题});},);},),);}
}class NewsListItem extends StatelessWidget {final String headline;final String description;final String imageUrl;final VoidCallback onDelete;const NewsListItem({Key? key,required this.headline,required this.description,required this.imageUrl,required this.onDelete,}) : super(key: key);Widget build(BuildContext context) {return Card(child: ListTile(contentPadding: const EdgeInsets.all(16.0),leading: Image.network(imageUrl, // 使用网络图片 URLwidth: 80,height: 80,fit: BoxFit.cover,),title: Text(headline,style: const TextStyle(fontWeight: FontWeight.bold),),subtitle: Text(description),trailing: IconButton(icon: const Icon(Icons.delete),onPressed: onDelete, // 触发删除操作),onTap: () {// 处理点击事件,例如打开新闻详情页面// 这里可以添加你的代码逻辑},),);}
}
效果如下:
6. 案例3:模拟文件资源管理器页面
import 'package:flutter/material.dart';void main() {runApp(const FileExplorerApp());
}class FileExplorerApp extends StatelessWidget {const FileExplorerApp({super.key});Widget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: const Text('文件资源管理器'),),body: const FileExplorerUI(),),);}
}class FileExplorerUI extends StatefulWidget {const FileExplorerUI({super.key});State<FileExplorerUI> createState() => _FileExplorerUIState();
}class _FileExplorerUIState extends State<FileExplorerUI> {SortMode _sortMode = SortMode.name;Widget build(BuildContext context) {return Column(crossAxisAlignment: CrossAxisAlignment.stretch,children: [Row(mainAxisAlignment: MainAxisAlignment.end,children: [IconButton(icon: const Icon(Icons.view_list),onPressed: () {setState(() {});},),IconButton(icon: const Icon(Icons.view_module),onPressed: () {setState(() {});},),IconButton(icon: const Icon(Icons.view_headline),onPressed: () {setState(() {});},),DropdownButton<SortMode>(value: _sortMode,onChanged: (value) {setState(() {_sortMode = value!;});},items: SortMode.values.map<DropdownMenuItem<SortMode>>((mode) => DropdownMenuItem(value: mode,child: Text(mode.toString().split('.').last),),).toList(),),],),Expanded(child: ListView.builder(itemCount: 10, // 虚拟数据,实际根据文件列表长度设置itemBuilder: (context, index) {return ListTile(leading: const Icon(Icons.folder), // 根据文件类型设置图标title: Text('文件或文件夹 $index'), // 根据文件名称设置subtitle: const Text('文件大小: 1 KB'), // 根据文件大小设置trailing: const Text('修改日期: 2023-01-01'), // 根据修改日期设置);},),),],);}
}enum ViewMode { details, largeIcon, smallIcon }enum SortMode { name, size, type, date }
效果如图所示: