ListTitle
是什么
ListTitle
是 Flutter Material 库里提供的一个 widget。
主要用来在 列表 或 菜单 里展示一行内容。
内部已经帮你预留了常见的布局区域,比如:
- leading:左边的图标/头像
- title:标题文字(主信息)
- subtitle:副标题文字(次信息)
- trailing:右边的图标/按钮
所以你不用自己写 Row
+ Padding
+ Icon
+ Text
,直接一个 ListTile
搞定。
而且它自带 左右布局 和 水波纹点击效果
ListTitle的使用
基本使用
ListTile(
// 设置内容内边距
contentPadding: EdgeInsets.symmetric(vertical: 20.0),
leading: Icon(Icons.person), // 左边图标
title: Text("张三"), // 主标题
subtitle: Text("Flutter开发工程师"), // 副标题
trailing: Icon(Icons.arrow_forward), // 右边图标
onTap: () {
// 点击事件
print("点击了张三");
},
),

设置页
ListTile(
leading: Icon(Icons.settings),
title: Text("设置"),
trailing: Icon(Icons.chevron_right),
),

聊天记录
ListTile(
// CircleAvatar:圆形头像
leading: CircleAvatar(child: Text("A")),
title: Text("Alice"),
subtitle: Text("你好呀~"),
)

ListTile 属性
基础内容类属性
属性 | 类型 | 作用 | 示例 |
---|---|---|---|
leading | Widget? |
左侧图标/头像 | leading: Icon(Icons.person) |
title | Widget? |
主标题 | title: Text("用户名") |
subtitle | Widget? |
副标题 | subtitle: Text("账号信息") |
trailing | Widget? |
右侧图标/按钮 | trailing: Icon(Icons.chevron_right) |
交互类属性
属性 | 类型 | 作用 | 示例 |
---|---|---|---|
onTap | GestureTapCallback? |
点击事件 | onTap: () { print("点击了"); } |
onLongPress | GestureLongPressCallback? |
长按事件 | onLongPress: () => print("长按") |
enabled | bool |
是否可点击(默认 true) | enabled: false → 禁用点击效果 |
selected | bool |
是否选中 | selected: true → 高亮显示 |
样式控制类属性
属性 | 类型 | 作用 | 示例 |
---|---|---|---|
dense | bool? |
紧凑模式(更小间距) | dense: true |
isThreeLine | bool |
是否显示三行(title + subtitle + 额外内容) | isThreeLine: true |
visualDensity | VisualDensity |
控制视觉密度 | visualDensity: VisualDensity.compact |
contentPadding | EdgeInsetsGeometry? |
内边距 | contentPadding: EdgeInsets.all(8) |
shape | ShapeBorder? |
外形(圆角、边框等) | shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)) |
tileColor | Color? |
背景色 | tileColor: Colors.grey[200] |
selectedTileColor | Color? |
选中时背景色 | selectedTileColor: Colors.blue[100] |
排版类属性
属性 | 类型 | 作用 | 示例 |
---|---|---|---|
horizontalTitleGap | double? |
leading 与 title 的水平间距 |
horizontalTitleGap: 20 |
minLeadingWidth | double? |
leading 最小宽度 | minLeadingWidth: 40 |
minVerticalPadding | double? |
上下最小内边距 | minVerticalPadding: 10 |
ListTitle的大小
ListTile
本身是一个 固定高度 的组件,默认高度大概是 56dp(有副标题时会变成 72dp),并不会像 Container
那样可以随便改高度。但是有几种方式可以“间接控制”它的大小:
修改 contentPadding
(调整内边距)
contentPadding
只能改左右和上下内边距
上下 padding 变大时,ListTile
的高度就会被撑大
ListTile(
// 设置内容内边距
contentPadding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
tileColor: Colors.amber,
leading: Icon(Icons.home),
title: Text("首页: 设置了边距"),
),
ListTile(
tileColor: Colors.red,
leading: Icon(Icons.home),
title: Text("首页: 没有边距"),
),

