当前位置: 首页 > news >正文

记录一下flutter项目自己封窗的弹窗

在评委项目开发中我使用到的弹窗dialog与modal sheet底部弹出组件,我对其进行了基础的封装,以适用于本项目,代码如下:
 

class JudgeDialog {// 内容边距static EdgeInsetsGeometry _contentPadding(String? content) {return content != null? EdgeInsets.only(left: 30.rpx,right: 30.rpx,top: 32.rpx,bottom: 26.rpx,): EdgeInsets.all(0.rpx);}// 内容样式static TextStyle _contentStyle() {return TextStyle(fontSize: 31.rpx,height: 1.5,fontFamily: AppTextFamily.appleMiddle,color: AppColors.t3,);}// X关闭按钮static Widget closeBtn(BuildContext context, {Function? closeCall,}) {return Positioned(right: 36.rpx,top: 30.rpx,child: SizedBox(height: 36.rpx,width: 36.rpx,child: IconButton(onPressed: () {if (closeCall != null) {closeCall();} else {Navigator.pop(context);}},padding: EdgeInsets.all(0.rpx),icon: Transform.rotate(angle: pi / 4,child: Icon(AppIcon.plusAdd,size: 36.rpx,color: AppColors.t9,),),),),);}static Future<bool?> tipDialog(BuildContext context, {bool? dismissible = false, // 背景与滑动是否可关bool? close = false, // 是否有X的关闭Function? closeCall, // 关闭X时调用Color? bgColor, // 背景色double? opacity,String? title,String? content,Widget? contentChild,EdgeInsetsGeometry? contentPadding,TextAlign? textAlign,double? btnWidth,String? confirmText = '我知道了',Function? confirm,String? cancelText = '取消',Function? cancel,}) async {return showDialog(context: context,barrierDismissible: dismissible!,barrierColor: bgColor ?? Colors.black.withOpacity(opacity ?? 0.55),builder: (dialogContext) {return WillPopScope(onWillPop: () async {return dismissible;},child: Container(width: HYSizeFit.screenWidth,padding: EdgeInsets.only(left: HYSizeFit.screenWidth * 0.1,right: HYSizeFit.screenWidth * 0.1,bottom: HYSizeFit.screenHeight * 0.1,),child: Column(crossAxisAlignment: CrossAxisAlignment.center,mainAxisAlignment: MainAxisAlignment.center,children: [AlertDialog(insetPadding: EdgeInsets.all(0.rpx),backgroundColor: Colors.white,titlePadding: EdgeInsets.all(0.rpx),buttonPadding: EdgeInsets.all(0.rpx),alignment: Alignment.center,elevation: 0.rpx,shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.rpx), // 设置圆角大小),title: Stack(children: [Container(alignment: Alignment.center,padding: EdgeInsets.only(top: 52.rpx),child: AppTextTitle.titleH34(title ?? '提示',fontFamily: AppTextFamily.appleBold,),),if (close!)closeBtn(dialogContext,closeCall: closeCall,),],),contentPadding: contentPadding ?? _contentPadding(content),contentTextStyle: _contentStyle(),content: content != null? Text(content, textAlign: textAlign ?? TextAlign.center): contentChild ?? const SizedBox.shrink(),actionsAlignment: MainAxisAlignment.spaceAround,actionsPadding: EdgeInsets.only(top: content != null ? 26.rpx : 0.rpx,left: 30.rpx,right: 30.rpx,bottom: 52.rpx,),actions: [if (cancel != null)GlobalButton.customButton('$cancelText',bgColor1: AppColors.page,bgColor2: AppColors.page,color: AppColors.t3,width: btnWidth ?? 210.rpx,height: 70.rpx,radius: 35.rpx,size: 30.rpx,ripple: false,onPressed: () => cancel(),),GlobalButton.customButton('$confirmText',bgColor1: AppColors.primary,bgColor2: AppColors.primary,width: btnWidth ?? 210.rpx,height: 70.rpx,radius: 35.rpx,size: 30.rpx,ripple: false,onPressed: () {if (confirm == null) {Navigator.pop(context, true);} else {confirm();}},),],),],),),);},);}// 自定义弹窗static Future<bool?> markDialog(BuildContext context, {bool? dismissible = false,double? opacity,Color? bgColor, // 背景色required Widget child,}) async {return showDialog(context: context,barrierDismissible: dismissible!,barrierColor: bgColor ?? Colors.black.withOpacity(opacity ?? 0.55),builder: (BuildContext context) {return WillPopScope(onWillPop: () async {return dismissible;},child: SizedBox(width: HYSizeFit.screenWidth,height: double.maxFinite,child: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [child],),),);},);}/// 底部弹窗static Future<bool?> modalSheet(BuildContext context, {bool? dismissible = true,double? opacity,Color? barrierColor, // 弹窗背景色Color? bgColor, // 弹出背景double? elevation,BoxConstraints? constraints,required Widget child,}) async {return showModalBottomSheet(context: context,elevation: elevation,constraints: constraints,backgroundColor: bgColor ?? Colors.transparent,barrierColor: barrierColor ?? Colors.black.withOpacity(opacity ?? 0.6),builder: (BuildContext context) {return child;},);}
}

