Blog スタッフブログ

Flutter システム開発 ひとくちコードスニペット

[Flutter]ロード中にUI操作をブロックするAbsorbPointerのコードスニペット

こんにちは、株式会社MIXシステム開発担当のBloomです。

今回はFlutterで利用できるAbsorbPointerの利用例についてのコードスニペットを紹介します。

AbsorbPointerを利用することで、なんらかのフラグが立っている時に触らせたくないUI部品への操作を吸収しブロックすることができます。実際にサンプルを見てみましょう。

class AbsorbPointerDemoPage extends StatefulWidget {
  const AbsorbPointerDemoPage({super.key});

  @override
  State<AbsorbPointerDemoPage> createState() => _AbsorbPointerDemoPageState();
}

class _AbsorbPointerDemoPageState extends State<AbsorbPointerDemoPage> {
  bool _isLoading = false;
  int _tapCount = 0;
  String _status = '待機中';

  Future<void> _startFakeLoading() async {
    if (_isLoading) return;

    setState(() {
      _isLoading = true;
      _status = 'ロード中(操作不能)';
    });

    await Future<void>.delayed(const Duration(seconds: 2));

    if (!mounted) return;
    setState(() {
      _isLoading = false;
      _status = '完了(操作可能)';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('AbsorbPointer demo')),
      body: Stack(
        children: [
          Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('状態: $_status', style: const TextStyle(fontSize: 18)),
                const SizedBox(height: 8),
                Text('タップ回数: $_tapCount', style: const TextStyle(fontSize: 18)),
                const SizedBox(height: 24),

                // ローディング中に操作を吸収したいUIをAbsorbPointerのchildにする
                AbsorbPointer(
                  absorbing: _isLoading,
                  child: Opacity(
                    opacity: _isLoading ? 0.6 : 1.0,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        FilledButton(
                          onPressed: _startFakeLoading,
                          child: const Text('ロード開始(2秒)'),
                        ),
                        const SizedBox(height: 12),
                        OutlinedButton(
                          onPressed: () {
                            setState(() => _tapCount++);
                          },
                          child: const Text('カウントアップ(ロード中操作不能)'),
                        ),
                        const SizedBox(height: 12),
                        TextField(
                          decoration: const InputDecoration(
                            labelText: '入力欄(ロード中操作不能)',
                            border: OutlineInputBorder(),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

これだけでロード中にUIを操作不能にすることができました。良かったですね。