Flutter中SfCalendar资源行高度调整及固定顶部问题求助
解决方案
一、调整资源行高度以完整显示预约内容
SfCalendar的资源行高度无法通过resourceHeaderBuilder内部容器高度直接控制,需使用组件内置的resourceViewSettings配置项,搭配自定义预约布局实现文本完整展示:
- 在
SfCalendar中添加资源视图高度配置:
return SfCalendar( showDatePickerButton: true, controller: _calendarController, allowDragAndDrop: true, allowedViews: _allowedViews, minDate: _minDate, timeRegionBuilder: _getSpecialRegionWidget, specialRegions: _specialTimeRegions, showNavigationArrow: true, dataSource: _calendarDataSource, onViewChanged: viewChangedCallback, resourceViewHeaderBuilder: _resourceHeaderBuilder, appointmentTimeTextFormat: 'HH:mm', // 添加资源视图高度设置 resourceViewSettings: const ResourceViewSettings( resourceHeight: 220, // 根据实际需求调整高度值 ), timeSlotViewSettings: const TimeSlotViewSettings( timeInterval: Duration(minutes: 15), timeFormat: 'HH:mm', startHour: 7, endHour: 18, ), // 自定义预约布局,实现文本自动换行 appointmentBuilder: (context, details) { return Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4), child: Text( details.appointments.first.subject, maxLines: null, overflow: TextOverflow.visible, style: const TextStyle(fontSize: 12), ), ); }, );
二、将"N/A"资源行固定在顶部
通过拆分资源列表、组合固定区域与滚动日历的方式实现固定效果,同时保留拖拽交互能力:
- 拆分资源数据源:
// 从原始资源列表中分离N/A资源与其他资源 final Resource nonAssignedResource = _resources.firstWhere((r) => r.displayName == "N/A"); final List<Resource> scrollableResources = _resources.where((r) => r.displayName != "N/A").toList();
- 构建固定顶部+滚动日历的组合布局:
return Column( children: [ // 顶部固定的N/A资源行 _buildFixedNonAssignedHeader(nonAssignedResource), // 下方滚动的其他资源日历 Expanded( child: SfCalendar( // 复用原有配置,仅替换资源列表 showDatePickerButton: true, controller: _calendarController, allowDragAndDrop: true, allowedViews: _allowedViews, minDate: _minDate, timeRegionBuilder: _getSpecialRegionWidget, specialRegions: _specialTimeRegions, showNavigationArrow: true, dataSource: _calendarDataSource..resources = scrollableResources, onViewChanged: viewChangedCallback, resourceViewHeaderBuilder: _resourceHeaderBuilder, appointmentTimeTextFormat: 'HH:mm', resourceViewSettings: const ResourceViewSettings( resourceHeight: 220, // 与固定行高度保持一致 ), timeSlotViewSettings: const TimeSlotViewSettings( timeInterval: Duration(minutes: 15), timeFormat: 'HH:mm', startHour: 7, endHour: 18, ), appointmentBuilder: (context, details) { return Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4), child: Text( details.appointments.first.subject, maxLines: null, overflow: TextOverflow.visible, style: const TextStyle(fontSize: 12), ), ); }, ), ), ], );
- 实现固定行的构建函数(含拖拽触发逻辑):
Widget _buildFixedNonAssignedHeader(Resource resource) { int capacity = _visibleAppointments.where((app) => app.resourceIds != null && app.resourceIds!.contains(resource.id) ).length; return Container( height: 220, color: resource.color, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ icons[Random().nextInt(5)], Text( resource.displayName, style: const TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold), ), Padding( padding: const EdgeInsets.only(top: 5), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: const <Widget>[ Text( 'Termine: ', textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 10, ), ), Text( capacity.toString(), textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold), ), ], ), ), // 展示N/A资源下的预约,支持长按拖拽 Expanded( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), child: Column( children: _visibleAppointments .where((app) => app.resourceIds != null && app.resourceIds!.contains(resource.id) ) .map((app) => GestureDetector( onLongPressStart: (details) { _calendarController.startAppointmentDrag(app, details.globalPosition); }, child: Container( margin: const EdgeInsets.only(bottom: 4), padding: const EdgeInsets.all(6), color: Colors.white.withOpacity(0.2), child: Text( app.subject, maxLines: null, style: const TextStyle(color: Colors.white, fontSize: 12), ), ), )) .toList(), ), ), ), ], ), ); }
内容的提问来源于stack exchange,提问作者Lukas Fürst
相关产品推荐
相关产品推荐

