dbenitez-bcn / solid_bottom_sheet

Apache License 2.0
58 stars 19 forks source link

Error when i setState inside SolidBottomSheet widget: setState() or markNeedsBuild() called during build. #9

Closed dvlj closed 4 years ago

dvlj commented 5 years ago

flutter: phase only if one of its ancestors is currently building. This exception is allowed because the flutter: framework builds parent widgets before children, which means a dirty descendant will always be flutter: built. Otherwise, the framework might not visit this widget during this build phase. flutter: The widget on which setState() or markNeedsBuild() was called was: flutter: SolidBottomSheet flutter: The widget which was currently being built when the offending call was made was: flutter: _InheritedResetNotifier

sample code:

Widget build(BuildContext context) {
    return Scaffold(
      body: _getImageLayer(),
      bottomSheet: SolidBottomSheet(
        controller: _controller,
        minHeight: MediaQuery.of(context).size.height * 0.7,
        maxHeight: MediaQuery.of(context).size.height * 0.9,
        body: _getMenuLayer(),
      ),
    );
  }
  Widget _getMenuLayer() {
    return Container(
      padding: EdgeInsets.only(top: 20),
      decoration: BoxDecoration(
        color: Colors.cyan[900],
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(25.0),
          topRight: Radius.circular(25.0),
        ),
      ),
      child: NotificationListener<ScrollNotification>(
        onNotification: (scrollNotification) {
          if (scrollNotification is ScrollStartNotification) {
          } else if (scrollNotification is ScrollUpdateNotification) {
            if (scrollNotification.metrics.pixels > _currentPosition) {
              _controller.show();
              setState(() {
                _firstStateEnabled = false;
              });
            }
          } else if (scrollNotification is ScrollEndNotification) {
            if (scrollNotification.metrics.pixels == 0) {
              _controller.hide();
              setState(() {
                _firstStateEnabled = true;
              });
            }
          }
          _currentPosition = scrollNotification.metrics.pixels;
          return true;
        },
        child: CustomScrollView(
          physics: ClampingScrollPhysics(),
          slivers: [
            _itemHeader(),
            _itemAmount(),
            _items(0),
            _items(1),
            _items(2),
            _items(3),
            _itemRemark(),
            _itemBottom(),
          ],
        ),
      ),
    );
  }
dbenitez-bcn commented 5 years ago

I think that the error comes because you are calling setstate() while the building process. Try to avoid this. Maybe the LayoutBuilder can help you.

dvlj commented 5 years ago

Actually, I can call setState() in this code without problem, but when i add SolidController.show() and hide(), it shows error, there must be some kind of conflict between setState and show/hide.

keitoro commented 4 years ago

I have the same issue here when using show or hide.

dbenitez-bcn commented 4 years ago

Sorry Folks, but I can't reproduce this error for the moment. I will keep trying to fix it.

dbenitez-bcn commented 4 years ago

Hi there! I have released a new version which includes an improvement on the internal behaviour of the solid bottom sheet. Could you please update your package and tell me if the issue is fixed? Thanks!

happilii commented 4 years ago

I am currently having the same issue, in onShow & onHide I am attempting to setState(() {}) to a value, however it gives the following error:

════════ Exception caught by foundation library ════════════════════════════════ The following assertion was thrown while dispatching notifications for SolidController: setState() or markNeedsBuild() called during build.

dbenitez-bcn commented 4 years ago

Could you please be more especific and explain me when is the exception thown? I will have a look this weekend

happilii commented 4 years ago
onShow() {
    this.setState(() {
        topPadding = 20.0;
    });
}

I had something like the above code, and everytime the onShow was called it occurred.

dbenitez-bcn commented 4 years ago

The problem is that solid bottom sheet calls the setState by itself, so your code is calling also setState and it throws an exception. A solution that I've found is using streams and streamBuilder widgets. I will add two streams for listening solid bottom sheet's height and visibility and depending on the values you should use one "state" or other on your application.

immobilizer9 commented 4 years ago

hi, can i set a starting height? then set minHeight to 0?

dbenitez-bcn commented 4 years ago

Hello @immobilizer9 Right now you can't set an initial height when the Solid Bottom Sheet widget is created, however you can try to set the height using the SolidController for the moment. I'll try to add a field on the constructor to set the initial height on the next release. I think that could be interesting to have.

immobilizer9 commented 4 years ago

@dbenitez-bcn Thanks for the update! Could you guide me how to use the SolidController to set the initial height? I'm new to this. Thanks again!

dbenitez-bcn commented 4 years ago

You have to create a SolidController SolidController solidController = SolidController(); and then pass it to your SolidBottomSheet widget like this SolidBottomSheet(controller: solidController, /* your other props here */)

and just do solidController.height = 100; and if I did it fine it will change the height automatically.

immobilizer9 commented 4 years ago

Thanks! Will try it and post an update @dbenitez-bcn

immobilizer9 commented 4 years ago

It did set the height to 100 but does not go back down to 0 @dbenitez-bcn

dbenitez-bcn commented 4 years ago

You can use the controller to hide it again