You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在CupertinoAlertDialog中提示用户输入的邮箱无效?

规范简洁的Cupertino邮箱验证Dialog实现方案

下面是优化后的完整代码,结合Cupertino设计规范和Flutter最佳实践,解决你的输入反馈问题:

// 抽离邮箱验证方法,方便复用和维护
bool isValidEmail(String email) {
  // 标准邮箱正则,覆盖绝大多数合法格式
  final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
  return emailRegex.hasMatch(email);
}

Future showEmailAlertBox(
    Service serv, DateTime date, Duration dur, var price) async {
  bool showError = false; // 控制错误提示的显示状态

  await showDialog(
    context: context,
    barrierDismissible: true,
    builder: (context) {
      // 用StatefulBuilder管理dialog内部状态,避免外部setState无法更新dialog UI
      return StatefulBuilder(
        builder: (context, setState) {
          return CupertinoAlertDialog(
            title: const Text('Enter Email Address to confirm'),
            content: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                CupertinoTextField(
                  controller: emailController,
                  placeholder: 'your@email.com',
                  keyboardType: TextInputType.emailAddress, // 优化输入键盘类型
                  decoration: BoxDecoration(
                    border: Border.all(
                      // 错误时显示Cupertino风格警示红边框
                      color: showError ? CupertinoColors.destructiveRed : CupertinoColors.systemGrey4,
                      width: 1,
                    ),
                    borderRadius: BorderRadius.circular(8),
                  ),
                  onChanged: (_) {
                    // 用户输入时自动隐藏错误提示
                    if (showError) {
                      setState(() => showError = false);
                    }
                  },
                ),
                // 仅在验证失败时显示错误文本
                if (showError)
                  Padding(
                    padding: const EdgeInsets.only(top: 8),
                    child: Text(
                      'Please enter a valid email address',
                      style: TextStyle(
                        color: CupertinoColors.destructiveRed,
                        fontSize: 12,
                      ),
                    ),
                  ),
              ],
            ),
            actions: <CupertinoDialogAction>[
              CupertinoDialogAction(
                isDefaultAction: true,
                onPressed: () async {
                  if (isValidEmail(emailController.text)) {
                    // 执行预订创建逻辑
                    await dbhandler.createBooking(
                      pickeddate,
                      selectedTimeSlot,
                      selectedDurationOption!.duration,
                      selectedService!.title,
                      price,
                    );

                    await getAllBookings();
                    // 更新状态前判断widget是否挂载,避免空状态错误
                    if (!mounted) return;
                    setState(() {
                      availableTimeSlots = getTimeSlots(
                        selectedDurationOption!.duration,
                        pickeddate!,
                        selectedService!,
                      );
                      selectedTimeSlot = '';
                    });
                    _showConfettiAnimation();
                    Navigator.pop(context);
                    emailController.clear(); // 清空输入框,避免残留内容
                  } else {
                    // 触发错误提示状态更新
                    setState(() => showError = true);
                    // 添加触觉反馈,贴合iOS交互习惯(需导入flutter/services.dart)
                    HapticFeedback.mediumImpact();
                  }
                },
                child: const Text('Confirm'),
              ),
              CupertinoDialogAction(
                isDestructiveAction: true,
                onPressed: () {
                  decision = false;
                  emailController.clear();
                  Navigator.pop(context);
                },
                child: const Text('Cancel'),
              ),
            ],
          );
        },
      );
    },
  );
}

核心优化说明

  • 严谨的邮箱验证:替换原有的简单@检查逻辑,用正则覆盖更多无效场景(比如无域名后缀、@在首尾等)。
  • 直观的错误反馈:验证失败时输入框显示红色边框,下方展示明确的错误文本;用户开始输入时自动隐藏错误,提升交互流畅度。
  • 正确的状态管理:使用StatefulBuilder处理dialog内部状态,解决外部setState无法更新dialog UI的问题。
  • 内存与状态清理:操作完成后清空输入框,避免残留旧内容;更新状态前判断mounted,防止widget销毁后触发错误。
  • 细节优化:添加邮箱专用输入键盘,引导用户输入;触发错误时加入触觉反馈,贴合iOS平台交互习惯。

额外建议

如果不想自己维护正则表达式,可以使用email_validator第三方包,但自定义正则已经能覆盖绝大多数场景,可避免不必要的依赖。

内容的提问来源于stack exchange,提问作者Milan Labus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 20:19:52