今日又用到了我自己写的 loadDialog,才发现以前的写法是如此的简陋。现在我想到了另外一个方法。关于 如何在 A 页面执行的方法中来关闭 弹出的 Dialog。
import 'dart:async';
import 'package:flutter/material.dart';
// ignore: must_be_immutable
class NetLoadingDialog extends StatefulWidget {
String loadingText;
bool outsideDismiss;
Function dismissDialog;
NetLoadingDialog(
{Key key,
this.loadingText = "loading...",
this.outsideDismiss = true,
this.dismissDialog})
: super(key: key);
@override
State<NetLoadingDialog> createState() => _LoadingDialog();
}
class _LoadingDialog extends State<NetLoadingDialog> {
_dismissDialog() {
Navigator.of(context).pop();
}
@override
void initState() {
super.initState();
if (widget.dismissDialog != null) {
widget.dismissDialog(
//将关闭 dialog的方法传递到调用的页面.
(){Navigator.of(context).pop();}
);
}
}
@override
Widget build(BuildContext context) {
return xxxx
}
}
build方法不变,主要在于利用了 dismissDialog ,向调用这个界面的地方 回传了一个 pop 方法,这样 只要在自己处理完的地方调用即可。
调用代码:
showDialog(
context: context,
builder: (context) {
return new NetLoadingDialog(
dismissDialog: _disMissCallBack,
outsideDismiss: false,
);
}
);
//这个func 就是关闭Dialog的方法,在适当的时候关闭即可
_disMissCallBack(Function func) {
xxx
showSnackBar("登录成功");
func();
}
这样,很多情况下都可以用 回调 的方式来处理了 ,over。
与我第一次写的相比,主要是将 逻辑置于自己的页面来处理了,各有各的利用情况。
希望都能给你些灵感。
以下是原文
因为新打开的Dialog是另外一个界面了,所以我想,如果用pop(context),那么就必须获取到dialog的contex,那么为啥不让dialog自己调用关闭自己呢。所以我实现了如下Dialog:
import 'dart:async';
import 'package:flutter/material.dart';
// ignore: must_be_immutable
class NetLoadingDialog extends StatefulWidget {
String loadingText;
bool outsideDismiss;
Function dismissCallback;
Future<dynamic> requestCallBack;
NetLoadingDialog(
{Key key,
this.loadingText = "loading...",
this.outsideDismiss = true,
this.dismissCallback,
this.requestCallBack})
: super(key: key);
@override
State<NetLoadingDialog> createState() => _LoadingDialog();
}
class _LoadingDialog extends State<NetLoadingDialog> {
_dismissDialog() {
if (widget.dismissCallback != null) {
widget.dismissCallback();
}
Navigator.of(context).pop();
}
@override
void initState() {
super.initState();
if (widget.requestCallBack != null) {
widget.requestCallBack.then((_) {
Navigator.pop(context);
});
}
}
@override
Widget build(BuildContext context) {
return new GestureDetector(
onTap: widget.outsideDismiss ? _dismissDialog : null,
child: Material(
type: MaterialType.transparency,
child: new Center(
child: new SizedBox(
width: 120.0,
height: 120.0,
child: new Container(
decoration: ShapeDecoration(
color: Color(0xffffffff),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(8.0),
),
),
),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new CircularProgressIndicator(),
new Padding(
padding: const EdgeInsets.only(
top: 20.0,
),
child: new Text(
widget.loadingText,
style: new TextStyle(fontSize: 12.0),
),
),
],
),
),
),
),
),
);
}
}
这里主要传递了一个requestCallBack的Future函数,然后在initState中监听返回,当执行完成的时候,关闭dialog。所以,主要就是传递一个Future函数给Dialog,这也是为啥我上篇网络请求返回Future的原因。
使用起来就简单了,和普通的Dialog一样。
showDialog(
context: context,
barrierDismissible: false,
builder: (_) {
return new NetLoadingDialog(
requestCallBack: _register(),
outsideDismiss: false,
);
});
而这个_register()方法就是一个Future函数。
可以自己先写一个Loading 的界面,然后在需要调用的时候,根据state来判断,是否加载loading界面,当然咯,这个loading界面也可以设置成半透明的。
@override
Widget build(BuildContext context) {
if(showLoading){
return xxx;
}
}
这里外层可以使用Stack布局,像Android里面的FrameLayout。这样就能把两个布局"重合"在一起。实现展示Loading的能力。同样的,改变状态就需要调用setState即可。当然前提是这得是一个StatefulWidget。
ok,有其它的方式后再补充,或者如果有更好的方式,能在A页面中关闭A页面打开的Dialog,希望您能评论告诉我。
希望我的方法对你有帮助。