aryzhov / flutter-expandable

A Flutter widget that can be expanded or collapsed by the user.
MIT License
398 stars 113 forks source link

Build scheduled during frame exception when using the draggable_scrollbar package. #59

Open MostHated opened 4 years ago

MostHated commented 4 years ago

Hey there, I am using this package and love it, but unfortunately, I keep getting this exception. I am not quite sure if it is because of Expandable, or the draggable_scrollbar package. It only occurs when collapsing a card in my list as seen in the clip below: It doesn't occur, though, if it's the top item being expanded and collapsed.

https://i.imgur.com/v2dxj38.mp4

Here is more of the exception:

════════ Exception caught by rendering library ═════════════════════════════════════════════════════
The following assertion was thrown during performLayout():
Build scheduled during frame.

While the widget tree was being built, laid out, and painted, a new frame was scheduled to rebuild the widget tree.

This might be because setState() was called from a layout or paint callback. If a change is needed to the widget tree, it should be applied as the tree is being built. Scheduling a change for the subsequent frame instead results in an interface that lags behind by one frame. If this was done to make your build dependent on a size measured at layout time, consider using a LayoutBuilder, CustomSingleChildLayout, or CustomMultiChildLayout. If, on the other hand, the one frame delay is the desired effect, for example because this is an animation, consider scheduling the frame in a post-frame callback using SchedulerBinding.addPostFrameCallback or using an AnimationController to trigger the animation.

The relevant error-causing widget was: 
  ListView file:///E:/_programming/go/src/github.com/instance-id/searcher_installer_go/lib/routes/news.dart:145:49
When the exception was thrown, this was the stack: 
#0      WidgetsBinding._handleBuildScheduled.<anonymous closure> (package:flutter/src/widgets/binding.dart:734:9)
#1      WidgetsBinding._handleBuildScheduled (package:flutter/src/widgets/binding.dart:757:6)
#2      BuildOwner.scheduleBuildFor (package:flutter/src/widgets/framework.dart:2511:23)
#3      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:4190:11)
#4      State.setState (package:flutter/src/widgets/framework.dart:1253:14)
...
The following RenderObject was being processed when the exception was fired: RenderViewport#3cf44 NEEDS-LAYOUT NEEDS-PAINT
...  needs compositing
...  parentData: <none> (can use size)
...  constraints: BoxConstraints(0.0<=w<=750.6, 0.0<=h<=277.0)
...  layer: OffsetLayer#b4b41
...    engine layer: OffsetEngineLayer#3f7b8
...    offset: Offset(0.0, 0.0)
...  size: Size(750.6, 277.0)
...  axisDirection: down
...  crossAxisDirection: right
...  offset: ScrollPositionWithSingleContext#f0bf4(offset: 186.0, range: 0.0..145.7, viewport: 277.0, ScrollableState, ClampingScrollPhysics, BallisticScrollActivity#acc00(AnimationController#0ab75(▶ 186.000; for BallisticScrollActivity)), ScrollDirection.idle)
...  anchor: 0.0
RenderObject: RenderViewport#3cf44 NEEDS-LAYOUT NEEDS-PAINT
  needs compositing
  parentData: <none> (can use size)
  constraints: BoxConstraints(0.0<=w<=750.6, 0.0<=h<=277.0)
  layer: OffsetLayer#b4b41
    engine layer: OffsetEngineLayer#3f7b8
    offset: Offset(0.0, 0.0)
  size: Size(750.6, 277.0)
  axisDirection: down
  crossAxisDirection: right
  offset: ScrollPositionWithSingleContext#f0bf4(offset: 186.0, range: 0.0..145.7, viewport: 277.0, ScrollableState, ClampingScrollPhysics, BallisticScrollActivity#acc00(AnimationController#0ab75(▶ 186.000; for BallisticScrollActivity)), ScrollDirection.idle)
  anchor: 0.0

Here is the code from the widget:


  @override
  Widget build(BuildContext context) {
    news = Provider.of<NewsDataProvider>(context).newsData;

    return Container(
      alignment: Alignment.center,
      width: MediaQuery.of(context).size.width,
      height: MediaQuery.of(context).size.height,
      child: Container(
        margin: EdgeInsets.fromLTRB(0, 22, 0, 30),
        alignment: Alignment.center,
        width: MediaQuery.of(context).size.width * 0.9,
        child: Column(
          children: <Widget> [
            CustomCard(
              borderRadius: [10, 10, 0, 0],
              elevation: 3,
              color: Colors.black87,
              child: Container(
                  height: 25,
                  width: context.widthPx,
                  child: Text(
                    "News",
                    textAlign: TextAlign.center,
                  )),
            ),
            Expanded(
              flex: 1,
              child: CustomCard(
                padding: [0, 6, 0, 0],
                borderRadius: [0, 0, 10, 10],
                elevation: 10,
                shadowColor: Colors.black,
                color: Color.fromRGBO(35, 47, 52, 0.8),
                child: Column(
                  children: [
                    Expanded(
                      flex: 1,
                      child: Scaffold(
                        body: (news == null)
                            ? Center(child: CircularProgressIndicator())
                            : DraggableScrollbar.arrows(
                                alwaysVisibleScrollThumb: true,
                                backgroundColor: Color.fromRGBO(35, 35, 35, 0.9),
                                padding: EdgeInsets.only(right: 2),
                                controller: _scrollController,
                                child: ListView.separated(
                                  controller: _scrollController,
                                  itemCount: news.length,
                                  separatorBuilder: (context, __) => SizedBox(height: 8),
                                  itemBuilder: (context, index) {
                                    return (news[index].isDynamic)
                                        ? Center(child: CircularProgressIndicator())
                                        : FadeInVertical(
                                            delay: (index.toDouble() * 0.3) + 0.3,
                                            distance: -75,
                                            duration: 500,
                                            child: Padding(
                                              padding: EdgeInsets.fromLTRB(10, 0, 23, 0),
                                              child: ExpansionNews(news[index], index),
                                            ),
                                          );
                                  },
                                ),
                                heightScrollThumb: 48.0,
                              ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
            SizedBox(height: 35),
          ],
        ),
      ),
    );
  }

I am hoping that you might be able to at least help point me in the right direction? I will probably post this same message over in the draggable_scrollbar github as well, just in case this ends up being something on their end.

Thanks! -MH

MostHated commented 4 years ago

I have discovered that on line 417 of draggable_scrollbar, if instead of simply setState(), an addPostFrameCallback is added, the issue no longer occurs. So I suppose we are good here.