在此基础上还增加了底部支付选择的弹窗:
 

// 支付方式
enum PayMethodType {/// 支付宝alipay,/// 评贝pingBei
}/// 全局支付方式选择
class AppPayModalSheet extends StatefulWidget {const AppPayModalSheet({super.key,required this.title,this.amount,this.beiAmount,this.balance,this.enough,this.unit,required this.methods,this.onPressed,});final String title; // 弹窗标题final String? amount; // 金额final String? beiAmount; // 评贝金额final String? balance; // 本人评贝余额final bool? enough; // 评贝余额是否不足final String? unit; // 单位final Set<PayMethodType> methods; // 支付方式final ValueChanged? onPressed;@overrideState<AppPayModalSheet> createState() => _AppPayModalSheetState();
}class _AppPayModalSheetState extends State<AppPayModalSheet> {late Set<PayMethodType> methods;late PayMethodType group;@overridevoid initState() {super.initState();methods = widget.methods;group = methods.first;setState(() {});}@overrideWidget build(BuildContext context) {return IntrinsicHeight(child: Container(width: HYSizeFit.screenWidth,padding: EdgeInsets.only(bottom: HYSizeFit.bottomHeight + 10.rpx),decoration: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.only(topLeft: Radius.circular(30.rpx),topRight: Radius.circular(30.rpx),),),child: Column(mainAxisAlignment: MainAxisAlignment.end,mainAxisSize: MainAxisSize.min,children: [PayModalTitle(title: widget.title),Column(mainAxisSize: MainAxisSize.min,children: methods.map((e) {return PayByModalMethod(value: e,group: group,balance: widget.balance,enough: widget.enough,changed: (val) {group = val;if (mounted) setState(() {});},);}).toList(),),PayBottomBtn(leftChild: group == PayMethodType.pingBei ? beiBy() : priceBy(),onPressed: () {widget.onPressed!(group);},),],),),);}// 金额Widget priceBy() {return RichText(text: TextSpan(text: '¥',style: AppTextTitle.customStyle(height: 1.2, size: 32.rpx),children: [TextSpan(text: '${widget.amount}',style: AppTextTitle.customStyle(height: 1.2,size: 40.rpx,fontFamily: AppTextFamily.pingFangHeavy,),),],),);}// 评贝Widget beiBy() {return RichText(text: TextSpan(text: '${widget.beiAmount}',style: AppTextTitle.customStyle(height: 1.2,size: 40.rpx,fontFamily: AppTextFamily.pingFangHeavy,),children: [TextSpan(text: widget.unit ?? '评贝',style: AppTextTitle.customStyle(height: 1.2, size: 32.rpx, letterSpacing: -2.rpx),),],),);}
}/// 支付弹窗标题
class PayModalTitle extends StatelessWidget {const PayModalTitle({super.key, required this.title});final String title;@overrideWidget build(BuildContext context) {return Container(width: double.maxFinite,padding: EdgeInsets.only(top: 42.rpx, bottom: 50.rpx),alignment: Alignment.center,decoration: BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(30.rpx),topRight: Radius.circular(30.rpx),),gradient: AppColors.multicolor(['#FFEFCD', '#FFEFCD', '#FFFFFF']),),child: Text(title,style: AppTextTitle.customStyle(height: 1.2,size: 38.rpx,color: ColorUtil.stringColor('#A07313'),fontFamily: AppTextFamily.appleBold,),),);}
}/// 支付底部按钮区
class PayBottomBtn extends StatelessWidget {const PayBottomBtn({super.key,this.leftChild,this.mainAxisAlignment,this.btnText,this.onPressed,});final Widget? leftChild;final MainAxisAlignment? mainAxisAlignment;final String? btnText;final VoidCallback? onPressed;@overrideWidget build(BuildContext context) {return Container(height: 112.rpx,width: double.maxFinite,padding: EdgeInsets.only(left: 56.rpx, right: 30.rpx),margin: EdgeInsets.only(top: 30.rpx),decoration: BoxDecoration(border: Border(top: BorderSide(width: 1.rpx, color: AppColors.line),),),child: Row(mainAxisAlignment: mainAxisAlignment ?? MainAxisAlignment.spaceBetween,crossAxisAlignment: CrossAxisAlignment.center,children: [leftChild ?? const SizedBox.shrink(),GlobalButton.elevatedButton(btnText ?? '支付',width: 216.rpx,height: 80.rpx,size: 32.rpx,ripple: false,radius: 6.rpx,bgColor: ColorUtil.stringColor('#EDA830'),onPressed: onPressed,),],),);}
}/// 支付方法选项
class PayByModalMethod extends StatelessWidget {const PayByModalMethod({super.key,this.balance,this.enough,this.value,this.group,this.changed,});final PayMethodType? value;final PayMethodType? group;final String? balance; // 本人评贝余额final bool? enough; // 评贝余额是否不足final ValueChanged? changed;@overrideWidget build(BuildContext context) {bool isEnough = value == PayMethodType.pingBei && enough != null && enough!;String payText() {switch (value) {case PayMethodType.alipay:return AdaptStr.strHansen();case PayMethodType.pingBei:return '评贝${AdaptStr.sef()}';default:return '';}}return Container(width: HYSizeFit.screenWidth,height: 100.rpx,padding: EdgeInsets.only(left: 46.rpx, right: 40.rpx),child: InkWell(onTap: () {if (!isEnough) {changed!(value);}},child: Row(crossAxisAlignment: CrossAxisAlignment.center,mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [Row(children: [payIcon(),AppTextTitle.titleH2(payText(), letterSpacing: -2.rpx),if (value == PayMethodType.pingBei && balance != null)AppTextTitle.titleH2('(余额:$balance评贝)',letterSpacing: -1.5.rpx,),],),isEnough? AppTextTitle.titleH3('评贝余额不足', color: AppColors.primary): SizedBox(width: 100.rpx,child: value == group? Icon(JudgesIcon.radioYes,size: 34.rpx,color: ColorUtil.stringColor('#4FCD3E'),): Icon(JudgesIcon.radioNot,size: 34.rpx,color: ColorUtil.stringColor('#CCCCCC'),),),],),),);}// 支付方式iconWidget payIcon() {if (value == PayMethodType.alipay) {return Padding(padding: EdgeInsets.only(right: 20.rpx),child: Icon(JudgesIcon.payAli,size: 48.rpx,color: ColorUtil.stringColor('00a0ea'),),);} else {return Padding(padding: EdgeInsets.only(right: 20.rpx),child: Image.asset('${AppGlobal.imgUrl}beiby.png',height: 48.rpx,fit: BoxFit.fitHeight,),);}}
}

