解決Flutter Text下劃線 在Android上不對(duì)齊的問題

我們一般給文字加下劃線是這樣加的

const Text(
        text,
        style: TextStyle(
          decoration: TextDecoration.underline, // 添加下劃線
          decorationColor: Colors.black, // 設(shè)置下劃線顏色
          decorationThickness: 2, // 設(shè)置下劃線的粗細(xì)
        ),
      )
image.png

當(dāng)文字中有中文 英文的時(shí)候,在Android中顯示效果有些問題,下劃線沒有對(duì)齊。在iOS下到時(shí)沒有這個(gè)問題。

為此寫個(gè)簡單的Widget來解決這個(gè)小問題
multiline_underline_text.dart

import 'package:flutter/material.dart';

class MultilineUnderlineText extends StatelessWidget {
  final String text;
  final TextStyle? textStyle;
  final Color underlineColor;
  final double underlineThickness;
  final double? underlinePadding;
  final TextAlign textAlign;

  const MultilineUnderlineText({
    super.key,
    required this.text,
    this.textStyle,
    this.underlineColor = Colors.black,
    this.underlineThickness = 1.0,
    this.underlinePadding = 2.0,
    this.textAlign = TextAlign.left,
  });

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        return CustomPaint(
          painter: _UnderlinePainter(
            text: text,
            textStyle: textStyle ?? Theme.of(context).textTheme.bodyMedium!,
            underlineColor: underlineColor,
            underlineThickness: underlineThickness,
            underlinePadding: underlinePadding ?? 2.0,
            maxWidth: constraints.maxWidth,
            textAlign: textAlign,
          ),
          child: Text(
            text,
            style: textStyle,
            textAlign: textAlign,
          ),
        );
      },
    );
  }
}

class _UnderlinePainter extends CustomPainter {
  final String text;
  final TextStyle textStyle;
  final Color underlineColor;
  final double underlineThickness;
  final double underlinePadding;
  final double maxWidth;
  final TextAlign textAlign;

  _UnderlinePainter({
    required this.text,
    required this.textStyle,
    required this.underlineColor,
    required this.underlineThickness,
    required this.underlinePadding,
    required this.maxWidth,
    required this.textAlign,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final textPainter = TextPainter(
      text: TextSpan(text: text, style: textStyle),
      textDirection: TextDirection.ltr,
      textAlign: textAlign,
      maxLines: null,
    );

    textPainter.layout(maxWidth: maxWidth);
    
    final lineMetrics = textPainter.computeLineMetrics();
    
    final Paint paint = Paint()
      ..color = underlineColor
      ..strokeWidth = underlineThickness
      ..style = PaintingStyle.stroke;

    for (var line in lineMetrics) {
      double startX = 0;
      double width = line.width;
      
      // 處理文本對(duì)齊
      switch (textAlign) {
        case TextAlign.center:
          startX = (size.width - width) / 2;
          break;
        case TextAlign.right:
          startX = size.width - width;
          break;
        case TextAlign.left:
        default:
          startX = 0;
          break;
      }

      // 調(diào)整下劃線位置,考慮下延字母
      // 使用字體大小的比例來計(jì)算偏移量
      final fontSize = textStyle.fontSize ?? 14.0;
      final descenderOffset = fontSize * 0.2; // 增加偏移量以適應(yīng)下延字母
      final underlineY = line.baseline + underlinePadding + descenderOffset;

      canvas.drawLine(
        Offset(startX, underlineY),
        Offset(startX + width, underlineY),
        paint,
      );
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
} 

顯示效果:
Android


image.png

iOS


9a42fefc2e66c2069c4a4b6b4f8d59ea.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容