需求:
这是一个比较常见的需求:
进入app,有时有一堆的弹窗需要弹出来,什么活动弹窗啊,新用户福利弹窗啊,这些弹窗不能一次性全部弹出来,而是一个弹窗消失后下一个弹窗才弹出来。甚至,点击第一个弹窗进入详情页后,从详情页返回的时候,后面的弹窗才接着弹出来。
演示:
点击第一个弹窗进入详情页后,从详情页返回的时候,后面的弹窗才接着弹出来。
为了方便说明,就用弹出两个简单弹窗来阐述:
- 视频展示:
思路:
把任务放进队列。
“弹出弹窗” 视为一个任务,任务由队列控制,队列由我们控制。
现在 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,拥有多年开发经验,实战能力强,代码规范,注释清晰,欢迎技术交流与合作。
网友评论