Flutter - 隐藏不应该显示的线

问题描述 投票:0回答:1

我正在尝试使用 Flutter 创建一个带有悬停动画的文本,其中前面有一个点。 该设计来自此网站(查看底部部分,您会发现我正在复制的内容)。

这是我的组件的代码:

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: ClipRRect(
        child: Container(
          alignment: Alignment.centerRight,
          width: widget.hasDot ? widget.width + 25 : widget.width,
          height: widget.underlineOffset + 2,
          // color: Colors.green,
          child: Stack(
            clipBehavior: Clip.none,
            children: [
              // Points (si il y en a un)
              if (widget.hasDot)
                const Positioned(
                  top: 9,
                  left: -26,
                  child: Icon(
                    Icons.circle,
                    color: Colors.black,
                    size: 10,
                  ),
                ),

              // Texte
              Stack(
                children: [
                  Text(
                    widget.text,
                    style: widget.textStyle.copyWith(
                      color: _colorAnimation.value,
                    ),
                  ),
                ],
              ),

              // Underline (onHover animation)
              Positioned(
                top: widget.underlineOffset,
                left: _underlineAnimation.value,
                child: Container(
                  width: widget.width,
                  height: 1,
                  color: Colors.orange,
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

一切正常,但是当我设置

hasDot: true
时,橙色线出现在点下方。

注意:我希望下划线动画仅出现在文本下方,而不是点下方。

我的问题是如何实现与

hasDot
false
时相同的动画效果,但包含点并且橙色线隐藏在点下。

其他信息:如果您需要 Flutter 项目的完整代码,请查看我的 GitHub 存储库

提前感谢您的帮助。

祝您编码愉快!

flutter animation clip flutter-clippath
1个回答
0
投票

更新: 在发布这个问题之前,我尝试了很多方法来完成这个任务,但没有成功。发布这个问题后,我在大约2秒内找到了解决方案...

因此,这是组件的完整代码,经过少量修改(基本上添加了一行以将点与其余所有部分分开):

import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:kanaknaturals_cursor/utilities/my_active_provider.dart';
import 'package:provider/provider.dart';

class MyText extends StatefulWidget {
  final int itemID;
  final String text;
  final TextStyle textStyle;
  final double width;
  final double underlineOffset;
  final bool hasDot;
  const MyText({
    Key key,
    required this.itemID,
    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);
        Provider.of<MyActiveProvider>(context, listen: false)
            .setActiveItem(widget.itemID);
      },
      onExit: (event) {
        _colorAnimationController.reverse();
        _underlineAnimationController.animateTo(1);
        Provider.of<MyActiveProvider>(context, listen: false)
            .setActiveItem(null);
      },
      cursor: SystemMouseCursors.click,
      child: Row(
        children: [
          // Points (if there is one)
          if (widget.hasDot)
            const Row(
              children: [
                Positioned(
                  top: 9,
                  left: -26,
                  child: Icon(
                    Icons.circle,
                    color: Colors.black,
                    size: 10,
                  ),
                ),
                Gap(10),
              ],
            ),
          ClipRRect(
            child: Container(
              alignment: Alignment.centerRight,
              width: widget.hasDot ? widget.width : widget.width,
              height: widget.underlineOffset + 2,
              // color: Colors.green,
              child: Stack(
                clipBehavior: Clip.none,
                children: [
                  // Text
                  Stack(
                    children: [
                      Text(
                        widget.text,
                        style: widget.textStyle.copyWith(
                          color: _colorAnimation.value,
                        ),
                      ),
                    ],
                  ),

                  // Underline (onHover animation)
                  Positioned(
                    top: widget.underlineOffset,
                    left: _underlineAnimation.value,
                    child: Container(
                      width: widget.width,
                      height: 1,
                      color: Colors.orange,
                    ),
                  )
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.