You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现ListView Builder中列表项置顶功能(类WhatsApp/Telegram聊天置顶)

实现ListView Builder置顶列表项功能

1. 定义带置顶标记的数据模型

给列表项添加isPinned字段,用来标记是否需要置顶:

class ChatItem {
  final String id;
  final String title;
  final String lastMessage;
  bool isPinned; // 置顶状态标记

  ChatItem({
    required this.id,
    required this.title,
    required this.lastMessage,
    this.isPinned = false,
  });
}

2. 处理数据源排序逻辑

维护列表数据时,通过排序将置顶项固定在列表最前端:

List<ChatItem> _chatList = [
  ChatItem(id: '1', title: '工作群', lastMessage: '明天下午开会'),
  ChatItem(id: '2', title: '家人群', lastMessage: '周末聚餐'),
  ChatItem(id: '3', title: '朋友小李', lastMessage: '晚上打球吗?'),
];

// 排序方法:置顶项优先排在前面,非置顶项按原有顺序或其他规则排列
void _sortChatList() {
  _chatList.sort((a, b) {
    if (a.isPinned && !b.isPinned) return -1;
    if (!a.isPinned && b.isPinned) return 1;
    return 0; // 非置顶项保持原顺序
  });
  setState(() {}); // 触发UI更新
}

3. 用ListView Builder构建列表

拆分置顶/非置顶数据,分区域渲染列表项:

@override
Widget build(BuildContext context) {
  final pinnedItems = _chatList.where((item) => item.isPinned).toList();
  final unpinnedItems = _chatList.where((item) => !item.isPinned).toList();

  return ListView.builder(
    itemCount: pinnedItems.length + unpinnedItems.length,
    itemBuilder: (context, index) {
      ChatItem item;
      if (index < pinnedItems.length) {
        item = pinnedItems[index];
      } else {
        item = unpinnedItems[index - pinnedItems.length];
      }

      return ListTile(
        title: Text(item.title),
        subtitle: Text(item.lastMessage),
        trailing: IconButton(
          icon: Icon(item.isPinned ? Icons.push_pin : Icons.push_pin_outlined),
          onPressed: () {
            setState(() => item.isPinned = !item.isPinned);
            _sortChatList(); // 切换状态后重新排序
          },
        ),
      );
    },
  );
}

4. 可选优化细节

  • 添加区域分隔:如果需要明确区分置顶和普通列表区域,可以在非置顶项前添加标题分隔栏,注意调整itemCount:
itemCount: pinnedItems.length + unpinnedItems.length + (pinnedItems.isNotEmpty ? 1 : 0),

// 在itemBuilder中添加判断
if (index == pinnedItems.length) {
  return const ListTile(
    title: Text(
      '最近聊天',
      style: TextStyle(fontWeight: FontWeight.bold, color: Colors.grey),
    ),
  );
}
  • 持久化置顶状态:若需要重启APP后保留置顶设置,可将isPinned字段存入本地存储(如SharedPreferences或SQLite),初始化时读取数据并执行排序。

内容的提问来源于stack exchange,提问作者user21055008

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 09:47:03