🙊

[Flutter]Hooksを使ってFloatingActionButtonの表示と非表示を切り替える

に公開

FloatingActionButtonの表示と非表示を切り替え

ListTileにボタンを配置したFloatingActionButton(以下fab)が邪魔で押せない!!Xのようにスクロールしたら非表示されるようにしたい!となったので調べたところ良い記事が見つからなかったのですがなかなか良い記事がなかったので古い記事を参考にHooksでやる方法を記述します。

Hooksで切り替え

HookWidgetHookConsumerWidgetで記述することを想定しています。
表示と非表示を切り替えるためにboolとscrollControllerを用意します。

/// 切り替えのbool値
final visible = useState(true);

 /// スクロールのコントローラ
final scrollController = useScrollController();

次にスクロールを検知するためにListViewSingleChildScrollViewの下にcontrollerを設定します。

ListView.builder(
        /// スクロールの状態を管理
        controller: scrollController,
        itemCount: 100,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text('Item $index'),
        );
    },
),

最後に表示と非表示を切り替えるためにfabに書き加えます。
今回はtrueの時になにも表示してほしくないので空のContainerを返すようにします。

floatingActionButton: visible.value
          ? FloatingActionButton(
              onPressed: () {},
              child: const Icon(Icons.add),
            )
          : Container(),

コード全体

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

class FabSamplePage extends HookWidget {
  const FabSamplePage({super.key});

  
  Widget build(BuildContext context) {
    /// 切り替えのbool値
    final visible = useState(true);

    /// スクロールのコントローラ
    final scrollController = useScrollController();

    /// スクロールのリスナー
    scrollController.addListener(() {
      if (scrollController.position.userScrollDirection ==
          ScrollDirection.forward) {
        /// 表示
        visible.value = true;
      } else {
        /// 非表示
        visible.value = false;
      }
    });
    return Scaffold(
      appBar: AppBar(
        title: const Text('Fab Sample'),
      ),
      body: ListView.builder(
        /// スクロールの状態を管理
        controller: scrollController,
        itemCount: 100,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text('Item $index'),
          );
        },
      ),
      floatingActionButton: visible.value
          ? FloatingActionButton(
              onPressed: () {},
              child: const Icon(Icons.add),
            )
            /// 空のコンテナ
          : Container(),
    );
  }
}

さいごに

今回はHooksでやりましたがStatefulWidgetでもsetStateで同じようなことができるようになると思います。
またこのまま実行するとアニメーションがなく寂しいのでアニメーションをつけたい旨をGPTにでも聞いて実装してみてください(笑)

スクリーンショット

Discussion