0
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

【Flutter】Text Widgetのwidthを取得し、アニメーション付きでアンダーラインを表示する方法

アニメーション付きアンダーラインはAnimatedContainerで表現する。
Text Widgetのwidth取得方法はこちらを参考に実装。

header_menu_item.dart
class HeaderMenuItem extends StatefulWidget {
  final String text;
  final double fontSize = 16;

  const HeaderMenuItem({Key key, this.text}) : super(key: key);

  @override
  _HeaderMenuItemState createState() => _HeaderMenuItemState();
}

class _HeaderMenuItemState extends State<HeaderMenuItem> {
  double _opacity = 0;
  double _lineRatio = 0.5;

  @override
  Widget build(BuildContext context) {
    return MouseRegion(
      onEnter: (details) => _onEnterHandler(details, context),
      onExit: (details) => _onExitHandler(details, context),
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 30.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Expanded(
              child: Container(
                alignment: Alignment.center,
                child: Text(
                  widget.text,
                  style: TextStyle(
                    fontSize: widget.fontSize,
                    letterSpacing: 5,
                  ),
                ),
              ),
            ),
            AnimatedContainer(
              width: lineWidth(widget.text) * _lineRatio,
              height: 2,
              color: Colors.black.withOpacity(_opacity),
              curve: Curves.linear,
              duration: Duration(milliseconds: 200),
            ),
          ],
        ),
      ),
    );
  }

  // マウスホバー時
  void _onEnterHandler(PointerEvent details, BuildContext context) {
    setState(() {
      _lineRatio = 1;
      _opacity = 1;
    });
  }

  // マウスホバー解除時
  void _onExitHandler(PointerEvent details, BuildContext context) {
    setState(() {
      _lineRatio = 0.5;
      _opacity = 0;
    });
  }

  // TextWidgetのwidthを取得
  double lineWidth(String text) {
    var renderParagraph = RenderParagraph(
      TextSpan(
        text: text,
        style: TextStyle(
          fontSize: widget.fontSize,
          letterSpacing: 5,
        ),
      ),
      textDirection: TextDirection.ltr,
    )..layout(BoxConstraints(maxWidth: 200));

    return renderParagraph.getMinIntrinsicWidth(widget.fontSize);
  }
}

参考

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
0
Help us understand the problem. What are the problem?