iOS 技巧Flutter学习

Flutter | 简单好用的弹窗队列

2022-02-12  本文已影响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;
  }
}

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,拥有多年开发经验,实战能力强,代码规范,注释清晰,欢迎技术交流与合作。

上一篇 下一篇

猜你喜欢

热点阅读