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

Flutter中如何在ListView列表项之间绘制带圆点连接的竖线

Flutter 列表项带圆点连接竖线实现方案

核心实现思路是给每个列表项左侧独立封装时间线指示器组件,通过控制圆点和上下竖线的显式/样式,匹配预订状态展示需求。


步骤1:定义列表项数据结构

增加预订状态标记位用于控制指示器样式:

class BookingItem {
  final String content;
  final bool isBooked;
  BookingItem({required this.content, required this.isBooked});
}

步骤2:封装时间线指示器组件

组件内部处理首项/尾项的竖线截断逻辑,以及预订状态的样式切换:

class TimelineDot extends StatelessWidget {
  // 是否是列表第一个项
  final bool isFirst;
  // 是否是列表最后一个项
  final bool isLast;
  // 当前项是否已预订
  final bool isBooked;
  const TimelineDot({
    super.key,
    required this.isFirst,
    required this.isLast,
    required this.isBooked,
  });

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 24,
      child: Stack(
        alignment: Alignment.center,
        children: [
          // 上半段连接竖线:非首项时显示
          if (!isFirst)
            Positioned(
              top: 0,
              child: Container(
                width: 2,
                height: 12,
                color: isBooked ? Colors.green : Colors.grey.shade300,
              ),
            ),
          // 下半段连接竖线:非尾项时显示
          if (!isLast)
            Positioned(
              bottom: 0,
              child: Container(
                width: 2,
                height: 12,
                color: isBooked ? Colors.green : Colors.grey.shade300,
              ),
            ),
          // 中心圆点
          Container(
            width: 12,
            height: 12,
            decoration: BoxDecoration(
              shape: BoxShape.circle,
              color: isBooked ? Colors.green : Colors.grey.shade300,
              border: Border.all(color: Colors.white, width: 2),
            ),
          )
        ],
      ),
    );
  }
}

步骤3:和ListView结合使用

class BookingTimelineList extends StatelessWidget {
  final List<BookingItem> itemList;
  const BookingTimelineList({super.key, required this.itemList});

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      padding: const EdgeInsets.all(16),
      itemCount: itemList.length,
      itemBuilder: (context, index) {
        final currentItem = itemList[index];
        return Padding(
          padding: const EdgeInsets.symmetric(vertical: 8),
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              TimelineDot(
                isFirst: index == 0,
                isLast: index == itemList.length - 1,
                isBooked: currentItem.isBooked,
              ),
              const SizedBox(width: 12),
              Expanded(
                child: Container(
                  padding: const EdgeInsets.all(16),
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(8),
                    boxShadow: [
                      BoxShadow(
                        color: Colors.grey.shade200,
                        blurRadius: 4,
                        offset: const Offset(0, 2),
                      )
                    ],
                  ),
                  child: Text(currentItem.content),
                ),
              )
            ],
          ),
        );
      },
    );
  }
}

常见调整方案

  • 如果需要仅连续预订的项之间显示连接竖线,修改竖线显示条件即可:上半段竖线新增itemList[index-1].isBooked判断、下半段竖线新增itemList[index+1].isBooked判断
  • 列表项高度不固定时,把竖线的固定高度改为Expanded即可自适应填充上下区域
  • 圆点大小、竖线粗细、颜色样式均可根据需求直接修改对应参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 17:45:01