1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

アクセシビリティの知見を発信しよう!

【Flutter】ボタンの連打を無効にする対応メモ。onPressedの処理中は押せないボタンを作成する方法

Posted at

この記事でやりたいこと・紹介すること

ボタンを押した後の処理を実行中は、ボタンを押せないようにするボタンを作成して、ユーザーが連打や実行中に比較的短い時間内でボタンを再度タップする動作等をしても二重で処理が発生しないようにする

実施した概要

ボタンクラスのラッパークラスを作成して、処理中はボタンの"onPressed"パラメータにNullを渡すことでタップ動作を無効にする。

上記の実装をすることで、容易に連打防止対応をしたボタンをコード全体で簡単に何度も使用することができます。

実際の方法とソースコード

実際の導入方法を紹介します。

ボタンクラスのラッパークラスを作成

ボタンクラスのラッパークラスであるWaitableElevatedButtonクラスとWaitableOutlinedButtonクラスを作成

以下のファイルを任意の場所に作成します。

私は、基本的にUtilディレクトリ等を作成して、その配下に以下のwaitable_button.dartクラスを作成します。

waitable_button.dart

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class WaitableElevatedButton extends StatefulWidget {

  WaitableElevatedButton({
    required this.onPressed,
    required this.child,
    this.style,
    super.key,
  });
  @override
  createState() => _WaitableElevatedButtonState();

  final AsyncCallback? onPressed;
  final ButtonStyle? style;
  final Widget child;
}

class _WaitableElevatedButtonState extends State<WaitableElevatedButton> {
  bool _waiting = false;

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      style: widget.style,
      onPressed: widget.onPressed == null || _waiting
          ? null
          : () async {
        setState(() => _waiting = true);
        await widget.onPressed!();
        setState(() => _waiting = false);
      },
      child: widget.child,
    );
  }
}

class WaitableOutlinedButton extends StatefulWidget {

  WaitableOutlinedButton({
    required this.onPressed,
    required this.child,
    this.style,
    super.key,
  });
  @override
  createState() => _WaitableOutlinedButtonState();

  final AsyncCallback? onPressed;
  final ButtonStyle? style;
  final Widget child;
}

class _WaitableOutlinedButtonState extends State<WaitableOutlinedButton> {
  bool _waiting = false;

  @override
  Widget build(BuildContext context) {
    return OutlinedButton(
      style: widget.style,
      onPressed: widget.onPressed == null || _waiting
          ? null
          : () async {
        setState(() => _waiting = true);
        await widget.onPressed!();
        setState(() => _waiting = false);
      },
      child: widget.child,
    );
  }
}

コード内での利用方法

後は上記のWaitableElevatedButtonクラスとWaitableOutlinedButtonクラスを通常のElevatedButtonのように記述することで連打防止ボタンが実装できます。

変更例.dart
- child: ElevatedButton(  //元のクラス
+ child: WaitableElevatedButton(  //新しいクラス
使用例.dart
ElevatedButton(
  child: const Text('Button'),
  style: ElevatedButton.styleFrom(
    primary: Colors.yellow,
    onPrimary: Colors.black,
    shape: BeveledRectangleBorder(
      borderRadius: BorderRadius.circular(10),
    ),
  ),
  onPressed: () async {
    // 何らかの処理。(下記は単純に10ミリ秒Delayをさせているだけ)
    await Future.delayed(Duration(milliseconds: 10));
  },
),

参考記事

1
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?