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

如何在Flutter中实现Dribbble上的连接式列表UI效果?

Flutter实现连接式列表样式方案

要实现你提到的这种带竖线连接的列表效果,核心是给每个列表项添加左侧的装饰元素(竖线+圆点),并根据列表项的位置调整线条显示逻辑。以下是具体实现方式:

核心思路

每个列表项左侧通过Column组合绘制圆点和竖线,根据项的位置区分显示逻辑:

  • 首项:仅显示下半段竖线+圆点
  • 中间项:显示上下两段竖线+圆点
  • 尾项:仅显示上半段竖线+圆点

代码实现

1. 自定义列表项组件

class ConnectedListItem extends StatelessWidget {
  final String title;
  final String subtitle;
  final double amount;
  final bool isFirst;
  final bool isLast;

  const ConnectedListItem({
    super.key,
    required this.title,
    required this.subtitle,
    required this.amount,
    required this.isFirst,
    required this.isLast,
  });

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
      child: Row(
        children: [
          // 左侧连接装饰
          _buildConnectionDecor(),
          const SizedBox(width: 16),
          // 右侧内容区
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(title, style: Theme.of(context).textTheme.titleMedium),
                const SizedBox(height: 4),
                Text(subtitle, style: Theme.of(context).textTheme.bodySmall?.copyWith(color: Colors.grey)),
              ],
            ),
          ),
          Text(
            amount >= 0 ? "+${amount.toStringAsFixed(2)}" : amount.toStringAsFixed(2),
            style: Theme.of(context).textTheme.titleMedium?.copyWith(
                  color: amount >= 0 ? Colors.green : Colors.red,
                ),
          ),
        ],
      ),
    );
  }

  Widget _buildConnectionDecor() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        // 上半段竖线,首项隐藏
        if (!isFirst)
          Container(width: 2, height: 20, color: Colors.grey.shade300),
        // 圆点
        Container(
          width: 12,
          height: 12,
          decoration: BoxDecoration(color: Colors.blue, borderRadius: BorderRadius.circular(6)),
        ),
        // 下半段竖线,尾项隐藏
        if (!isLast)
          Container(width: 2, height: 20, color: Colors.grey.shade300),
      ],
    );
  }
}

2. 构建完整列表

class ConnectedListPage extends StatelessWidget {
  final List<Map<String, dynamic>> transactions = [
    {"title": "Grocery Store", "subtitle": "Shopping", "amount": -45.20},
    {"title": "Salary", "subtitle": "Monthly Payment", "amount": 2500.00},
    {"title": "Subscription", "subtitle": "Streaming Service", "amount": -12.99},
    {"title": "Freelance Work", "subtitle": "Project Payment", "amount": 800.00},
  ];

  ConnectedListPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Transactions")),
      body: ListView.builder(
        itemCount: transactions.length,
        itemBuilder: (context, index) {
          final item = transactions[index];
          return ConnectedListItem(
            title: item["title"],
            subtitle: item["subtitle"],
            amount: item["amount"],
            isFirst: index == 0,
            isLast: index == transactions.length - 1,
          );
        },
      ),
    );
  }
}

样式自定义说明

  • 修改_buildConnectionDecor里的容器颜色、大小,可适配你的设计风格
  • 若需交互效果,可在ConnectedListItem外层包裹InkWell组件
  • 要添加动画,可将静态容器替换为AnimatedContainer

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 21:10:26