美文网首页iOS 技巧Flutter学习
Flutter | 简单好用的弹窗队列

Flutter | 简单好用的弹窗队列

作者: Lol刀妹 | 来源:发表于2022-02-12 22:31 被阅读0次

    需求:

    这是一个比较常见的需求:

    进入app,有时有一堆的弹窗需要弹出来,什么活动弹窗啊,新用户福利弹窗啊,这些弹窗不能一次性全部弹出来,而是一个弹窗消失后下一个弹窗才弹出来。甚至,点击第一个弹窗进入详情页后,从详情页返回的时候,后面的弹窗才接着弹出来。

    演示:

    点击第一个弹窗进入详情页后,从详情页返回的时候,后面的弹窗才接着弹出来。

    为了方便说明,就用弹出两个简单弹窗来阐述:

    • 视频展示:
    弹窗队列.gif

    思路:

    把任务放进队列。

    “弹出弹窗” 视为一个任务,任务由队列控制,队列由我们控制。

    现在 get 不到没关系,后面有完整 demo,你一定能可以理解。

    代码:

    • 队列代码:

    仅三十多行代码。

    import 'package:flutter/material.dart';
    
    /// 弹窗队列管理
    class DialogQueueManager {
      static bool _isNewQueue = true;
      static List<VoidCallback> _array = [];
    
      /// 入队
      static void enqueue(VoidCallback callback) {
        if (_isNewQueue) {
          _isNewQueue = false;
          callback();
        } else {
          _array.add(callback);
        }
      }
    
      /// 出队,返回出队是否成功
      static bool dequeue() {
        if (_array.isEmpty) {
          _isNewQueue = true;
          return false;
        } else {
          // 执行
          _array.first();
          // 删除
          _array.removeAt(0);
          _isNewQueue = _array.isEmpty;
          return true;
        }
      }
    
      static void clear() {
        _array = [];
        _isNewQueue = true;
      }
    }
    
    
    • demo 演示代码:
    import 'package:flutter/material.dart';
    import 'package:flutter_uikit/common/macro.dart';
    import 'package:flutter_uikit/contents/dialog/dialog_queue/dialog_queue_manager.dart';
    
    class DialogQueueDemoPage extends StatefulWidget {
      const DialogQueueDemoPage({Key? key}) : super(key: key);
    
      @override
      _DialogQueueDemoPageState createState() => _DialogQueueDemoPageState();
    }
    
    class _DialogQueueDemoPageState extends State<DialogQueueDemoPage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: const Text('弹窗队列')),
          body: Center(
            child: ElevatedButton(
              onPressed: _test,
              child: const Text('弹出多个弹窗'),
            ),
          ),
        );
      }
    
      void _test() {
        // 入队
        DialogQueueManager.enqueue(() {
          // 弹出弹窗1
          _showDialog1();
        });
        // 入队
        DialogQueueManager.enqueue(() {
          // 弹窗弹窗2
          _showDialog2();
        });
      }
    
      void _showDialog1() {
        showDialog(
          context: globalContext,
          builder: (context) {
            return Dialog(
              backgroundColor: Colors.orange,
              child: SizedBox(
                height: 100,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    const Text('这是弹窗1'),
                    ElevatedButton(
                      onPressed: () {
                        // 移除弹窗1
                        Navigator.pop(globalContext);
                        // 跳转到详情页
                        Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) => const _DetailPage()),
                        ).then((value) {
                          // 返回页面的时候才出队
                          // 此时弹窗队列的下一个任务执行
                          DialogQueueManager.dequeue();
                        });
                      },
                      child: const Text('查看详情'),
                    ),
                  ],
                ),
              ),
            );
          },
        );
      }
    
      void _showDialog2() {
        showDialog(
          context: globalContext,
          builder: (context) {
            return Dialog(
              backgroundColor: Colors.green,
              child: SizedBox(
                height: 200,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    const Text('这是弹窗2'),
                    ElevatedButton(
                      onPressed: () {
                        Navigator.pop(globalContext);
                        // 出队
                        DialogQueueManager.dequeue();
                      },
                      child: const Text('确定'),
                    ),
                  ],
                ),
              ),
            );
          },
        );
      }
    }
    
    /// 详情页
    class _DetailPage extends StatelessWidget {
      const _DetailPage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: const Text('这是弹窗1的详情页')),
        );
      }
    }
    
    

    秀在哪?

    看完后你可能觉得很简单,如果是这样,说明你已经 get 到了。

    这段代码它秀在秀在:放在队列里的是任务,代码表现上就是函数,而函数,可以是一切

    我给它命名为 DialogQueueManager,其实并不准确,因为它并不局限于弹窗队列,毕竟任务不仅仅可以是弹出弹窗,它可以是一切操作。它更适合的名字,应该是: TaskQueueManager

    这个类你可以拿到项目里直接用,它已经经过了两个项目的考验。你也可以改造它,让它更强大,为你更好的服务。

    源码

    https://github.com/CaiWanFeng/flutter-uikit

    最后

    本人擅长 iOS 和 Flutter,拥有多年开发经验,实战能力强,代码规范,注释清晰,欢迎技术交流与合作。

    相关文章

      网友评论

        本文标题:Flutter | 简单好用的弹窗队列

        本文链接:https://www.haomeiwen.com/subject/diyakrtx.html