作者:李俊才 (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', // 替换为你的新闻图片网络 URL
onDelete: () {
// 处理删除事件
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, // 使用网络图片 URL
width: 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 }
效果如图所示: