Flutter自定义弹窗Dialog效果
更新时间:2022年03月23日 15:09:29 作者:antu58
这篇文章主要为大家详细介绍了Flutter自定义弹窗Dialog效果,含底部抽屉,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
本文实例为大家分享了Flutter自定义弹窗Dialog效果的具体代码,供大家参考,具体内容如下
主要是基于系统的dialog机制做一些使用限制和自定义UI的优化
核心代码:
class CustomDialog { static void show(BuildContext context, Widget Function(BuildContext ctx, void Function() dismiss)builder, {bool cancellable = false}) { showDialog( context: context, barrierDismissible: cancellable, builder: (ctx) { return WillPopScope( child: Dialog( child: builder(ctx, () => Navigator.of(ctx).pop()), backgroundColor: Colors.transparent, shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(0.0))), elevation: 0, alignment: Alignment.center, ), onWillPop: () async => cancellable, ); }, ); } static void showBottomSheet(BuildContext context, Widget Function(BuildContext ctx, void Function() dismiss)builder, {bool cancellable = true}) { showModalBottomSheet( context: context, isDismissible: cancellable, enableDrag: cancellable, isScrollControlled: true, builder: (BuildContext ctx) { return WillPopScope( child: builder(ctx, () => Navigator.of(ctx).pop()), onWillPop: () async => cancellable, ); }, //不设置会默认使用屏幕最大宽度而不是子组件宽度 constraints: const BoxConstraints(minWidth: 0, minHeight: 0, maxWidth: double.infinity, maxHeight: double.infinity), backgroundColor: Colors.transparent, ); } }
使用:
import 'dart:async'; import 'package:flutter/material.dart'; class DialogTestPage extends StatefulWidget { const DialogTestPage({Key? key}) : super(key: key); @override State<StatefulWidget> createState() => _DialogTestState(); } class _DialogTestState extends State<DialogTestPage> { @override Widget build(BuildContext context) { return Scaffold( body: Column(children: [ const SizedBox(height: 0, width: double.infinity,), TextButton( child: const Text("show dialog"), onPressed: () => showCustomDialog(), ), TextButton( child: const Text("show delay dialog"), onPressed: () => showDelayDialog(), ), TextButton( child: const Text("show sheet"), onPressed: () => showSheetDialog(), ), ], mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.center,), ); } void showCustomDialog() { CustomDialog.show(context, (context, dismiss) { return Container( width: 200, height: 100, color: Colors.white, child: Center(child: TextButton(onPressed: () => dismiss(), child: const Text("POP")),), ); }); } void showSheetDialog() { CustomDialog.showBottomSheet(context, (ctx, dismiss) { return Container( height: 300, color: Colors.white, child: Center(child: TextButton(onPressed: () => dismiss(), child: const Text("POP")),), margin: const EdgeInsets.all(20), ); }); } void showDelayDialog() { CustomDialog.show(context, (context, dismiss) { //延时关闭 Timer(const Duration(seconds: 2), () => dismiss()); return Container( width: 200, height: 100, color: Colors.yellow, child: const Center(child: Text("等待"),), ); }, cancellable: true); } }
其中show方法中使用到的Dialog默认使用material组件库的,如果觉得有不合理的尺寸约束,可替换我修改过的Dialog组件,有其他需求也可在此定制,为什么不直接放弃使用此组件?主要涉及到其路由跳转中的一些动画布局之类的。
class Dialog extends StatelessWidget { const Dialog({ Key? key, this.backgroundColor, this.elevation, this.insetAnimationDuration = const Duration(milliseconds: 100), this.insetAnimationCurve = Curves.decelerate, this.insetPadding = const EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0), this.clipBehavior = Clip.none, this.shape, this.alignment, this.child, }) : super(key: key); final Color? backgroundColor; final double? elevation; final Duration insetAnimationDuration; final Curve insetAnimationCurve; final EdgeInsets? insetPadding; final Clip clipBehavior; final ShapeBorder? shape; final AlignmentGeometry? alignment; final Widget? child; static const RoundedRectangleBorder _defaultDialogShape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))); static const double _defaultElevation = 24.0; @override Widget build(BuildContext context) { final DialogTheme dialogTheme = DialogTheme.of(context); final EdgeInsets effectivePadding = MediaQuery.of(context).viewInsets + (insetPadding ?? EdgeInsets.zero); return AnimatedPadding( padding: effectivePadding, duration: insetAnimationDuration, curve: insetAnimationCurve, child: MediaQuery.removeViewInsets( removeLeft: true, removeTop: true, removeRight: true, removeBottom: true, context: context, child: Align( alignment: alignment ?? dialogTheme.alignment ?? Alignment.center, child: Material( color: backgroundColor ?? dialogTheme.backgroundColor ?? Theme.of(context).dialogBackgroundColor, elevation: elevation ?? dialogTheme.elevation ?? _defaultElevation, shape: shape ?? dialogTheme.shape ?? _defaultDialogShape, type: MaterialType.card, clipBehavior: clipBehavior, child: child, ), ), ), ); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
相关文章
Android编程开发ScrollView中ViewPager无法正常滑动问题解决方法
这篇文章主要介绍了Android编程开发ScrollView中ViewPager无法正常滑动问题解决方法,以实例形式分析了ScrollView中滑动失效的原因及解决方法,具有一定参考借鉴价值,需要的朋友可以参考下2015-10-10Android 滑动小圆点ViewPager的两种设置方法详解流程
Viewpager,视图翻页工具,提供了多页面切换的效果。Android 3.0后引入的一个UI控件,位于v4包中。低版本使用需要导入v4包,现在我们一般不再兼容3.0及以下版本,另外使用Android studio开发,默认导入v7包,v7包含了v4,所以不用导包,越来越方便了2021-11-11使用Android系统提供的DownloadManager来下载文件
本篇文章主要介绍了使用Android系统提供的DownloadManager来下载文件,可以将长时间的下载任务交给系统,完全由系统管理,有需要的可以了解下。2016-11-11item高度不同时Recyclerview获取滑动距离的方法
这篇文章主要介绍了item高度不同时Recyclerview获取滑动距离的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2018-11-11
最新评论