カテゴリー・パッケージ・リポジトリを検索

async_button のカバー
パッケージ詳細v2.0.0-beta.1+2

async_button

非同期 onPressed 関数用のカスタムボタン。[アイドル]、[ロード中]、[成功]、[失敗] のボタン状態間でスムーズなアニメーションをサポートしています。

AndroidiOSWebmacOSWindowsLinux
30日間ダウンロード
13
いいね数
33
Pub ポイント
150

パッケージをインストール

flutter pub add async_button

パッケージ概要

公開情報に基づく選定ガイドです。参考としてご利用ください。

非同期の onPressed 操作に最適なカスタマイズ可能なボタンを提供するFlutterパッケージです。スムーズなアニメーションで、アイドル、ローディング、成功、失敗の各状態間の遷移を自然に処理します。フォームやログインフロー、非同期実行中にフィードバックが必要な任意のアクションに最適です。ボタンは操作のライフサイクルに応じて動的に調整され、進捗と結果を明確に示すことでユーザー体験を向上させます。

用途

  • フォームの送信
  • 認証フロー
  • データ保存アクション
  • APIリクエストのトリガー
  • ユーザー操作フィードバック

主な機能

  • アイドル/ロード/成功/失敗の状態を持つステートフルボタン
  • 組み込みアニメーション遷移
  • カスタマイズ可能な外観と動作
  • 自動状態管理
  • エラー処理と成功インジケータのサポート

適している対象

  • インタラクティブなUIを構築する開発者
  • 頻繁な非同期操作を行うアプリ
  • UXの一貫性を重視するチーム
  • 応答性のあるフォームコントロールを必要とするプロジェクト
  • 複雑なユーザー作業ワークフローを持つFlutterアプリ

注意事項

  • async/await パターンの理解が必要です
  • 複雑なデザインには追加のスタイルが必要になる場合があります
  • ボタン固有のユースケースに限定
  • インタラクティブでない要素には適していません
  • プラットフォーム固有のレンダリング動作に依存しています

元の README

関連するソースリポジトリの README 原文のスナップショットです。最新の内容はリポジトリをご覧ください。

Async Button

Buttons get boring when there is an asynchronous onTap function involved. Users don't get to see if or when the onTap function has finished execution, or if it has even finished sucessfully. To put it simply, this project aims to make them a little un-boring.

What is this?

This project provides you with the same buttons that you are used to, just with some modifications under the hood. You can manipulate the button state based on whether the onTap function is idle, loading or has finished loading(successfully or unsuccessfully).

How to use it?

This project provides you with 3 types of buttons. Let's list them below with an example.

AsyncElevatedBtn

Just like ElevatedButton, but for async onPressed

AsyncBtnStatesController btnStateController = AsyncBtnStatesController();

AsyncElevatedBtn(
  asyncBtnStatesController: btnStateController,
  onPressed: () async {
    btnStateController.update(AsyncBtnState.loading);
    try {
      // Await your api call here
      await Future.delayed(const Duration(seconds: 2));
      btnStateController.update(AsyncBtnState.success);
    } catch (e) {
      btnStateController.update(AsyncBtnState.failure);
    }
  },
  // * It is NOT mandatory to define [loadingStyle, successStyle, failureStyle]
  // * if you don't need it.

  // This should ideally be the button's loading state indicator.
  // If [style] or [widget] properties are not defined, we consider the button's
  // corresponding default [style] and [child] property
  loadingStyle: AsyncBtnStateStyle(
    style: ElevatedButton.styleFrom(
      backgroundColor: Colors.amber,
    ),
    widget: const SizedBox.square(
      dimension: 24,
      child: CircularProgressIndicator(
        color: Colors.white,
      ),
    ),
  ),

  // This should ideally be the button's success state indicator.
  // If [style] or [widget] properties are not defined, we consider the button's
  // corresponding default [style] and [child] property
  successStyle: AsyncBtnStateStyle(
    style: ElevatedButton.styleFrom(
      backgroundColor: Colors.green,
      foregroundColor: Colors.white,
    ),
    widget: Row(
      mainAxisSize: MainAxisSize.min,
      children: const [
        Icon(Icons.check),
        SizedBox(width: 4),
        Text('Success!')
      ],
    ),
  ),

  // This should ideally be the button's failure state indicator.
  // If [style] or [widget] properties are not defined, we consider the button's
  // corresponding default [style] and [child] property
  failureStyle: AsyncBtnStateStyle(
    style: ElevatedButton.styleFrom(
      backgroundColor: Colors.red,
      foregroundColor: Colors.white,
    ),
    widget: Row(
      mainAxisSize: MainAxisSize.min,
      children: const [
        Icon(Icons.error),
        SizedBox(width: 4),
        Text('Error!'),
      ],
    ),
  ),
  child: const Text('Execute'),
);

