Flutter中能否实现自定义样式的文本下划线?
在Flutter中实现自定义样式下划线
完全可以实现这类自定义下划线,Flutter的自定义绘制能力能满足这类需求,下面提供两种实用方案:
方案一:使用CustomPaint自定义绘制
通过自定义CustomPainter,可以精准控制下划线的样式、位置和文本排版:
class CustomUnderlineText extends StatelessWidget { final String text; final TextStyle style; final Color underlineColor1; final Color underlineColor2; final double underlineThickness1; final double underlineThickness2; final double underlineGap; const CustomUnderlineText({ super.key, required this.text, required this.style, this.underlineColor1 = Colors.black, this.underlineColor2 = Colors.grey, this.underlineThickness1 = 3, this.underlineThickness2 = 1, this.underlineGap = 2, }); @override Widget build(BuildContext context) { return CustomPaint( painter: _CustomUnderlinePainter( text: text, style: style, underlineColor1: underlineColor1, underlineColor2: underlineColor2, underlineThickness1: underlineThickness1, underlineThickness2: underlineThickness2, underlineGap: underlineGap, ), child: Text(text, style: style), ); } } class _CustomUnderlinePainter extends CustomPainter { final String text; final TextStyle style; final Color underlineColor1; final Color underlineColor2; final double underlineThickness1; final double underlineThickness2; final double underlineGap; _CustomUnderlinePainter({ required this.text, required this.style, required this.underlineColor1, required this.underlineColor2, required this.underlineThickness1, required this.underlineThickness2, required this.underlineGap, }); @override void paint(Canvas canvas, Size size) { // 计算文本宽度与基线位置 final textPainter = TextPainter( text: TextSpan(text: text, style: style), textDirection: TextDirection.ltr, )..layout(minWidth: 0, maxWidth: size.width); final lineMetrics = textPainter.computeLineMetrics().first; final textBottom = lineMetrics.baseline + lineMetrics.descent; // 绘制第一条下划线(粗线) final paint1 = Paint() ..color = underlineColor1 ..style = PaintingStyle.fill; canvas.drawRect( Rect.fromLTWH( 0, textBottom + underlineGap, textPainter.width, underlineThickness1, ), paint1, ); // 绘制第二条下划线(细线) final paint2 = Paint() ..color = underlineColor2 ..style = PaintingStyle.fill; canvas.drawRect( Rect.fromLTWH( 0, textBottom + underlineGap * 2 + underlineThickness1, textPainter.width, underlineThickness2, ), paint2, ); } @override bool shouldRepaint(covariant _CustomUnderlinePainter oldDelegate) { return text != oldDelegate.text || style != oldDelegate.style || underlineColor1 != oldDelegate.underlineColor1 || underlineColor2 != oldDelegate.underlineColor2 || underlineThickness1 != oldDelegate.underlineThickness1 || underlineThickness2 != oldDelegate.underlineThickness2 || underlineGap != oldDelegate.underlineGap; } }
使用方式:
CustomUnderlineText( text: "自定义下划线示例", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), underlineColor1: Colors.blue, underlineColor2: Colors.lightBlue, )
方案二:使用Stack组合文本与自定义线条
如果觉得自定义绘制太复杂,也可以用Stack将文本和两条Container线条组合,通过定位实现效果:
Widget customUnderlineText(String text) { return LayoutBuilder( builder: (context, constraints) { // 先获取文本实际宽度 final textPainter = TextPainter( text: TextSpan(text: text, style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), textDirection: TextDirection.ltr, )..layout(maxWidth: constraints.maxWidth); return Stack( alignment: Alignment.bottomLeft, children: [ Text( text, style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), Positioned( bottom: -8, child: Column( children: [ Container( width: textPainter.width, height: 3, color: Colors.blue, ), SizedBox(height: 2), Container( width: textPainter.width, height: 1, color: Colors.lightBlue, ), ], ), ), ], ); }, ); }
内容的提问来源于stack exchange,提问作者Shagun arora
相关产品推荐
相关产品推荐

