我们平时在做一个项目时,肯定会有许多需要显示弹窗的地方。弹窗的样式由UI给出,不用地方有不同的弹窗。想着可以把一些常用的弹窗封装成一个工具类,使用时只需替换不同元素(一般就是文本内容)即可。
话不多说,先上示例效果图:
底部单按钮普通提示弹出框:
底部两按钮普通提示弹出框:
底部弹出列表单项选择弹出框:
使用代码
// 底部单按钮普通提示弹出框
RaisedButton(
child: Text('使用DialogUtil底部单按钮普通提示弹出框'),
onPressed: () {
DialogUtil(
context: context,
onBtnPressed: () {
Navigator.pop(context);
}).showNoticeDialogWithOneButton();
},
),
// 底部两按钮普通提示弹出框
RaisedButton(
child: Text('使用DialogUtil底部两按钮普通提示弹出框'),
onPressed: () {
DialogUtil(
context: context,
content: '这是底部两按钮普通提示弹出框。确认继续么?',
onLeftBtnPressed: () {
Navigator.pop(context);
},
onRightBtnPressed: () {
// 确认后要做的的事
Navigator.pop(context);
}).showNoticeDialogWithTwoButtons();
},
),
// 底部弹出列表单项选择弹出框
RaisedButton(
child: Text('使用DialogUtil底部弹出列表单项选择弹出框'),
onPressed: () {
DialogUtil(
context: context,
title: '取消原因',
itemStringList: _cancelReasonList,
selectIndex: selectIndex,
onSelected: _handleCancelReasonSelected,
).showSheetView();
},
),
DialogUtil完整代码
import 'package:flutter/material.dart';
/// FileName dialog_util
///
/// @Author wangpenghui
/// @Date 2022/3/2 16:13
///
/// @Description 显示弹窗dialog工具类
class DialogUtil {
final BuildContext context;
/// 标题
final String title;
/// 内容
final String content;
/// 按钮名称
final String btnName;
/// 按钮字体颜色
final Color btnColor;
/// 左侧按钮名称
final String leftBtnName;
/// 左侧按钮字体颜色
final Color leftBtnColor;
/// 右侧按钮名称
final String rightBtnName;
/// 右侧按钮字体颜色
final Color rightBtnColor;
/// 点击背景是否可以关闭弹窗
final bool barrierDismissible;
/// 点击返回按钮是否可以关闭弹窗
final bool backDismissible;
/// 背景颜色
final Color barrierColor;
/// 阴影
final double elevation;
/// 内边距
final EdgeInsets padding;
/// 按钮点击回调
Function onBtnPressed;
/// 左侧按钮点击回调
Function onLeftBtnPressed;
/// 右侧按钮点击回调
Function onRightBtnPressed;
/// 弹窗列表
final List itemStringList;
/// 选中的索引,默认选中第一个
int selectIndex = 0;
/// 选择item后回调
final ValueChanged onSelected;
DialogUtil(
{@required this.context,
this.title = '提示',
this.content = '这是底部单按钮普通提示弹出框,请知晓',
this.btnName = '知道了',
this.btnColor = const Color(0xFFFF8900),
this.leftBtnName = '取消',
this.leftBtnColor = const Color(0xFF666666),
this.rightBtnName = '确认',
this.rightBtnColor = const Color(0xFFFE3826),
this.onBtnPressed,
this.onLeftBtnPressed,
this.onRightBtnPressed,
this.barrierColor = Colors.black54,
this.barrierDismissible = true,
this.backDismissible = true,
this.elevation = 0,
this.padding,
this.itemStringList,
this.selectIndex,
this.onSelected});
void showNoticeDialogWithOneButton() {
_showGeneralDialog(builder: (BuildContext context) {
return WillPopScope(
child: AnimatedPadding(
padding: padding == null
? EdgeInsets.symmetric(horizontal: 32, vertical: 24)
: padding,
duration: Duration(milliseconds: 100),
curve: Curves.decelerate,
child: MediaQuery.removeViewInsets(
removeLeft: true,
removeTop: true,
removeRight: true,
removeBottom: true,
context: context,
child: Center(
child: Material(
elevation: elevation,
borderRadius: BorderRadius.circular(14),
child: _noticeViewWithOneButton(),
),
),
),
),
);
});
}
void showNoticeDialogWithTwoButtons() {
_showGeneralDialog(builder: (BuildContext context) {
return WillPopScope(
child: AnimatedPadding(
padding: padding == null
? EdgeInsets.symmetric(horizontal: 32, vertical: 24)
: padding,
duration: Duration(milliseconds: 100),
curve: Curves.decelerate,
child: MediaQuery.removeViewInsets(
removeLeft: true,
removeTop: true,
removeRight: true,
removeBottom: true,
context: context,
child: Center(
child: Material(
elevation: elevation,
borderRadius: BorderRadius.circular(14),
child: _noticeViewWithTwoButtons(),
),
),
),
),
);
});
}
/// 重写showGeneralDialog,系统自带的背景背景透明不能修改
void _showGeneralDialog({
Widget Function(BuildContext) builder,
Widget child,
}) {
showGeneralDialog(
context: context,
pageBuilder: (BuildContext buildContext, Animation animation,
Animation secondaryAnimation) {
final Widget pageChild = child ?? Builder(builder: builder);
return SafeArea(
child: Builder(builder: (BuildContext context) {
return pageChild;
}),
);
},
barrierDismissible: barrierDismissible,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
barrierColor: barrierColor,
transitionDuration: const Duration(milliseconds: 150),
transitionBuilder: (BuildContext context, Animation animation,
Animation secondaryAnimation, Widget child) {
return FadeTransition(
opacity: CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
),
child: child,
);
},
);
}
Widget _noticeViewWithOneButton() {
return Container(
constraints: BoxConstraints(
minHeight: 130,
),
width: double.infinity - 104,
child: Column(
mainAxisSize: MainAxisSize.min, //column自适应子控件的高度,不加这条默认会撑到最大
children: [
_contentViewInOneButton(),
Divider(
height: 1,
thickness: 1,
color: Color(0xFFEEEEEE),
),
_bottomViewInOneButton(),
],
),
);
}
Widget _noticeViewWithTwoButtons() {
return Container(
constraints: BoxConstraints(
minHeight: 140,
),
width: double.infinity - 104,
child: Column(
mainAxisSize: MainAxisSize.min, //column自适应子控件的高度,不加这条默认会撑到最大
children: [
_titleViewInTwoButtons(),
_contentViewInTwoButtons(),
Divider(
height: 1,
thickness: 1,
color: Color(0xFFEEEEEE),
),
_bottomViewInTwoButtons(),
],
),
);
}
Widget _titleViewInTwoButtons() {
return Container(
margin: EdgeInsets.only(top: 19, left: 16, right: 16),
height: 22,
child: Text(title,
style: TextStyle(
color: Color(0xFF333333),
fontSize: 17,
fontWeight: FontWeight.w400,
)),
);
}
Widget _contentViewInTwoButtons() {
return Container(
constraints: BoxConstraints(minHeight: 32),
margin: EdgeInsets.only(top: 9, bottom: 14, left: 16, right: 16),
child: Text(content,
textAlign: TextAlign.center,
style: TextStyle(
color: Color(0xFF666666),
fontSize: 12,
fontWeight: FontWeight.w400)),
);
}
Widget _bottomViewInTwoButtons() {
return Container(
height: 43,
child: Row(
children: [
_clickView(leftBtnName, leftBtnColor, onLeftBtnPressed),
VerticalDivider(
color: Color(0xFFEEEEEE),
width: 1,
thickness: 1,
),
_clickView(rightBtnName, rightBtnColor, onRightBtnPressed),
],
),
);
}
Widget _contentViewInOneButton() {
return Container(
constraints: BoxConstraints(minHeight: 44),
margin: EdgeInsets.only(top: 22, bottom: 20, left: 16, right: 16),
alignment: Alignment.center,
child: Text(content,
textAlign: TextAlign.center,
style: TextStyle(
color: Color(0xFF333333),
fontSize: 17,
fontWeight: FontWeight.w400)),
);
}
Widget _bottomViewInOneButton() {
return Container(
height: 43,
child: Row(
children: [
_clickView(btnName, btnColor, onBtnPressed),
],
),
);
}
Widget _clickView(String btnName, Color textColor, Function btnClick) {
return Expanded(
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: btnClick,
child: Container(
height: 43,
alignment: Alignment.center,
child: Text(btnName,
style: TextStyle(
color: textColor,
fontSize: 17,
fontWeight: FontWeight.w400)),
),
),
);
}
void showSheetView() {
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Color(0x33000000),
builder: (context) {
return StatefulBuilder(
builder: (context, _setState) {
return Column(
children: [
Expanded(
child: GestureDetector(
onTap: () {
onSelected(selectIndex);
Navigator.pop(context);
},
),
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12)),
color: Color(0xFFF7F7F7),
),
child: Column(
children: [
Column(
children: [
Container(
width: double.infinity,
padding: EdgeInsets.only(
top: 14, left: 20, right: 20),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12)),
color: Colors.white,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(
fontSize: 17,
color: Color(0xFF333333),
fontWeight: FontWeight.w500,
),
),
Container(
width: double.infinity,
padding: EdgeInsets.only(
top: 14, bottom: 14),
child: Column(
children: _chooseListAllWidget(_setState),
),
),
],
),
),
],
),
Container(
margin: EdgeInsets.only(top: 6),
child: GestureDetector(
child: Container(
height: 56,
width: double.infinity,
alignment: Alignment.center,
color: Colors.white,
child: Text(
'取消',
style: TextStyle(
fontSize: 17,
color: Color(0xFF333333),
fontWeight: FontWeight.w400,
),
),
),
onTap: () {
onSelected(selectIndex);
Navigator.pop(context);
},
),
),
],
),
),
],
);
},
);
});
}
List _chooseListAllWidget(StateSetter setState) {
List widgetList = [];
for (int i = 0; i < itemStringList.length; i++) {
widgetList.add(_chooseListItemWidget(i, setState));
}
return widgetList;
}
Widget _chooseListItemWidget(int index, StateSetter setMyState) {
return GestureDetector(
child: Container(
padding: EdgeInsets.only(top: 11, bottom: 11),
child: Row(
children: [
Expanded(
child: Text(
itemStringList[index],
style: TextStyle(
fontSize: 15,
color: Color(0xFF333333),
fontWeight: FontWeight.w400,
),
),
),
Image.asset(
selectIndex == index
? 'images/img/icon_checked.webp'
: 'images/img/icon_unchecked.webp',
width: 16.5,
height: 16.5,
),
],
),
),
onTap: () {
setMyState(() {
selectIndex = index;
onSelected(selectIndex);
});
Navigator.pop(context);
},
);
}
}