用 dense: true
(让高度变小)
ListTile(
dense: true,
leading: Icon(Icons.person),
title: Text("联系人"),
)
dense: true
会让 ListTile
变得更紧凑(小号字体 + 高度更低),
适合做紧凑的菜单或二级选项。
外层包一层 SizedBox
或 Container
如果你想要完全控制大小,可以把 ListTile
包在 SizedBox
或 Container
里:
SizedBox(
height: 80, // 强制设置高度
child: ListTile(
leading: Icon(Icons.settings),
title: Text("设置"),
),
)
ListView
是什么
ListView
是 Flutter 提供的一个 可滚动的列表组件。
- 它继承自
BoxScrollView
- 常用来展示一组 垂直排列的子组件(比如新闻列表、菜单项、聊天记录等)。
- 如果子组件超出屏幕,用户可以 上下滑动 来查看。
简单来说:
👉 Column
是普通的竖直排布(不支持滚动)。
👉 ListView
= Column + 滚动能力
。
ListView 常用属性
数据与构建方式
属性 | 类型 | 作用 | 示例 |
---|---|---|---|
children | List<Widget> |
静态子组件列表 | children: [Text("A"), Text("B")] |
itemBuilder | IndexedWidgetBuilder |
按需构建子项(懒加载) | itemBuilder: (context, index) => Text("Item $index") |
itemCount | int? |
子项数量(结合 itemBuilder ) |
itemCount: 100 |
prototypeItem | Widget? |
用于估算高度(提升性能) | prototypeItem: ListTile(title: Text("样例")) |
滚动控制
属性 | 类型 | 作用 | 示例 |
---|---|---|---|
scrollDirection | Axis |
滚动方向(默认竖直) | scrollDirection: Axis.horizontal |
controller | ScrollController? |
滚动控制器 | controller: _scrollController |
physics | ScrollPhysics? |
滚动物理效果 | physics: BouncingScrollPhysics() |
shrinkWrap | bool |
根据内容自动收缩 | shrinkWrap: true |
reverse | bool |
是否反向滚动 | reverse: true |
布局与外观
属性 | 类型 | 作用 | 示例 |
---|---|---|---|
padding | EdgeInsetsGeometry? |
内边距 | padding: EdgeInsets.all(10) |
itemExtent | double? |
固定子项高度 | itemExtent: 60 |
cacheExtent | double? |
缓存区域大小(预加载) | cacheExtent: 200 |
addAutomaticKeepAlives | bool |
保持子项状态(默认 true) | addAutomaticKeepAlives: false |
addRepaintBoundaries | bool |
是否给子项加重绘边界(优化性能) | addRepaintBoundaries: false |
addSemanticIndexes | bool |
是否为子项加语义索引 | addSemanticIndexes: false |
性能与可访问性
属性 | 类型 | 作用 | 示例 |
---|---|---|---|
keyboardDismissBehavior | ScrollViewKeyboardDismissBehavior |
滚动时隐藏键盘 | keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag |
semanticChildCount | int? |
语义(辅助功能)子项数量 | semanticChildCount: 50 |
dragStartBehavior | DragStartBehavior |
拖动起始行为 | dragStartBehavior: DragStartBehavior.start |
最常见的用法
直接传一个 children
列表:
这种方式适合 列表项比较少、固定 的情况。
ListView(
children: [
ListTile(title: Text("Item 1")),
ListTile(title: Text("Item 2")),
ListTile(title: Text("Item 3")),
ListTile(title: Text("Item 4")),
//...........省略重复的代码..................
ListTile(title: Text("Item 26")),
ListTile(title: Text("Item 27")),
ListTile(title: Text("Item 28")),
ListTile(title: Text("Item 29")),
],
),

用 ListView.builder
如果列表项很多,甚至无限(比如聊天记录、朋友圈),就要用 惰性加载 的方式。这样 Flutter 会 按需创建 item,不会一次性渲染 100 个,性能更好。
Widget _buildBody3() {
// 假设我们有一组数据
final List<String> fruits = [
"Apple",
"Banana",
"Cherry",
"Durian",
"Grape",
"Mango",
];
return ListView.builder(
itemCount: fruits.length, // 告诉 ListView 一共有多少项
// itemBuilder 是一个回调函数,用于构建每一项
// 这个index是从0开始的
itemBuilder: (context, index) {
// 这里的 index 是 0,1,2,3... 一直递增
final fruitName = fruits[index]; // 用 index 取出对应的数据
return ListTile(
leading: CircleAvatar(child: Text("${index + 1}")), // 显示序号
title: Text(fruitName),
subtitle: Text("这是第 ${index + 1} 个水果"),
onTap: () {
debugPrint("点击了第 $index 项:$fruitName");
},
);
},
);
}
在 ListView.builder
里,这个 index
参数是 Flutter 自动传入的子项序号,从 0
开始,一直递增到 (itemCount - 1
)。

用 ListView.separated
ListView.separated
(和 builder 类似,但可以额外指定分隔组件)
separatorBuilder
:用来构建每两个子项之间的“分隔组件”。
使用 ListView.separated
的好处:不需要手动在 itemBuilder
里加 if (index != last)
这种逻辑来判断最后一个要不要加分割组件,Flutter 会自动帮你在元素之间插入分隔组件。
Widget _buildBody3() {
// 假设我们有一组数据
final List<String> fruits = [
"Apple",
"Banana",
"Cherry",
"Durian",
"Grape",
"Mango",
];
// return ListView.builder(
return ListView.separated(
itemCount: fruits.length, // 告诉 ListView 一共有多少项
// 分隔组件
separatorBuilder: (context, index) => Divider(),
// itemBuilder 是一个回调函数,用于构建每一项
// 这个index是从0开始的
itemBuilder: (context, index) {
// 这里的 index 是 0,1,2,3... 一直递增
final fruitName = fruits[index]; // 用 index 取出对应的数据
return ListTile(
leading: CircleAvatar(child: Text("${index + 1}")), // 显示序号
title: Text(fruitName),
subtitle: Text("这是第 ${index + 1} 个水果"),
onTap: () {
debugPrint("点击了第 $index 项:$fruitName");
},
);
},
);
}

Divider
Divider
是什么?
Divider
是 Flutter 提供的一个分割线组件,继承自 StatelessWidget
。它的作用就是在布局中画一条水平线,常用来分隔列表项、区块。
Divider()
:默认就是一条浅灰色、厚度 1px 的横线,会在父容器(比如 ListView
或 Column
)里占据整行宽度。
常用属性
Divider
提供了几个参数,方便你控制样式:
Divider(
height: 20, // 占用的总高度(线 + 上下间距)
thickness: 2, // 线条的实际粗细
color: Colors.blue, // 线条颜色
indent: 10, // 左边缩进
endIndent: 10, // 右边缩进
)
例如
ListView(
children: [
ListTile(title: Text("Item 1")),
Divider(), // 默认分隔线
ListTile(title: Text("Item 2")),
Divider(color: Colors.red, thickness: 10), // 红色粗线
ListTile(title: Text("Item 3")),
],
);
