Flutter CupertinoDatePicker null check error on _minScrollExtent in scroll_position.dart

34 Views Asked by At

I have a list of times that are representing breakslots. They are adjustable with the CupertinoDatePicker on a BottomSheet. Every time i try to add a new breakslot with a CupertinoDatePicker i get following error. In Debug Mode it leads me to the Scroll_position.dart and shows me that the _minScrollExtent is null but has a null check (!). Anyone ideas or suggestions how to fix that?

The following _TypeError was thrown building CupertinoDatePicker(dependencies: [Directionality,
MediaQuery, _InheritedCupertinoTheme, _LocalizationsScope-[GlobalKey#45bfe]], state:
_CupertinoDatePickerDateTimeState#e45f1):
Null check operator used on a null value

The relevant error-causing widget was:
  CupertinoDatePicker
  CupertinoDatePicker:file:///Users/jordanruff/Prio/prio_app/lib/TimeKeeping/components/timekeeping_day_editor.dart:337:24

When the exception was thrown, this was the stack:
#0      ScrollPosition.minScrollExtent (package:flutter/src/widgets/scroll_position.dart:226:49)
#1      _FixedExtentScrollPosition.itemIndex (package:flutter/src/widgets/list_wheel_scroll_view.dart:392:24)
#2      FixedExtentScrollController.selectedItem (package:flutter/src/widgets/list_wheel_scroll_view.dart:251:21)
#3      _CupertinoDatePickerDateTimeState._selectedHourIndex (package:flutter/src/cupertino/date_picker.dart:558:76)
#4      _CupertinoDatePickerDateTimeState.selectedHour (package:flutter/src/cupertino/date_picker.dart:557:55)
#5      _CupertinoDatePickerDateTimeState._buildMinutePicker.<anonymous closure> (package:flutter/src/cupertino/date_picker.dart:896:13)
#6      new _GrowableList.generate (dart:core-patch/growable_array.dart:136:28)
#7      _CupertinoDatePickerDateTimeState._buildMinutePicker (package:flutter/src/cupertino/date_picker.dart:889:19)
#8      _CupertinoDatePickerDateTimeState.build (package:flutter/src/cupertino/date_picker.dart:1076:33)
#9      StatefulElement.build (package:flutter/src/widgets/framework.dart:5409:27)
#10     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5297:15)
#11     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5462:11)
#12     Element.rebuild (package:flutter/src/widgets/framework.dart:5016:7)
#13     StatefulElement.update (package:flutter/src/widgets/framework.dart:5485:5)
#14     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#15     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5322:16)
#16     Element.rebuild (package:flutter/src/widgets/framework.dart:5016:7)
#17     ProxyElement.update (package:flutter/src/widgets/framework.dart:5628:5)
#18     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#19     Element.updateChildren (package:flutter/src/widgets/framework.dart:3834:32)
#20     MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6594:17)
#21     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#22     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6441:14)
#23     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#24     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6441:14)
#25     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#26     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5322:16)
#27     Element.rebuild (package:flutter/src/widgets/framework.dart:5016:7)
#28     StatelessElement.update (package:flutter/src/widgets/framework.dart:5373:5)
#29     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#30     Element.updateChildren (package:flutter/src/widgets/framework.dart:3834:32)
#31     MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6594:17)
#32     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#33     Element.updateChildren (package:flutter/src/widgets/framework.dart:3834:32)
#34     MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6594:17)
#35     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#36     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5322:16)
#37     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5462:11)
#38     Element.rebuild (package:flutter/src/widgets/framework.dart:5016:7)
#39     StatefulElement.update (package:flutter/src/widgets/framework.dart:5485:5)
#40     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#41     Element.updateChildren (package:flutter/src/widgets/framework.dart:3834:32)
#42     MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6594:17)
#43     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#44     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6441:14)
#45     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#46     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5322:16)
#47     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5462:11)
#48     Element.rebuild (package:flutter/src/widgets/framework.dart:5016:7)
#49     StatefulElement.update (package:flutter/src/widgets/framework.dart:5485:5)
#50     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#51     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6441:14)
#52     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#53     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6441:14)
#54     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#55     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6441:14)
#56     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#57     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6441:14)
#58     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#59     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6441:14)
#60     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#61     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5322:16)
#62     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5462:11)
#63     Element.rebuild (package:flutter/src/widgets/framework.dart:5016:7)
#64     StatefulElement.update (package:flutter/src/widgets/framework.dart:5485:5)
#65     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#66     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6441:14)
#67     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#68     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5322:16)
#69     Element.rebuild (package:flutter/src/widgets/framework.dart:5016:7)
#70     ProxyElement.update (package:flutter/src/widgets/framework.dart:5628:5)
#71     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#72     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6441:14)
#73     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#74     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5322:16)
#75     Element.rebuild (package:flutter/src/widgets/framework.dart:5016:7)
#76     ProxyElement.update (package:flutter/src/widgets/framework.dart:5628:5)
#77     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#78     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5322:16)
#79     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5462:11)
#80     Element.rebuild (package:flutter/src/widgets/framework.dart:5016:7)
#81     StatefulElement.update (package:flutter/src/widgets/framework.dart:5485:5)
#82     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#83     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5322:16)
#84     Element.rebuild (package:flutter/src/widgets/framework.dart:5016:7)
#85     ProxyElement.update (package:flutter/src/widgets/framework.dart:5628:5)
#86     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#87     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5322:16)
#88     Element.rebuild (package:flutter/src/widgets/framework.dart:5016:7)
#89     StatelessElement.update (package:flutter/src/widgets/framework.dart:5373:5)
#90     Element.updateChild (package:flutter/src/widgets/framework.dart:3685:15)
#91     _LayoutBuilderElement._layout.layoutCallback (package:flutter/src/widgets/layout_builder.dart:135:18)
#92     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2719:19)
#93     _LayoutBuilderElement._layout (package:flutter/src/widgets/layout_builder.dart:153:12)
#94     RenderObject.invokeLayoutCallback.<anonymous closure> (package:flutter/src/rendering/object.dart:2604:59)
#95     PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:1059:15)
#96     RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2604:14)
#97     RenderConstrainedLayoutBuilder.rebuildIfNecessary (package:flutter/src/widgets/layout_builder.dart:228:7)
#98     _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:313:5)
#99     RenderObject.layout (package:flutter/src/rendering/object.dart:2493:7)
#100    RenderBox.layout (package:flutter/src/rendering/box.dart:2382:11)
#101    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:104:21)
#102    RenderObject.layout (package:flutter/src/rendering/object.dart:2493:7)
#103    RenderBox.layout (package:flutter/src/rendering/box.dart:2382:11)
#104    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:104:21)
#105    RenderCustomPaint.performLayout (package:flutter/src/rendering/custom_paint.dart:554:11)
#106    RenderObject.layout (package:flutter/src/rendering/object.dart:2493:7)
#107    RenderBox.layout (package:flutter/src/rendering/box.dart:2382:11)
#108    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:104:21)
#109    _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1431:11)
#110    RenderObject.layout (package:flutter/src/rendering/object.dart:2493:7)
#111    RenderBox.layout (package:flutter/src/rendering/box.dart:2382:11)
#112    RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:104:21)
#113    RenderObject.layout (package:flutter/src/rendering/object.dart:2493:7)
#114    RenderBox.layout (package:flutter/src/rendering/box.dart:2382:11)
#115    _RenderBottomSheetLayoutWithSizeListener.performLayout (package:flutter/src/material/bottom_sheet.dart:614:14)
#116    RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:2332:7)
#117    PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1013:18)
#118    RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:494:19)
#119    WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:918:13)
#120    RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:360:5)
#121    SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1297:15)
#122    SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1227:9)
#123    SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1085:5)
#124    _invoke (dart:ui/hooks.dart:170:13)
#125    PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:401:5)
#126    _drawFrame (dart:ui/hooks.dart:140:31)

This is the CodeSnippet of the "breakslots" with the CupertinoPicker:

 Widget _buildBreakSlot(BreakSlot breakSlot) {
    final error = _breakSlotErrors[breakSlot.index];

    String errorMessage = '';
    if (error != null) {
      switch (error) {
        case _BreakSlotError.overlapsWithOtherBreak:
          errorMessage = AppLocalizations.of(context).timeKeepingBreakOverlaps;
          break;
        case _BreakSlotError.tooCloseToWorkStart:
          errorMessage = AppLocalizations.of(context).timeKeepingBreakTooCloseToWorkStart;
          break;
        case _BreakSlotError.tooCloseToWorkEnd:
          errorMessage = AppLocalizations.of(context).timeKeepingBreakTooCloseToWorkEnd;
          break;
      }
    }

    return Column(
      children: [
        InkWell(
            onTap: () {
              setState(() {
                if (currentEditingBreaktimeIndex != null &&
                    currentEditingBreaktimeIndex == breakSlot.index &&
                    !editWorktime) {
                  currentEditingBreaktimeIndex = null;
                } else {
                  editWorktime = false;
                  currentEditingBreaktimeIndex = breakSlot.index;
                }
              });
            },
            child: Ink(
              child: _buildTimeHeader(
                context,
                'Pause',
                breakSlot.startTime,
                breakSlot.endTime,
                currentEditingBreaktimeIndex != null && currentEditingBreaktimeIndex == breakSlot.index,
              ),
            )),
        const Divider(
          height: 0.5,
        ),
        AnimatedSize(
          duration: const Duration(milliseconds: 300),
          child: Container(
            alignment: Alignment.centerLeft,
            height: currentEditingBreaktimeIndex != null && currentEditingBreaktimeIndex == breakSlot.index
                ? 150.0
                : 0.0001,
            child: Row(
              children: [
                Expanded(
                  child: CupertinoDatePicker(
                    mode: CupertinoDatePickerMode.time,
                    minuteInterval: timeSlotDurationInMinutes,
                    initialDateTime: breakSlot.startTime,
                    onDateTimeChanged: (DateTime value) {
                      setState(() {
                        //_value = _value.withStartDateTime(value);
                      });
                      //widget.onChanged(_value);
                      // _newValue = value;
                    },
                    use24hFormat: true,
                  ),
                ),
                Expanded(
                  child: CupertinoDatePicker(
                    mode: CupertinoDatePickerMode.time,
                    minuteInterval: timeSlotDurationInMinutes,
                    initialDateTime: breakSlot.endTime,
                    onDateTimeChanged: (DateTime value) {
                      setState(() {
                        //_value = _value.withEndDateTime(value);
                      });
                      //widget.onChanged(_value);
                      // _newValue = value;
                    },
                    use24hFormat: true,
                  ),
                ),
              ],
            ),
          ),
        ),
        AnimatedSize(
          duration: const Duration(milliseconds: 500),
          child: Container(
            alignment: Alignment.centerLeft,
            height: 0.0,
            child: Text(
              errorMessage,
              style: TextStyle(color: Theme.of(context).colorScheme.error),
            ),
          ),
        )
      ],
    );
  }

And this where i show it with a list of breakSlot items:

@override
  Widget build(BuildContext context) {
    final breakSlots = _value.breakSlots;

    return Column(
      children: [
        const Divider(
          height: 0.5,
        ),
        InkWell(
          onTap: () {
            setState(() {
              if (!editWorktime) {
                currentEditingBreaktimeIndex = null;
                editWorktime = true;
              } else {
                editWorktime = false;
              }
            });
          },
          child: Ink(
            child: _buildTimeHeader(context, 'Arbeitszeit', _value.startDateTime!, _value.endDateTime!, editWorktime),
          ),
        ),
        const Divider(
          height: 0.5,
        ),
        AnimatedSize(
          duration: const Duration(milliseconds: 300),
          child: Container(
            alignment: Alignment.centerLeft,
            height: editWorktime ? 150.0 : 0.0001,
            child: Row(
              children: [
                Expanded(
                  child: CupertinoDatePicker(
                    mode: CupertinoDatePickerMode.time,
                    minuteInterval: timeSlotDurationInMinutes,
                    initialDateTime: _value.startDateTime ??
                        DateTime.now().copyWith(hour: 8, minute: 0, second: 0, millisecond: 0, microsecond: 0),
                    onDateTimeChanged: (DateTime value) {
                      setState(() {
                        _value = _value.withStartDateTime(value);
                      });
                      widget.onChanged(_value);
                      // _newValue = value;
                    },
                    use24hFormat: true,
                  ),
                ),
                Expanded(
                  child: CupertinoDatePicker(
                    mode: CupertinoDatePickerMode.time,
                    minuteInterval: timeSlotDurationInMinutes,
                    initialDateTime: _value.endDateTime ??
                        DateTime.now().copyWith(hour: 16, minute: 30, second: 0, millisecond: 0, microsecond: 0),
                    onDateTimeChanged: (DateTime value) {
                      setState(() {
                        _value = _value.withEndDateTime(value);
                      });
                      widget.onChanged(_value);
                      // _newValue = value;
                    },
                    use24hFormat: true,
                  ),
                ),
              ],
            ),
          ),
        ),
        for (var breakSlot in _value.breakSlots) _buildBreakSlot(breakSlot),

        ListTile(
            onTap: () {
              widget.onChanged(_value);
              setState(() {
                _value = _value.addBreakSlot();
                currentEditingBreaktimeIndex = _value.breakSlots.last.index;
              });
            },
            title: Row(
              children: [
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 8.0),
                  child: FaIcon(
                    FontAwesomeIcons.lightPlus,
                    size: 16.0,
                    color: Theme.of(context).colorScheme.secondary,
                  ),
                ),
                Text(
                  'Pause',
                  style: TextStyle(color: Theme.of(context).colorScheme.secondary),
                ),
              ],
            )),
      ],
    );
  }

Null check is shown me in scroll_position.dart:226

/// Where the scrolling is taking place.
  ///
  /// Typically implemented by [ScrollableState].
  final ScrollContext context;

  /// Save the current scroll offset with [PageStorage] and restore it if
  /// this scroll position's scrollable is recreated.
  ///
  /// See also:
  ///
  ///  * [ScrollController.keepScrollOffset] and [PageController.keepPage], which
  ///    create scroll positions and initialize this property.
  // TODO(goderbauer): Deprecate this when state restoration supports all features of PageStorage.
  final bool keepScrollOffset;

  /// A label that is used in the [toString] output.
  ///
  /// Intended to aid with identifying animation controller instances in debug
  /// output.
  final String? debugLabel;

  @override
  double get minScrollExtent => _minScrollExtent!;
  double? _minScrollExtent;

  @override
  double get maxScrollExtent => _maxScrollExtent!;
  double? _maxScrollExtent;

  @override
  bool get hasContentDimensions => _minScrollExtent != null && _maxScrollExtent != null;
```


I tried many things like, wrap the CupertinoDatePicker directly into a SizedBox with height or removed the AnimatedSize-Widget and some other stuff, but i have the feeling that its a bug inside of the CupertinoDatePicker in Flutter itself.
0

There are 0 best solutions below