zoukankan      html  css  js  c++  java
  • Flutter 支持 Loading 的 Button

    介绍

    Flutter 常见的 loading 框一般是采用 showDialog 的方式弹出一个新的界面,首先并不美观易用,其次,还有一个很大的弊端,因为取消 Loading 框时需要采用 Navigator.pop 方法,会造成严重路由混乱,甚至在一些特殊场景下甚至没有办法实现。

    下图是一个按钮,在点击时会触发相应事件,按钮变为不可点击的 loading 状态,事件执行完成后 loading 状态自动结束,并执行其他逻辑操作。

    代码

    主要代码如下:

    import 'package:flutter/material.dart';
    
    /// 含 Loading 的按钮
    ///
    /// @author seliote
    /// @version 2021-09-08
    
    /// 异步的 VoidCallback,可用于等待执行完成
    typedef AsyncVoidCallback = Future<void> Function();
    
    /// 含 Loading 的按钮
    class LoadingButton extends StatefulWidget {
      final Widget childWidget;
      final Widget loadingWidget;
      final AsyncVoidCallback? callback;
      final VoidCallback? onLongPress;
      final ButtonStyle? style;
      final FocusNode? focusNode;
      final bool autofocus;
      final Clip clipBehavior;
    
      const LoadingButton(this.childWidget, this.loadingWidget, this.callback,
          {Key? key,
          this.onLongPress,
          this.style,
          this.focusNode,
          this.autofocus = false,
          this.clipBehavior = Clip.none})
          : super(key: key);
    
      @override
      _LoadingButtonState createState() => _LoadingButtonState();
    }
    
    class _LoadingButtonState extends State<LoadingButton> {
      bool loading = false;
    
      @override
      Widget build(BuildContext context) {
        return loading
            ? widget.loadingWidget
            : TextButton(
                child: loading ? widget.loadingWidget : widget.childWidget,
                // 保留原始功能,为 null 时或 loading 时禁用按钮
                onPressed: loading
                    ? () => null
                    : (widget.callback == null
                        ? () => null
                        : () async {
                            // 执行前变换
                            setState(() {
                              loading = !loading;
                            });
                            await widget.callback!();
                            // 等待执行完成后再变换
                            setState(() {
                              loading = !loading;
                            });
                          }),
                onLongPress: widget.onLongPress,
                style: widget.style,
                focusNode: widget.focusNode,
                autofocus: widget.autofocus,
                clipBehavior: widget.clipBehavior);
      }
    }
    

    使用

    使用方法如下,其中 SpinKitDoubleBounceflutter_spinkit 库 提供的 Loading 动画:

    LoadingButton(
      Row(
        children: <Widget>[
          Text(
            AppLocalizations.of(globalKey.currentState!.context)!
                .nextStep,
            style: TextStyle(
                color: Colors.lightBlueAccent,
                fontWeight: FontWeight.w600),
          ),
        ],
      ),
      Padding(
        padding: const EdgeInsets.all(8),
        child: SpinKitDoubleBounce(color: Colors.blueAccent),
      ),
      callback,
    )
    
  • 相关阅读:
    并查集 [Total Eclipse]
    2020 Multi-University Training Contest 2 [The Oculus]
    2020牛客暑期多校训练营(第三场)G Operating on a Graph
    杭电多校第一场 [Fibonacci Sum]
    Codeforces Round #658 (Div. 2) E. Mastermind
    二次剩余
    SpringBlade 后端项目 部署 2.0-boot
    SpringBlade 前端项目 部署 Saber
    前端 天气插件
    SpringBlade 打包
  • 原文地址:https://www.cnblogs.com/seliote/p/15244906.html
Copyright © 2011-2022 走看看