1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Flutter Web] マウスホバー時に展開されるアイコンボタンを作ってみる

Last updated at Posted at 2021-06-07

作ったモノ

マウスホバーによってラベルが表示されるアイコンボタンをイメージしました。
マウスホバー時なので、Flutter Web想定です。

AccordionIconButton.gif

実装

全ソース
class AccordionIconButton extends StatefulWidget {
  final IconData _iconData;
  final double _iconSize;
  final String _label;
  final double _maxWidth;
  final void Function()? _onTap;

  const AccordionIconButton(
      {Key? key,
      required IconData iconData,
      required double iconSize,
      required String label,
      required double maxWidth,
      void Function()? onTap})
      : _iconData = iconData,
        _iconSize = iconSize,
        _label = label,
        _maxWidth = maxWidth,
        _onTap = onTap,
        super(key: key);

  @override
  State<StatefulWidget> createState() => _State(width: this._iconSize);
}

class _State extends State<AccordionIconButton> {
  static const double INITIAL_OPACITY = 0.0;

  double opacity;
  double width;

  _State({
    required this.width,
  })  : opacity = INITIAL_OPACITY,
        super();

  @override
  Widget build(BuildContext context) {
    final Duration duration = Duration(milliseconds: 250);
    final Widget iconWidget = Icon(
      widget._iconData,
      size: widget._iconSize,
    );
    final Widget textWidget = Text(
      widget._label,
      softWrap: false,
      overflow: TextOverflow.fade,
    );

    return AnimatedContainer(
      constraints: BoxConstraints(maxWidth: widget._maxWidth),
      width: this.width,
      curve: Curves.easeIn,
      duration: duration,
      child: InkWell(
        borderRadius: BorderRadius.all(Radius.circular(10.0)),
        onHover: (isHover) {
          setState(() {
            if (isHover) {
              opacity = 1.0;
              width = double.infinity;
            } else {
              opacity = INITIAL_OPACITY;
              width = widget._iconSize;
            }
          });
        },
        onTap: widget._onTap,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            iconWidget,
            Flexible(
                child: AnimatedOpacity(
              curve: Curves.easeIn,
              duration: duration,
              opacity: this.opacity,
              child: textWidget,
            ))
          ],
        ),
      ),
    );
  }
}

Github

説明

非常にシンプルです。

マウスホバー判断 :mouse_three_button:

InkWellクラスのonHover(bool)で検知出来ます。
ホバー状態を判断して全体の幅テキスト項目の透明度を変更しているだけです。

その他にもMouseRegionクラス等でもマウスの判定は可能です。
(こちらはマウスカーソルの位置等まで追跡可能)

      InkWell(
        onHover: (isHover) {
          setState(() {
            if (isHover) {
              opacity = 1.0;
              width = double.infinity;
            } else {
              opacity = INITIAL_OPACITY;
              width = widget._iconSize;
            }
          });
        },
	    ...
	  )

アニメ―ション表示 :film_frames:

Animated系ウィジェットを使用して実現しています。
詳しい解説は公式やこちらのサイトが非常に参考になります。

AnimatedContainer(
      constraints: BoxConstraints(maxWidth: widget._maxWidth),
      width: this.width, // ←widthが変更された際に指定されたアニメーションでWidgetが変化する
      curve: Curves.easeIn,
      duration: duration,
	  ...
)

まとめ

**たのしい!!!(KONAMI感)**😊

少し触った程度ですがマウス操作の検知等モバイル以外の用途でも使いやすいライブラリがそろってる印象でした。

コピペ出来なかったり、ホイールクリックが効かなかったり等まだまだありますが、
FlutterWebでも色々作っていきたくなりますね!

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?