flutter:使用 overlay 实现 loading
2021-06-19 本文已影响0人
李小轰
前言
最初,我们在项目中使用 showDialog 的方式实现 loading。问题点:任意一个pop操作都能 hide loading,无法统一管理 loading 的显隐。
Overlay是什么?
当我们创建MaterialApp的时候,它会自动创建一个Navigator,Navigator则又会创建一个Overlay:一个navigator用来管理所展示的views视图的Stack组件。
overlay 能干的事情很多,例如 loading,toast,popWindow 等等悬浮框能力都可以通过overlay来实现。下面我们通过loading样例来了解overlay的使用。
实现简单,直接上代码:
class LoadingTool {
static OverlayEntry _overlayEntry;
static void showLoading(BuildContext context) {
_show(context, CustomLoadingContainer(msg: "加载中"));
}
static void hideLoading() {
_cancel();
}
static void _show(BuildContext context, Widget msgContainer) {
if (_overlayEntry != null) {
_cancel();
}
_overlayEntry = OverlayEntry(builder: (BuildContext context) => SafeArea(child: msgContainer));
Overlay.of(context).insert(_overlayEntry);
}
static void _cancel() {
_overlayEntry?.remove();
_overlayEntry = null;
}
}
CustomLoadingContainer 为loading的布局widget
代码附上:
import 'package:flutter/material.dart';
class CustomLoadingContainer extends StatelessWidget {
final String msg;
const CustomLoadingContainer({Key key, this.msg}) : super(key: key);
@override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
width: double.infinity,
height: double.infinity,
color: Colors.black.withOpacity(0.5),
),
Align(
alignment: AlignmentDirectional.center,
child: _Indicator(
indicator: CircularProgressIndicator(
strokeWidth: 3,
valueColor: AlwaysStoppedAnimation(Colors.lightGreen),
),
status: msg),
),
],
);
}
}
class _Indicator extends StatelessWidget {
final Widget indicator;
final String status;
const _Indicator({
@required this.indicator,
@required this.status,
});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4.0),
),
padding: EdgeInsets.symmetric(
vertical: 15.0,
horizontal: 40.0,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
margin: status?.isNotEmpty == true
? EdgeInsets.only(bottom: 10.0)
: EdgeInsets.zero,
child: indicator,
),
Text (
status,
style: TextStyle (
color: Colors.black54,
decoration: TextDecoration.none,
fontSize: 15,
),
),
],
),
);
}
}
不足之处:调用时需要传递参数 BuildContext , 后期优化,使用全局 context 进行管理。