Implementation
static Future<void> makeDialog(BuildContext buildContext, String sendId,
String surveyId, String channelId,
{Map<String, dynamic> parameters = const {},
Map<String, dynamic> options = const {},
VoidCallback? onCancel,
VoidCallback? onSubmit,
ErrorCallback? onError,
VoidCallback? onClose}) async {
if ((sendId.isEmpty && (surveyId.isEmpty || channelId.isEmpty))) {
LoggerService.error(
"invalid parameter please check sendid sid $sendId, surveyId $surveyId and channelId $channelId");
return;
}
ServiceContext serviceContext = ServiceContext();
SurveyModel survey;
try {
survey = await serviceContext.unionStart(
sendId, surveyId, channelId, parameters);
} catch (e) {
LoggerService.error("unionStart failed: $e");
onError?.call(e.toString());
return;
}
Alignment alignment = Alignment.bottomCenter;
switch (survey.channelConfig!.embedVerticalAlign) {
case 'BOTTOM':
alignment = Alignment.bottomCenter;
break;
case 'TOP':
alignment = Alignment.topCenter;
break;
case 'CENTER':
alignment = Alignment.center;
break;
default:
}
// survey.channelConfig.embedHeightMode
// showAlignedDialog
return showGeneralDialog(
context: buildContext,
useRootNavigator: false,
barrierColor: survey.channelConfig!.embedBackGround
? Colors.black54
: Colors.transparent, // Background color based on config
barrierDismissible: options['clickDismiss'] ?? false,
transitionDuration: const Duration(milliseconds: 300),
transitionBuilder: (context, animation, secondaryAnimation, child) {
// 根据对齐方式选择不同的动画效果
switch (survey.channelConfig!.embedVerticalAlign) {
case 'BOTTOM':
// 底部向上滑入
final offsetAnimation = Tween<Offset>(
begin: const Offset(0.0, 1.0), // 从下方开始
end: Offset.zero,
).animate(CurvedAnimation(
parent: animation,
curve: Curves.easeOutCubic,
));
return SlideTransition(
position: offsetAnimation,
child: child,
);
case 'TOP':
// 顶部向下滑入
final offsetAnimation = Tween<Offset>(
begin: const Offset(0.0, -1.0), // 从上方开始
end: Offset.zero,
).animate(CurvedAnimation(
parent: animation,
curve: Curves.easeOutCubic,
));
return SlideTransition(
position: offsetAnimation,
child: child,
);
default:
// CENTER: 默认淡入淡出
return FadeTransition(
opacity: CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
),
child: child,
);
}
},
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
// ignore: deprecated_member_use
return WillPopScope(
// 使用 WillPopScope 以兼容 Flutter 3.7.8+
// PopScope 需要 Flutter 3.16+,暂不迁移以保持向后兼容性
onWillPop: () async {
// 处理返回键事件
Navigator.of(context).pop('normal_close');
return false; // 返回 false 拦截系统的 pop 行为
},
child: Align(
alignment: alignment,
child: SafeArea(
top: alignment == Alignment.topCenter, // 顶部对齐时启用顶部安全区域
bottom: alignment == Alignment.bottomCenter, // 底部对齐时启用底部安全区域
left: true, // 始终保留横向安全区域
right: true,
minimum: EdgeInsets.symmetric(
horizontal: survey.channelConfig!.appPaddingWidth,
),
child: Material(
color: Colors
.transparent, // Transparent background for custom styling
child: KeyboardAwareDialog(
embedHeight: survey.channelConfig!.embedHeight,
embedHeightMode: survey.channelConfig!.embedHeightMode,
child: Container(
margin: EdgeInsets.symmetric(
horizontal: survey.channelConfig!.appPaddingWidth,
),
decoration: BoxDecoration(
color: survey.style.backgroundColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(
survey.channelConfig!.embedVerticalAlign != 'TOP'
? survey.channelConfig!.appBorderRadius
: 0),
topRight: Radius.circular(
survey.channelConfig!.embedVerticalAlign != 'TOP'
? survey.channelConfig!.appBorderRadius
: 0),
bottomLeft: Radius.circular(
survey.channelConfig!.embedVerticalAlign !=
'BOTTOM'
? survey.channelConfig!.appBorderRadius
: 0),
bottomRight: Radius.circular(
survey.channelConfig!.embedVerticalAlign !=
'BOTTOM'
? survey.channelConfig!.appBorderRadius
: 0),
),
),
child: ChangeNotifierProvider<ServiceContext>.value(
value: serviceContext,
child: Stack(
children: [
SingleChildScrollView(
physics: const ClampingScrollPhysics(), // 防止弹性滚动
keyboardDismissBehavior:
ScrollViewKeyboardDismissBehavior
.manual, // 防止滚动时关闭键盘
child: HySurveyWidget(
key: ValueKey('survey_${survey.clientId}'),
sendId: sendId,
surveyId: surveyId,
channelId: channelId,
showClose: false,
isDialog: true,
onCancel: () {
Navigator.pop(context, 'normal_close');
},
onClose: () {
Navigator.pop(context, 'normal_close');
},
onSubmit: onSubmit,
onError: onError,
),
),
if (!options.containsKey("showClose") ||
options["showClose"] == true)
Positioned(
right: 2,
top: 2,
child: SurveyCloseWidget(
onClose: () {
Navigator.pop(context, 'normal_close');
},
),
),
],
),
),
),
)),
),
),
);
},
).then((value) {
onClose?.call();
});
}