Too much? We have created a custom constructor that uses the exact values for loadingStyle, successStyle and failureStyle as above

AsyncBtnStatesController btnStateController = AsyncBtnStatesController();

AsyncElevatedBtn.withDefaultStyles(
  asyncBtnStatesController: btnStateController,
  onPressed: () async {
    btnStateController.update(AsyncBtnState.loading);
    try {
      // Await your api call here
      await Future.delayed(const Duration(seconds: 2));
      btnStateController.update(AsyncBtnState.success);
    } catch (e) {
      btnStateController.update(AsyncBtnState.failure);
    }
  },
  child: const Text('Execute'),
);

AsyncTextBtn

And this is our version of async TextButton

AsyncBtnStatesController btnStateController = AsyncBtnStatesController();

AsyncTextBtn(
  asyncBtnStatesController: btnStateController,
  onPressed: () async {
    btnStateController.update(AsyncBtnState.loading);
    try {
      // Await your api call here
      await Future.delayed(const Duration(seconds: 2));
      btnStateController.update(AsyncBtnState.success);
    } catch (e) {
      btnStateController.update(AsyncBtnState.failure);
    }
  },
  // * It is NOT mandatory to define [loadingStyle, successStyle, failureStyle]
  // * if you don't need it.

  // This should ideally be the button's loading state indicator.
  // If [style] or [widget] properties are not defined, we consider the button's
  // corresponding default [style] and [child] property
  loadingStyle: AsyncBtnStateStyle(
    style: TextButton.styleFrom(
      foregroundColor: Colors.amber,
    ),
    widget: const SizedBox.square(
      dimension: 24,
      child: CircularProgressIndicator(
        color: Colors.amber,
      ),
    ),
  ),


  // This should ideally be the button's success state indicator.
  // If [style] or [widget] properties are not defined, we consider the button's
  // corresponding default [style] and [child] property
  successStyle: AsyncBtnStateStyle(
    style: TextButton.styleFrom(
      foregroundColor: Colors.green,
    ),
    widget: Row(
      mainAxisSize: MainAxisSize.min,
      children: const [
        Icon(Icons.check),
        SizedBox(width: 4),
        Text('Success!')
      ],
    ),
  ),

  // This should ideally be the button's failure state indicator.
  // If [style] or [widget] properties are not defined, we consider the button's
  // corresponding default [style] and [child] property
  failureStyle: AsyncBtnStateStyle(
    style: TextButton.styleFrom(
      foregroundColor: Colors.red,
    ),
    widget: Row(
      mainAxisSize: MainAxisSize.min,
      children: const [
        Icon(Icons.error),
        SizedBox(width: 4),
        Text('Error!')
      ],
    ),
  ),
  child: const Text('Execute'),
);

Here again, you can use the following constructor instead

AsyncBtnStatesController btnStateController = AsyncBtnStatesController();

