flutter:ListView,ListTitle和Divider

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? leadingtitle 的水平间距 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 变得更紧凑(小号字体 + 高度更低),

适合做紧凑的菜单或二级选项。

外层包一层 SizedBoxContainer

如果你想要完全控制大小,可以把 ListTile 包在 SizedBoxContainer 里:

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 的横线,会在父容器(比如 ListViewColumn)里占据整行宽度。

常用属性

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")),
  ],
);

×

喜欢就点赞,疼爱就打赏