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

如何在Flutter中实现带连线的序号UI代码(附参考示意图)

Flutter 带连线序号效果UI实现代码

带连线序号UI参考效果图

实现思路

这个效果属于竖向步骤条组件,核心是通过堆叠布局同时渲染序号节点和节点间的连线,根据步骤所在位置控制首尾连线的显隐即可。

完整示例代码

import 'package:flutter/material.dart';

// 自定义步骤项数据模型
class StepItemData {
  final String title;
  final String content;
  final bool isCompleted;

  StepItemData({
    required this.title,
    required this.content,
    required this.isCompleted,
  });
}

class ConnectedNumberStep extends StatelessWidget {
  final List<StepItemData> steps;
  const ConnectedNumberStep({super.key, required this.steps});

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      padding: const EdgeInsets.all(16),
      shrinkWrap: true,
      itemCount: steps.length,
      itemBuilder: (context, index) {
        final step = steps[index];
        final isFirst = index == 0;
        final isLast = index == steps.length - 1;
        final primaryColor = step.isCompleted ? Colors.green : Colors.grey.shade300;
        final textColor = step.isCompleted ? Colors.white : Colors.grey.shade600;

        return Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 左侧序号+连线区域
            SizedBox(
              width: 40,
              child: Stack(
                alignment: Alignment.topCenter,
                children: [
                  // 上连线:非首项显示
                  if (!isFirst)
                    Positioned(
                      top: 0,
                      child: Container(
                        width: 2,
                        height: 12,
                        color: primaryColor,
                      ),
                    ),
                  // 序号圆点
                  Container(
                    margin: const EdgeInsets.only(top: 12),
                    width: 24,
                    height: 24,
                    decoration: BoxDecoration(
                      color: step.isCompleted ? Colors.green : Colors.white,
                      border: Border.all(color: primaryColor, width: 2),
                      shape: BoxShape.circle,
                    ),
                    child: Center(
                      child: Text(
                        '${index + 1}',
                        style: TextStyle(
                          color: textColor,
                          fontSize: 12,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ),
                  ),
                  // 下连线:非末项显示
                  if (!isLast)
                    Positioned(
                      top: 36,
                      bottom: 0,
                      child: Container(
                        width: 2,
                        color: primaryColor,
                      ),
                    ),
                ],
              ),
            ),
            const SizedBox(width: 12),
            // 右侧内容区域
            Expanded(
              child: Container(
                margin: const EdgeInsets.only(bottom: 32),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      step.title,
                      style: const TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const SizedBox(height: 4),
                    Text(
                      step.content,
                      style: TextStyle(
                        fontSize: 14,
                        color: Colors.grey.shade600,
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ],
        );
      },
    );
  }
}

// 调用示例
void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('带连线序号效果')),
        body: ConnectedNumberStep(
          steps: [
            StepItemData(
              title: '注册账号',
              content: '填写手机号完成账号注册与实名认证',
              isCompleted: true,
            ),
            StepItemData(
              title: '信息填写',
              content: '完善个人基础信息与收货地址',
              isCompleted: true,
            ),
            StepItemData(
              title: '提交审核',
              content: '提交申请等待平台人工审核',
              isCompleted: false,
            ),
            StepItemData(
              title: '审核完成',
              content: '审核通过后即可正常使用全部功能',
              isCompleted: false,
            ),
          ],
        ),
      ),
    );
  }
}

自定义调整说明

  • 你可以直接修改颜色、圆点大小、连线粗细、内容边距等参数匹配你的设计稿
  • 如果需要对已完成步骤显示对勾替换序号,只需要修改序号圆点内部的Text组件为Icon组件即可
  • 针对横向的步骤条需求,只需要把布局方向从Row改成Column,连线从竖向改成横向即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 19:15:01