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

Flutter中实现多用户对应垂直渐变侧边色条的方法咨询

实现多用户时Container左侧垂直区域的多色分割显示

我当前有一个带侧边边框和颜色的Container,通过BoxDecoration的stops属性实现了单用户的左侧垂直色条效果。现在需要优化:当预约对应多个用户时,左侧垂直区域按用户数量均等分割,显示不同用户的对应颜色。

现有代码

Container(
      // margin: EdgeInsets.symmetric(horizontal: 15, vertical: 10)
      margin: StaticData.isTablet
          ? EdgeInsets.only(left: 80, right: 80, top: 15, bottom: 10)
          : EdgeInsets.only(top: 10, left: 15, right: 15, bottom: 2),
      padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
      decoration: BoxDecoration(
        border: Border.all(
          width: 1.5,
          color: Colors.grey.withOpacity(0.1),
        ),
        gradient: appointmentModel.apptUsersModel != null
            ? LinearGradient(stops: [
                0.02,
                0.02
              ], colors: [
                Color(int.tryParse("0xFF" +
                    (appointmentModel.apptUsersModel!.first!.color
                            ?.split("#")
                            .last ??
                        ""))!),
                Colors.white
              ])
            : LinearGradient(
                stops: [0.02, 0.02], colors: [Colors.white, Colors.white]),
        boxShadow: [
          BoxShadow(
            color: Colors.grey,
            blurRadius: 5,
          ),
        ],
        borderRadius: BorderRadius.circular(5),
        color: Colors.white,
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.start,
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
          _todayAppointmentCardTableView(appointmentModel),
          Visibility(
            visible: widget.homeBloc!.professionalUserTypeId != null &&
                    widget.homeBloc!.professionalUserTypeId == 4
                ? false
                : true,
            child: Divider(
              thickness: 1,
            ),
          ),
          Visibility(
              visible: widget.homeBloc!.professionalUserTypeId != null &&
                      widget.homeBloc!.professionalUserTypeId == 4
                  ? false
                  : true,
              child: _todayActionListWidgets(appointmentModel)),
        ],
      ));

解决方案

推荐使用Stack拆分主容器和左侧色条的逻辑,这样更直观可控,具体实现步骤如下:

1. 封装用户颜色解析工具方法

避免重复代码,同时处理空值情况:

Color parseUserColor(String? colorStr) {
  if (colorStr == null || colorStr.isEmpty) return Colors.grey;
  final hexCode = colorStr.startsWith('#') ? colorStr.substring(1) : colorStr;
  return Color(int.parse('0xFF$hexCode'));
}

2. 生成多色渐变的参数

根据用户列表生成对应颜色数组和渐变停止点数组:

final userList = appointmentModel.apptUsersModel ?? [];
final userCount = userList.length;

// 生成用户颜色数组
final stripeColors = userList.map((user) => parseUserColor(user.color)).toList();

// 生成垂直渐变的停止点(均等分割高度)
final stripeStops = <double>[];
for (int i = 0; i <= userCount; i++) {
  stripeStops.add(i / userCount);
}

3. 用Stack重构Container

将主容器和左侧多色条分层,避免原渐变逻辑的冲突:

Stack(
  children: [
    // 原主容器(移除用户色渐变逻辑,保留基础样式)
    Container(
      margin: StaticData.isTablet
          ? EdgeInsets.only(left: 80, right: 80, top: 15, bottom: 10)
          : EdgeInsets.only(top: 10, left: 15, right: 15, bottom: 2),
      padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
      decoration: BoxDecoration(
        border: Border.all(
          width: 1.5,
          color: Colors.grey.withOpacity(0.1),
        ),
        boxShadow: const [
          BoxShadow(
            color: Colors.grey,
            blurRadius: 5,
          ),
        ],
        borderRadius: BorderRadius.circular(5),
        color: Colors.white,
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
          _todayAppointmentCardTableView(appointmentModel),
          Visibility(
            visible: widget.homeBloc?.professionalUserTypeId != 4,
            child: const Divider(thickness: 1),
          ),
          Visibility(
            visible: widget.homeBloc?.professionalUserTypeId != 4,
            child: _todayActionListWidgets(appointmentModel),
          ),
        ],
      ),
    ),
    // 左侧多色垂直条
    if (userCount > 0)
      Positioned(
        // 和主容器的margin对齐,保证位置准确
        left: StaticData.isTablet ? 80 : 15,
        top: StaticData.isTablet ? 15 : 10,
        bottom: StaticData.isTablet ? 10 : 2,
        width: 3, // 固定宽度,替代原百分比方式,视觉更稳定
        child: Container(
          decoration: BoxDecoration(
            borderRadius: const BorderRadius.only(
              topLeft: Radius.circular(5),
              bottomLeft: Radius.circular(5),
            ),
            gradient: LinearGradient(
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
              stops: stripeStops,
              colors: stripeColors,
            ),
          ),
        ),
      ),
  ],
)

方案说明

  • 拆分逻辑后,主容器负责基础样式和内容,左侧色条单独处理多色渐变,代码更易维护
  • 用Positioned精确定位色条,和主容器margin完全对齐,避免偏移
  • 垂直渐变按用户数量均等分割高度,每个用户颜色占比一致
  • 优化了原代码中的空安全判断,减少强制解包风险

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:34:55