123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- import 'dart:math';
- import 'package:calendar_view/notification_demo/notification_card.dart';
- import 'package:calendar_view/notification_demo/notification_controller.dart';
- import 'package:flutter/material.dart';
- import 'package:get/get.dart';
- /// 全局消息通知层
- class GlobalNotificationLayer extends StatefulWidget {
- const GlobalNotificationLayer({Key? key, required this.child})
- : super(key: key);
- final Widget child;
- @override
- GlobalNotificationLayerState createState() => GlobalNotificationLayerState();
- }
- class GlobalNotificationLayerState extends State<GlobalNotificationLayer> {
- late NotificationController notificationController;
- List<SystemNotification> notifications = [];
- final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
- final ScrollController _scrollController = ScrollController();
- static const double _notificationWidth = 420;
- bool get _isShowCloseAll => notifications.length > 2;
- @override
- void initState() {
- super.initState();
- notificationController =
- Get.put<NotificationController>(NotificationController());
- notificationController.onReceiveNotification
- .addListener(_onReceiveNotification);
- }
- @override
- void dispose() {
- super.dispose();
- notificationController.onReceiveNotification
- .removeListener(_onReceiveNotification);
- }
- void _onReceiveNotification(e, SystemNotification notification) {
- _insertNotification(notifications.length, notification);
- }
- // 新增消息
- void _insertNotification(index, SystemNotification item) {
- if (_listKey.currentState is! AnimatedListState) return;
- notifications.insert(index, item);
- _listKey.currentState!.insertItem(index);
- setState(() {});
- }
- // 移除消息
- void _removeNotification(index) {
- if (_listKey.currentState is! AnimatedListState) return;
- final SystemNotification notificationToRemove = notifications[index];
- notifications.removeAt(index);
- _listKey.currentState!.removeItem(
- index,
- (context, animation) => _buildNotificationSizeOut(
- context, index, animation, notificationToRemove),
- duration: const Duration(milliseconds: 120));
- setState(() {});
- }
- /// 滑动式移除
- void _removeNotificationSliderOut(index) {
- if (_listKey.currentState is! AnimatedListState) return;
- final SystemNotification notificationToRemove = notifications[index];
- notifications.removeAt(index);
- _listKey.currentState!.removeItem(
- index,
- (context, animation) => _buildNotificationSliderOut(
- context, index, animation, notificationToRemove),
- duration: const Duration(milliseconds: 200));
- setState(() {});
- }
- /// 瞬间移除
- void _removeNotificationInstant(index) {
- if (_listKey.currentState is! AnimatedListState) return;
- final SystemNotification notificationToRemove = notifications[index];
- notifications.removeAt(index);
- _listKey.currentState!.removeItem(
- index,
- (context, animation) =>
- _buildNotificationToRemove(notificationToRemove),
- duration: const Duration(milliseconds: 0));
- setState(() {});
- }
- void _closeAll() {
- final animateFrame = min(notifications.length, 8);
- final int total = notifications.length;
- for (var i = 0; i < total; i++) {
- if (total - i > animateFrame) {
- _removeNotificationInstant(0);
- } else {
- Future.delayed(Duration(milliseconds: 100 * (i + animateFrame - total)),
- () {
- _removeNotificationSliderOut(0);
- });
- }
- }
- }
- @override
- Widget build(BuildContext context) {
- return Stack(
- children: [
- widget.child,
- Positioned(
- bottom: 0,
- right: 0,
- child: SizedBox(
- width: _notificationWidth,
- child: Align(
- alignment: Alignment.bottomRight,
- child: AnimatedList(
- key: _listKey,
- initialItemCount: notifications.length,
- controller: _scrollController,
- shrinkWrap: true,
- itemBuilder: _buildNotificationFromRightSliderIn,
- ),
- ),
- ),
- ),
- if (_isShowCloseAll) _buildCloseAllButton()
- // _buildCloseAllButton()
- ],
- );
- }
- // 从右侧划入
- Widget _buildNotificationFromRightSliderIn(
- BuildContext context, int index, Animation<double> animation) {
- return SlideTransition(
- position: Tween<Offset>(
- begin: const Offset(1, 0),
- end: Offset.zero,
- ).animate(CurvedAnimation(
- parent: animation,
- curve: Curves.fastOutSlowIn,
- reverseCurve: Curves.fastOutSlowIn.flipped)),
- child: SizeTransition(
- axis: Axis.vertical,
- sizeFactor: animation,
- child: _buildNotificationCard(index),
- ),
- );
- }
- /// 收缩移除
- Widget _buildNotificationSizeOut(BuildContext context, int index,
- Animation<double> animation, SystemNotification notification) {
- return SizeTransition(
- axis: Axis.vertical,
- sizeFactor: animation,
- child: _buildNotificationToRemove(notification),
- );
- }
- /// 滑动移除
- Widget _buildNotificationSliderOut(BuildContext context, int index,
- Animation<double> animation, SystemNotification notification) {
- return SlideTransition(
- position: Tween<Offset>(
- begin: const Offset(1, 0),
- end: Offset.zero,
- ).animate(CurvedAnimation(
- parent: animation,
- curve: Curves.fastOutSlowIn,
- reverseCurve: Curves.fastOutSlowIn.flipped)),
- child: SizeTransition(
- axis: Axis.vertical,
- sizeFactor: animation,
- child: _buildNotificationToRemove(notification),
- ),
- );
- }
- Widget _buildNotificationCard(int index) {
- return NotificationCard(
- notification: notifications[index],
- onClose: () {
- _removeNotification(index);
- },
- );
- }
- Widget _buildNotificationToRemove(SystemNotification notification) {
- return NotificationCard(
- notification: notification,
- onClose: () {},
- );
- }
- Widget _buildCloseAllButton() {
- return Positioned(
- right: 20,
- top: 20,
- child: SizedBox(
- height: 40,
- child: ElevatedButton.icon(
- style: ButtonStyle(
- backgroundColor: MaterialStateProperty.all(
- const Color.fromARGB(255, 238, 77, 77)),
- ),
- icon: const Icon(Icons.close),
- onPressed: () {
- _closeAll();
- },
- label: Text('全部关闭(${notifications.length})'),
- ),
- ),
- );
- }
- }
|