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

Flutter带前置点文本悬停优化:隐藏点下的橙色下划线

Flutter 带前置圆点文本悬停下划线动画问题解决

问题描述

用Flutter实现带前置圆点的文本悬停动画时,设置hasDot: true后橙色下划线会出现在圆点下方,需求是保留圆点的同时,让下划线仅在文本区域执行动画,隐藏圆点下方的线条。

解决方案

通过调整组件层级,将文本与下划线限制在独立的文本宽度容器内,并添加裁剪组件避免下划线溢出到圆点区域,修改后的代码如下:

import 'package:flutter/material.dart';

class MyText extends StatefulWidget {
  final String text;
  final TextStyle textStyle;
  final double width;
  final double underlineOffset;
  final bool hasDot;
  const MyText({
    super.key,
    required this.text,
    required this.textStyle,
    required this.width,
    required this.underlineOffset,
    this.hasDot = false,
  });

  @override
  State<MyText> createState() => _MyTextState();
}

class _MyTextState extends State<MyText> with TickerProviderStateMixin {
  late AnimationController _colorAnimationController;
  late Animation _colorAnimation;
  late AnimationController _underlineAnimationController;
  late Animation _underlineAnimation;

  @override
  void initState() {
    _colorAnimationController = AnimationController(
      duration: const Duration(milliseconds: 250),
      vsync: this,
    )..addListener(() {
        setState(() {});
      });
    _colorAnimation = ColorTween(
      begin: Colors.black,
      end: Colors.orange,
    ).animate(_colorAnimationController);
    _underlineAnimationController = AnimationController(
      duration: const Duration(milliseconds: 500),
      vsync: this,
    )..addListener(() {
        if (_underlineAnimationController.isCompleted &&
            _underlineAnimationController.value == 1) {
          _underlineAnimationController.reset();
        }
        setState(() {});
      });
    _underlineAnimation = Tween(begin: -widget.width, end: widget.width)
        .animate(_underlineAnimationController);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MouseRegion(
      onEnter: (event) {
        _colorAnimationController.forward();
        _underlineAnimationController.animateTo(0.5);
      },
      onExit: (event) {
        _colorAnimationController.reverse();
        _underlineAnimationController.animateTo(1);
      },
      cursor: SystemMouseCursors.click,
      child: Container(
        alignment: Alignment.centerRight,
        width: widget.hasDot ? widget.width + 25 : widget.width,
        height: widget.underlineOffset + 2,
        child: Stack(
          clipBehavior: Clip.none,
          children: [
            // 文本与下划线容器:限制在文本宽度内并裁剪溢出部分
            Align(
              alignment: Alignment.centerRight,
              child: ClipRect(
                child: Container(
                  width: widget.width,
                  height: widget.underlineOffset + 2,
                  child: Stack(
                    children: [
                      // 文本
                      Text(
                        widget.text,
                        style: widget.textStyle.copyWith(
                          color: _colorAnimation.value,
                        ),
                      ),
                      // 悬停下划线动画
                      Positioned(
                        top: widget.underlineOffset,
                        left: _underlineAnimation.value,
                        child: Container(
                          width: widget.width,
                          height: 1,
                          color: Colors.orange,
                        ),
                      )
                    ],
                  ),
                ),
              ),
            ),
            // 前置圆点
            if (widget.hasDot)
              const Positioned(
                top: 9,
                left: -26,
                child: Icon(
                  Icons.circle,
                  color: Colors.black,
                  size: 10,
                ),
              ),
          ],
        ),
      ),
    );
  }
}

修改说明

  • 拆分组件层级:将文本和下划线独立封装到宽度为widget.width的容器中,通过Align对齐到父容器右侧,让文本区域与圆点区域彻底分离。
  • 添加裁剪组件:使用ClipRect裁剪下划线超出文本宽度的部分,确保动画过程中线条仅显示在文本下方,不会延伸到圆点区域。
  • 保留原有动画逻辑:颜色切换和下划线滑动的动画逻辑保持不变,仅调整了组件的布局结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 22:45:03