Flutter中SfDateRangePicker结合bottom_sheet在release模式报错
问题根因
你看到的Another exception was thrown: Instance of 'DiagnosticsProperty'不是具体业务错误,是Flutter release模式下没有对异常信息做格式化输出导致的通用提示,真实触发原因有三个:
- 你在
showModalBottomSheet的builder外部获取了Theme、MediaQuery这类依赖上下文的对象,release模式树摇优化后,跨元素树查找InheritedWidget会失败,触发空引用 - 外层Column没有设置
mainAxisSize: MainAxisSize.min,结合写死的heightFactor: h/950、height: h/1.5这类基于全屏高度的固定尺寸计算,在bottom sheet的受限布局空间内会触发渲染越界 - 代码中使用了已被新版Flutter废弃的
textTheme.headline1字段,release模式下主题字段映射失效后会返回null,传入SfDateRangePicker时触发组件内部的空校验异常
修复方案
按以下顺序调整代码即可解决release模式下的报错:
- 把所有依赖BuildContext的Theme、MediaQuery获取逻辑,移到
showModalBottomSheet的builder内部,确保拿的是弹窗所在元素树的上下文 - 给弹窗内的Column设置
mainAxisSize: MainAxisSize.min,禁止组件默认撑满全屏高度;删除写死的FractionallySizedBox高度计算,改用Padding处理安全区、键盘弹出边距 - 替换所有废弃的
headline1文本样式字段,用当前Theme下有效存在的文本样式字段(如bodyLarge、labelLarge),避免空值 - 用
Expanded包裹SfDateRangePicker,让组件自动适配Column内的剩余可用空间,不要写死h/1.5这类跨设备不兼容的固定高度 - 给
showModalBottomSheet开启useSafeArea: true,避免系统状态栏、虚拟导航栏遮挡布局触发越界
修复后可运行代码
Future<void> dIALOG2() { return showModalBottomSheet<void>( isScrollControlled: true, context: context, elevation: 0, useSafeArea: true, builder: (BuildContext context) { // 上下文依赖对象全部移到builder内部获取 TextTheme _textthem = Theme.of(context).textTheme; final mediaQuery = MediaQuery.of(context); final w = mediaQuery.size.width; final h = mediaQuery.size.height; return Padding( // 适配键盘弹出时的边距 padding: EdgeInsets.only(bottom: mediaQuery.viewInsets.bottom), child: Column( // 关键:列布局只包裹内容本身高度,不强制撑满 mainAxisSize: MainAxisSize.min, children: [ Padding( padding: EdgeInsets.only(top: h / 50), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ SizedBox( width: w / 2, child: Text( 'Bubble Duration:', textAlign: TextAlign.left, style: _textthem.headlineLarge!.copyWith( fontFamily: 'Red Hat Display', fontSize: 18, letterSpacing: 0.4, fontWeight: FontWeight.w600, height: 1 ), ), ), const SizedBox.shrink(), ], ), ), const SizedBox(height: 16), Container( color: const Color(0xff942657), width: w, height: h / 180, ), // 用Expanded让日期选择器自适应剩余高度 Expanded( child: SizedBox( width: w / 1.2, child: SfDateRangePicker( monthCellStyle: DateRangePickerMonthCellStyle( // 替换废弃的headline1字段 textStyle: _textthem.bodyLarge!.copyWith( fontSize: 14, letterSpacing: 0.22, fontWeight: FontWeight.normal, height: 1.57 ), disabledDatesTextStyle: _textthem.bodyLarge!.copyWith( color: const Color.fromRGBO(96, 96, 96, 1), fontSize: 14, letterSpacing: 0.22, fontWeight: FontWeight.normal, height: 1.57 ), ), controller: _pickerController, showNavigationArrow: true, toggleDaySelection: true, rangeSelectionColor: const Color(0xffCF6D38), endRangeSelectionColor: const Color(0xffA83063), onSelectionChanged: _onSelectionChanged2, startRangeSelectionColor: const Color(0xffA83063), view: DateRangePickerView.month, selectionMode: DateRangePickerSelectionMode.range, ), ), ), InkWell( onTap: () { if (STartTime == "" || EndTime == "") { Navigator.pop(context); } else { _OptionsBloc.add(ChangeDone1((b) => b..DoneColor1 = true)); Navigator.pop(context); } }, child: Container( width: w / 2, height: h / 16, decoration: const BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(7)), color: Color.fromRGBO(148, 38, 87, 1), ), child: Center( child: Text( 'Confirm', textAlign: TextAlign.center, // 替换废弃的headline1字段,补充文字颜色避免和背景同色 style: _textthem.labelLarge!.copyWith(color: Colors.white), ), ), ), ), const SizedBox(height: 10), ], ), ); } ); }
补充验证
如果调整后仍有报错,可以先把syncfusion_flutter_datepicker依赖升级到最新稳定版,早期版本确实存在release模式下嵌入BottomSheet时的布局计算已知问题。debug模式下正常、release模式报错的场景,90%以上都是跨上下文获取对象、写死尺寸导致的布局越界、空对象引用三类问题,和组件本身的逻辑无关。
内容的提问来源于stack exchange,提问作者Saed Younis
相关产品推荐
相关产品推荐