AsyncTextBtn.withDefaultStyles(
  asyncBtnStatesController: btnStateController,
  onPressed: () async {
    btnStateController.update(AsyncBtnState.loading);
    try {
      // Await your api call here
      await Future.delayed(const Duration(seconds: 2));
      btnStateController.update(AsyncBtnState.success);
    } catch (e) {
      btnStateController.update(AsyncBtnState.failure);
    }
  },
  child: const Text('Execute'),
);

AsyncOutlinedBtn

Similarly, here's one for async OutlinedButton

AsyncBtnStatesController btnStateController = AsyncBtnStatesController();

AsyncOutlinedBtn(
  asyncBtnStatesController: btnStateController,
  onPressed: () async {
    btnStateController.update(AsyncBtnState.loading);
    try {
      // Await your api call here
      await Future.delayed(const Duration(seconds: 2));
      btnStateController.update(AsyncBtnState.success);
    } catch (e) {
      btnStateController.update(AsyncBtnState.failure);
    }
  },
  // * It is NOT mandatory to define [loadingStyle, successStyle, failureStyle]
  // * if you don't need it.

  // This should ideally be the button's loading state indicator.
  // If [style] or [widget] properties are not defined, we consider the button's
  // corresponding default [style] and [child] property
  loadingStyle: AsyncBtnStateStyle(
    style: OutlinedButton.styleFrom(
      foregroundColor: Colors.amber,
    ),
    widget: const SizedBox.square(
      dimension: 24,
      child: CircularProgressIndicator(
        color: Colors.amber,
      ),
    ),
  ),

  // This should ideally be the button's success state indicator.
  // If [style] or [widget] properties are not defined, we consider the button's
  // corresponding default [style] and [child] property
  successStyle: AsyncBtnStateStyle(
    style: OutlinedButton.styleFrom(
      foregroundColor: Colors.green,
    ),
    widget: Row(
      mainAxisSize: MainAxisSize.min,
      children: const [
        Icon(Icons.check),
        SizedBox(width: 4),
        Text('Success!')
      ],
    ),
  ),

  // This should ideally be the button's failure state indicator.
  // If [style] or [widget] properties are not defined, we consider the button's
  // corresponding default [style] and [child] property
  failureStyle: AsyncBtnStateStyle(
    style: OutlinedButton.styleFrom(
      foregroundColor: Colors.red,
    ),
    widget: Row(
      mainAxisSize: MainAxisSize.min,
      children: const [
        Icon(Icons.error),
        SizedBox(width: 4),
        Text('Error!')
      ],
    ),
  ),
  child: const Text('Execute'),
);

Here as well, there is an alternative constructor

AsyncBtnStatesController btnStateController = AsyncBtnStatesController();

AsyncOutlinedBtn.withDefaultStyles(
  asyncBtnStatesController: btnStateController,
  onPressed: () async {
    btnStateController.update(AsyncBtnState.loading);
    try {
      // Await your api call here
      await Future.delayed(const Duration(seconds: 2));
      btnStateController.update(AsyncBtnState.success);
    } catch (e) {
      btnStateController.update(AsyncBtnState.failure);
    }
  },
  child: const Text('Execute'),
);

More Intuitive Examples

All buttons also supports these arguments - styleBuilder, loadingStyleBuilder, successStyleBuilder and failureStyleBuilder which creates the custom state styles at runtime. This essentially mean that one can create unlimited number of custom state widgets and styles based on different conditions.

There are also scopes for fallback styles and widgets if none of the necessary conditions are met.

Login Button

Click here for Code!

Download Button

Click here for Code!

Similar Projects

If this library doesn't cater to your requirements. Here are the some similar projects you can explore:

  • async_button_builder

  • easy_loading_button

  • animated_loading_button

Contribute

The creator always appreciates a helping hand, so don't hesitate before creating a pull request or reporting a bug/issue.

Connect with the Creator

The creator does aspire to help grow the flutter community. So if you have a question related to this project, your project, or anything flutter, connect with him over the following links. Don't worry, it's free!😉


Made with ❤️

カテゴリー

ソースリポジトリ

このパッケージを使用しているプロジェクト

データはまだありません。