Flutter如何实现带标签的多色水平分割线?新手求实现方案
Flutter 带标签多色水平分割线实现方案
方案1:组件组合实现(新手友好,易修改)
不需要复杂的自定义绘制逻辑,直接用Flutter自带组件组合即可实现,后续修改样式也很直观:
import 'package:flutter/material.dart'; class TaggedMultiColorDivider extends StatelessWidget { /// 中间显示的标签文本 final String label; /// 分割线高度 final double dividerHeight; /// 标签和左右分割线的间距 final double labelHorizontalPadding; /// 分割线颜色列表,按列表顺序排列分段 final List<Color> dividerSegmentColors; /// 标签文本样式 final TextStyle? labelStyle; const TaggedMultiColorDivider({ super.key, required this.label, this.dividerHeight = 2, this.labelHorizontalPadding = 12, required this.dividerSegmentColors, this.labelStyle, }); @override Widget build(BuildContext context) { return Row( children: [ // 左侧多色分割线 Expanded(child: _buildColorSegments()), // 中间标签 Padding( padding: EdgeInsets.symmetric(horizontal: labelHorizontalPadding), child: Text( label, style: labelStyle ?? const TextStyle(fontSize: 14, color: Colors.grey), ), ), // 右侧多色分割线 Expanded(child: _buildColorSegments()), ], ); } Widget _buildColorSegments() { return Row( children: dividerSegmentColors.map((color) { // 如果需要不等宽分段,把Expanded改成指定宽度的SizedBox即可 return Expanded( child: Container( height: dividerHeight, color: color, // 如需圆角分割线,放开下面的注释配置圆角即可 // decoration: BoxDecoration( // color: color, // borderRadius: BorderRadius.circular(2), // ), ), ); }).toList(), ); } } // 调用示例,直接放到页面布局的对应位置即可 // TaggedMultiColorDivider( // label: "OR", // dividerSegmentColors: [Colors.redAccent, Colors.blueAccent, Colors.greenAccent], // )
方案2:CustomPaint 实现(灵活度更高)
如果需要实现更复杂的效果,比如渐变、斜向分割、特殊形状分段,可以用自定义绘制的方案,性能更好:
import 'package:flutter/material.dart'; class CustomTaggedDivider extends StatelessWidget { final String label; final double dividerHeight; final List<Color> segmentColors; final TextStyle? labelStyle; const CustomTaggedDivider({ super.key, required this.label, required this.segmentColors, this.dividerHeight = 2, this.labelStyle, }); @override Widget build(BuildContext context) { return CustomPaint( painter: _DividerPainter( label: label, dividerHeight: dividerHeight, segmentColors: segmentColors, labelStyle: labelStyle ?? const TextStyle(fontSize: 14, color: Colors.grey), ), child: Container( padding: const EdgeInsets.symmetric(vertical: 8), alignment: Alignment.center, child: Text(label, style: labelStyle), ), ); } } class _DividerPainter extends CustomPainter { final String label; final double dividerHeight; final List<Color> segmentColors; final TextStyle labelStyle; _DividerPainter({ required this.label, required this.dividerHeight, required this.segmentColors, required this.labelStyle, }); @override void paint(Canvas canvas, Size size) { // 计算文本宽度,预留标签位置 final textPainter = TextPainter( text: TextSpan(text: label, style: labelStyle), textDirection: TextDirection.ltr, )..layout(); final textWidth = textPainter.width; const gap = 24.0; final singleSideDividerWidth = (size.width - textWidth - gap * 2) / 2; final singleSegmentWidth = singleSideDividerWidth / segmentColors.length; // 绘制左侧分割线 double offsetX = 0; for (var color in segmentColors) { final paint = Paint()..color = color; canvas.drawRect( Rect.fromLTWH(offsetX, size.height/2, singleSegmentWidth, dividerHeight), paint, ); offsetX += singleSegmentWidth; } // 绘制右侧分割线 offsetX = size.width - singleSideDividerWidth; for (var color in segmentColors) { final paint = Paint()..color = color; canvas.drawRect( Rect.fromLTWH(offsetX, size.height/2, singleSegmentWidth, dividerHeight), paint, ); offsetX += singleSegmentWidth; } } @override bool shouldRepaint(covariant _DividerPainter oldDelegate) { return label != oldDelegate.label || dividerHeight != oldDelegate.dividerHeight || segmentColors != oldDelegate.segmentColors || labelStyle != oldDelegate.labelStyle; } }
常用参数调整说明
- 调整
dividerHeight可以修改分割线的粗细 - 增删
dividerSegmentColors/segmentColors列表的元素,可以修改分割线的分段数量和对应颜色 - 修改
label参数即可更换中间显示的标签文本 - 配置
labelStyle可以调整标签的文字大小、颜色、字重等样式
内容的提问来源于stack exchange,提问作者Meng Cheng teoh
相关产品推荐
相关产品推荐

