美文网首页
flutter: 实现 dialog 显隐监听

flutter: 实现 dialog 显隐监听

作者: 李小轰 | 来源:发表于2021-08-13 15:55 被阅读0次

背景

项目开发中碰到一个需求:监听接收流消息,每次使用 dialog 的方式弹窗显示,要求,每次弹窗将之前的弹窗关闭。

实现

为了达到这个效果,我们需要监听 dialog 的显隐状态,并提供方法关闭指定的dialog。

代码如下:

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

typedef DialogLifeCallback = Function(
  bool show,
  GlobalKey<BaseLifeDialogState>,
);

class BaseLifeDialog extends StatefulWidget {
  final DialogLifeCallback callback;
  final Widget child;

  const BaseLifeDialog({
    Key key,
    @required this.callback,
    @required this.child,
  }) : super(key: key);

  @override
  BaseLifeDialogState createState() => BaseLifeDialogState();
}

class BaseLifeDialogState extends State<BaseLifeDialog> {
  //flutter调度阶段是否为 build/layout/paint
  bool get isPersistentCallbacks =>
      SchedulerBinding.instance?.schedulerPhase ==
      SchedulerPhase.persistentCallbacks;

  @override
  void initState() {
    super.initState();
    if (!mounted) return;
    if (isPersistentCallbacks) {
      SchedulerBinding.instance?.addPostFrameCallback((_) {
        //回调告知 dialog 已显示
        _noticeLife(true);
      });
    } else {
      //回调告知 dialog 已显示
      _noticeLife(true);
    }
  }

  @override
  void dispose() {
    //回调告知 dialog 已消失
    _noticeLife(false);
    super.dispose();
  }

  void _noticeLife(bool isShow) {
    widget.callback(isShow, widget.key);
  }

  ///提供关闭自己的方法
  void closeSelf() {
    if (isPersistentCallbacks) {
      SchedulerBinding.instance?.addPostFrameCallback((_) {
        _closeSelf();
      });
    } else {
      _closeSelf();
    }
  }

  void _closeSelf() {
    Navigator.of(context).removeRoute(ModalRoute.of(context));
  }

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }
}
  • initState 将 dialog 显示状态传递出去
  • dispose 将 dialog 消失状态传递出去
  • 提供 closeSelf 关闭窗口方法,外部可通过 gloabalKey 进行调用

封装 dialog 管理工具类

(每次 showDialog 关闭之前未关闭的 dialog )

import 'package:flutter/material.dart';
import 'package:test_dialog_life/base_life_widget.dart';

class DialogController {
  List<GlobalKey<BaseLifeDialogState>> _widgetKeys = [];

  /// dialog 显隐 回调
  void onListenDialogToggle(bool isShow, GlobalKey<BaseLifeDialogState> key) {
    if (isShow) {
      //dialog显示

      //关闭之前的其他弹窗
      _widgetKeys.forEach((element) {
        element.currentState?.closeSelf();
      });
      _widgetKeys.add(key);
    } else {
      //dialog消失
      if (_widgetKeys.contains(key)) {
        _widgetKeys.remove(key);
      }
    }
  }

  //提供外部调用,showDialog
  show(
    BuildContext context,
    Widget child,
  ) {
    showDialog<bool>(
      context: context,
      barrierDismissible: false,
      child: Builder(
        builder: (context) {
          return Dialog(
            child: BaseLifeDialog(
              key: GlobalKey<BaseLifeDialogState>(),
              callback: onListenDialogToggle,
              child: child,
            ),
          );
        },
      ),
    );
  }

  ///单例实现
  DialogController._interval();
  static DialogController _instance = DialogController._interval();
  static DialogController get instance => _instance;

  factory DialogController() => _instance;
}

Demo 调用示例:

//点击触发
onPressed: () {
              DialogController.instance.show(context, DialogChild(msg: "1"));
              DialogController.instance.show(context, DialogChild(msg: "2"));
            }


class DialogChild extends StatelessWidget {
  final String msg;
  const DialogChild({Key key, this.msg}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 200,
      width: 200,
      child: Center(
        child: Text(msg),
      ),
    );
  }
}

相关文章

网友评论

      本文标题:flutter: 实现 dialog 显隐监听

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