Flutter:步骤条组件

发布于:2025-06-15 ⋅ 阅读:(18) ⋅ 点赞:(0)

在这里插入图片描述

组件封装

import 'package:flutter/material.dart';

class SubscribeStepWidget extends StatelessWidget {
  final List<Map<String, dynamic>> steps;
  final int current;
  final Axis axis;
  final Color? themeColor;

  const SubscribeStepWidget({
    Key? key,
    required this.steps,
    required this.current,
    this.axis = Axis.vertical, // 默认竖向
    this.themeColor,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    if (axis == Axis.horizontal) {
      // 横向略
      return Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: _buildHorizontalSteps(),
      );
    }
    // 竖向
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: _buildVerticalSteps(context),
    );
  }

  List<Widget> _buildVerticalSteps(BuildContext context) {
    final Color mainColor = themeColor ?? Colors.blue;
    List<Widget> widgets = [];
    for (int i = 0; i < steps.length; i++) {
      final step = steps[i];
      final isActive = i + 1 == current;
      final isFinished = i + 1 < current;

      widgets.add(
        IntrinsicHeight(
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // 步骤圆圈和竖线
              Column(
                children: [
                  Container(
                    width: 20,
                    height: 20,
                    alignment: Alignment.center,
                    decoration: BoxDecoration(
                      color: isActive
                          ? mainColor
                          : isFinished
                              ? mainColor.withOpacity(0.3)
                              : Colors.white,
                      border: Border.all(
                        color: isActive
                            ? mainColor
                            : isFinished
                                ? mainColor.withOpacity(0.3)
                                : Colors.grey,
                        width: 2,
                      ),
                      shape: BoxShape.circle,
                    ),
                    child: Center(
                      child: isFinished
                          ? Icon(Icons.check, size: 16, color: Colors.white)
                          : Text(
                              '${step['index']}',
                              style: TextStyle(
                                color: isActive
                                    ? Colors.white
                                    : isFinished
                                        ? Colors.white
                                        : Colors.grey,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                    ),
                  ),
                  // 竖线自适应
                  if (i != steps.length - 1)
                    Expanded(
                      child: Container(
                        width: 2,
                        color: isFinished || isActive
                            ? mainColor.withOpacity(0.3)
                            : Colors.grey[300],
                      ),
                    ),
                ],
              ),
              const SizedBox(width: 12),
              // 标题和内容
              Expanded(
                child: Container(
                  padding: const EdgeInsets.only(bottom: 20),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        step['title'] ?? '',
                        style: TextStyle(
                          fontSize: 16,
                          fontWeight: isActive ? FontWeight.bold : FontWeight.normal,
                          color: isActive
                              ? mainColor
                              : Colors.black87,
                        ),
                      ),
                      if (step['desc'] != null)
                        Padding(
                          padding: const EdgeInsets.only(top: 4, bottom: 8),
                          child: Text(
                            step['desc'],
                            style: TextStyle(
                              fontSize: 14,
                              color: Colors.grey[600],
                            ),
                            maxLines: 2,
                            overflow: TextOverflow.ellipsis,
                          ),
                        ),
                      if (step['time'] != null)
                        Text(
                          step['time'],
                          style: TextStyle(
                            fontSize: 12,
                            color: Colors.grey[400],
                          ),
                        ),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
      );
    }
    return widgets;
  }

  // 横向略(如需可补充)
  List<Widget> _buildHorizontalSteps() => [];
}

调用

  // 当前周期
  int current = 2;
  List<Map<String, dynamic>> timeList = [
    {
      'index': 1,
      'title': '项目预热',
      'desc': '阶段1简介',
      'time': '2025.03.20 22:25:26',
    },
    {
      'index': 2,
      'title': '开始申购',
      'desc': '阶段2简介',
      'time': '2025.03.20 22:25:26',
    },
    {
      'index': 3,
      'title': '结束申购',
      'desc': '阶段3简介',
      'time': '2025.03.20 22:25:26',
    },
    {
      'index': 4,
      'title': '公布结果',
      'desc': '阶段4简介',
      'time': '2025.03.20 22:25:26',
    },
  ];

SubscribeStepWidget(
  steps: controller.timeList,
  current: controller.current,
  axis: Axis.vertical, // 或 Axis.vertical
  themeColor: AppTheme.colorGreen,
),

网站公告

今日签到

点亮在社区的每一天
去签到