相关文章:

  • Flutter - 集成三方库:数据库(sqflite)
  • AbMole| PEG300 (CAS号25322-68-3;目录号M9292)
  • 缺乏进度跟踪机制,如何掌握项目状态?
  • 从ISO17025合规到信创适配 解密质检lims系统实验室的 AI 质检全链路实践
  • ChimeraX介绍
  • C++初阶-迭代器失效和vector::insert函数的最终实现
  • workflow:高效的流式工作架构
  • day31python打卡
  • c++使用protocol buffers
  • DeepSeek R2 或将发布,压力给到梁文锋
  • MySQL中添加一个具有创建数据库权限的用户
  • layui 介绍
  • SpringBean模块(三)具有生命周期管理能力的类(1)AutowireCapableBeanFactory
  • JAVA基础——方法和类型转换
  • 操作系统————四种动态分区分配算法详解(首次适应,最坏适应,最佳适应,邻近适应)
  • 【Java高阶面经:微服务篇】3.熔断机制深度优化:从抖动治理到微服务高可用架构实战
  • Python Day27 学习
  • Linux僵死进程以及文件操作
  • LW-CTrans:一种用于三维医学图像分割的轻量级CNN与Transformer混合网络|文献速递-深度学习医疗AI最新文献
  • RFID技术在半导体晶圆卡塞盒中的应用方案
  • 顶刊论文现“飙脏话辱骂第二作者”,期刊回应:正积极调查
  • 中国海警就菲向非法“坐滩”仁爱礁军舰运补发表谈话
  • 在越剧之乡嵊州,浙江音乐学院越剧学院成立
  • 戛纳参赛片《爱丁顿》评论两极,导演:在这个世道不奇怪
  • 上海肺科医院院长陈昶:临床中的痛点,正是新技术诞生的起点
  • 中国证监会副主席李明:目前A股估值水平仍处于相对低位