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

Flutter中BottomNavigationBar内嵌SfCalendar在iOS弹窗时出错

解决方案:iOS端SfCalendar与Dialog冲突的渲染错误修复

针对你遇到的iOS端打开带TextFormField的Dialog时,SfCalendar触发RRect断言、重复GlobalKey等错误的问题,以下是针对性修复步骤:

1. 缓存Calendar数据源,避免不必要重建

原代码中每次build都会创建新的MeetingDataSource实例,这会触发SfCalendar频繁更新状态,在iOS的渲染管线中容易引发布局计算异常。将数据源缓存到State中,仅在数据更新时重新生成:

修改_CalendarScreenState:

class _CalendarScreenState extends State<CalendarScreen> with AutomaticKeepAliveClientMixin {
  late MeetingDataSource _calendarDataSource;

  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    super.build(context); // 必须调用,确保AutomaticKeepAlive生效
    return Scaffold(
        appBar: const Appbar(),
        body: Subscription(
            options: SubscriptionOptions(
                document: gql(getCalTasks), variables: ({"user_id": useruid})),
            builder: (result) {
              if (result.isLoading) {
                return const Center(child: CircularProgressIndicator());
              }

              // 仅当tasks变化时更新数据源
              if (!mounted) return const SizedBox();
              final newDataSource = MeetingDataSource(_getDataSource(tasks));
              if (_calendarDataSource.appointments != newDataSource.appointments) {
                _calendarDataSource = newDataSource;
              }

              return SfCalendar(
                  key: const GlobalKey(), // 添加唯一GlobalKey
                  firstDayOfWeek: 1,
                  cellBorderColor: Colors.grey[200],
                  backgroundColor:
                      (Theme.of(context).brightness == Brightness.dark)
                          ? Colors.black
                          : Colors.white,
                  showDatePickerButton: true,
                  view: CalendarView.month,
                  dataSource: _calendarDataSource,
                  monthViewSettings: const MonthViewSettings(
                      agendaViewHeight: 100,
                      agendaItemHeight: 30,
                      showAgenda: true,
                      appointmentDisplayMode:
                          MonthAppointmentDisplayMode.appointment));
            }));
  }
}

2. 修复数据源生成方法的潜在问题

原_getDataSource方法中直接使用events['date'],未确保其为有效DateTime,这可能导致Calendar计算约会布局时出错。添加空值校验和类型转换:

List<Meeting> _getDataSource(List events) {
  final List<Meeting> meetings = <Meeting>[];
  for (int i = 0; i < events.length; i++) {
    final event = events[i];
    // 确保日期有效
    final date = event['date'] is DateTime 
        ? event['date'] as DateTime 
        : DateTime.tryParse(event['date'].toString()) ?? DateTime.now();
    meetings.add(Meeting(
        event['name'] ?? 'Unnamed Event',
        date,
        date,
        colorEntry.value,
        true));
  }
  return meetings;
}

3. 确保Dialog的弹出逻辑不影响Calendar状态

如果Dialog是在其他标签页的Scaffold中弹出,确保使用GlobalKey获取正确的上下文,避免上下文混乱导致的视图树异常:

// 示例:使用GlobalKey获取Scaffold上下文弹出Dialog
final GlobalKey<ScaffoldState> _firstTabScaffoldKey = GlobalKey();

// 第一个标签页的Scaffold
Scaffold(
  key: _firstTabScaffoldKey,
  floatingActionButton: FloatingActionButton(
    onPressed: () {
      showDialog(
        context: _firstTabScaffoldKey.currentContext!,
        builder: (context) => Dialog(
          child: TextFormField(),
        ),
      );
    },
  ),
)

验证步骤

  1. 运行iOS模拟器/真机,切换到Calendar标签页确保数据加载正常
  2. 切换回第一个标签页,点击FloatingActionButton弹出Dialog
  3. 检查控制台是否还有断言错误、重复GlobalKey报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 09:22:06