在Flutter中如何创建随数值变化色彩浓度的水平条?
实现思路与代码示例
要实现根据数值改变色彩浓度的水平条,核心是将数值映射为颜色参数(饱和度、透明度等),再结合Flutter的布局或绘制组件落地,下面给两种实用方案:
方案一:用Container快速实现(适合简单场景)
通过计算输入数值的比例,动态调整颜色的饱和度或透明度,用嵌套Container实现进度条:
class ColorProgressBar extends StatelessWidget { final double value; // 传入的数值,比如0-100 final double maxValue; // 数值的最大值,默认100 final Color baseColor; // 基础颜色 const ColorProgressBar({ super.key, required this.value, this.maxValue = 100, this.baseColor = Colors.blue, }); @override Widget build(BuildContext context) { // 把数值转成0-1的比例,防止超出范围 final double ratio = (value / maxValue).clamp(0.0, 1.0); // 调整色彩饱和度(更贴合"色彩浓度"的视觉需求) final hsl = HSLColor.fromColor(baseColor); final Color dynamicColor = hsl.withSaturation(ratio).toColor(); // 也可以选择调整透明度实现浓度变化 // final Color dynamicColor = baseColor.withOpacity(ratio); return Container( height: 20, width: double.infinity, margin: const EdgeInsets.symmetric(horizontal: 20), decoration: BoxDecoration( color: Colors.grey.shade200, borderRadius: BorderRadius.circular(10), ), child: Align( alignment: Alignment.centerLeft, child: Container( width: ratio * (MediaQuery.of(context).size.width - 40), height: double.infinity, decoration: BoxDecoration( color: dynamicColor, borderRadius: BorderRadius.circular(10), ), ), ), ); } }
调用示例
// 传入数值70,显示70%浓度的进度条 ColorProgressBar(value: 70)
方案二:用CustomPaint自定义绘制(适合复杂需求)
如果需要更灵活的样式(比如精细的圆角控制、自定义过渡效果),可以用CustomPaint手动绘制:
class CustomColorBarPainter extends CustomPainter { final double value; final double maxValue; final Color baseColor; CustomColorBarPainter({ required this.value, this.maxValue = 100, this.baseColor = Colors.blue, }); @override void paint(Canvas canvas, Size size) { final ratio = (value / maxValue).clamp(0.0, 1.0); // 基于饱和度调整色彩浓度 final hsl = HSLColor.fromColor(baseColor); final dynamicColor = hsl.withSaturation(ratio).toColor(); // 绘制背景灰条 final bgPaint = Paint()..color = Colors.grey.shade200; canvas.drawRRect( RRect.fromRectAndRadius( Rect.fromLTWH(0, 0, size.width, size.height), const Radius.circular(10), ), bgPaint, ); // 绘制彩色进度条 final progressPaint = Paint()..color = dynamicColor; canvas.drawRRect( RRect.fromRectAndRadius( Rect.fromLTWH(0, 0, size.width * ratio, size.height), const Radius.circular(10), ), progressPaint, ); } @override bool shouldRepaint(CustomColorBarPainter oldDelegate) { return oldDelegate.value != value; } }
调用示例
CustomPaint( size: const Size(double.infinity, 20), painter: CustomColorBarPainter(value: 50), )
关键细节说明
- 数值映射:必须用
clamp(0.0,1.0)限制比例范围,避免数值超出最大值或小于0时出现布局异常; - 色彩浓度:优先用
HSLColor调整饱和度(saturation),比调整透明度更贴合"色彩浓度"的视觉定义; - 响应式适配:进度条宽度可以结合
MediaQuery适配不同屏幕,或直接用double.infinity配合父容器的约束。
内容的提问来源于stack exchange,提问作者Macdonald
相关产品推荐
相关产品推荐

