jamesblasco / modal_bottom_sheet

Flutter | Create advanced modal bottom sheets. Material, Cupertino or your own style
https://pub.dev/packages/modal_bottom_sheet
MIT License
1.83k stars 461 forks source link

[Sheet] Triggering a re-build in child widget within the first 200ms or so seems to fully break the bottom sheet #372

Open AlexDochioiu opened 9 months ago

AlexDochioiu commented 9 months ago

I am using a (riverpod) Consumer Widget which gets built by builder when pushing SheetRoute. This widget starts on a loading state but very quickly changes to a data state (after checking some database value).

This causes the bottom sheet to not come up at all anymore. I can however see the barrier, and click on it to dismiss. Adding an artificial delay of 250ms when changing from Loading to Data state seems to fix this issue.

P.s. This issue does not happen with the official bottom sheet (from material package) and with the old modal_bottom_sheet package. Seems to be limited to the Sheet package.

AlexDochioiu commented 9 months ago

Been looking a bit into reproducing it. It seems that the issue may be because, when my widget rebuilds, the bottom sheet checks for the bottom sheet closing threshold. Given that the state changed while the bottom sheet is opening, that threshold is not met and instead it closes back automatically.

codeOfJannik commented 9 months ago

I have a similar issue. My sheet is closing on re-renderings but only on some devices. Which seems to be caused by the closing threshold. Did you find a solution?

AlexDochioiu commented 9 months ago

@codeOfJannik No. I decided to temporarily stick with the older modal_bottom_sheet package and eventually take the time to migrate to the official material bottom sheet.

mohamad-jawad commented 6 months ago

I faced the same issue when my child widget is a ListView.builder

I have solved it by changing stops parameter from [0,1] to [1]

dynamicpace-admin commented 5 months ago

I faced the same issue when my child widget is a ListView.builder

I have solved it by changing stops parameter from [0,1] to [1]

I confirm this works! I've have also had major issues with sheet and using riverpod but also other widgets like ExpansionTile while using initialExpanded.

Just adding [1] to stops property for example CupertinoSheetRoute makes everything work.

Thank you mohamad-jawad

gukong commented 4 months ago

The following structure of the code, and there are cases of asynchronous changes to the widget such as bloc/provider (just changing the text of the text does not count) When using the sheet component to implement the iOS modal effect, the pop-up page cannot be displayed normally

return CupertinoPageScaffold(
  child: SingleChildScrollView(
    controller: ScrollController(), // add  this line to fix the issue
    child: change ? Text('hello') : CupertinoButton(child: Text('world'), onPressed: null),
  ),
);

Solution: SingleChildScrollView must be work with a ScrollController

I traced the sheet source code, and guessed that the widget rebuilt the position, so I tried to add a ScrollController to the SingleChildScrollView to control its scrolling behavior, and unexpectedly, everything worked fine when I added the ScrollController. I don't know how it works, maybe you guys can submit a PR to fix it

AlexDochioiu commented 4 months ago

@gukong No idea how/if your solution works (I did not try it). But be careful because ScrollController requires to be reused and disposed at the end. So either use a stateful widget or something like flutter hooks to manage its lifecycle.

P.s. once you properly manage the reusability/disposal of the scroll controller your solution might stop fixing the bottom sheet problem.

gukong commented 4 months ago

@AlexDochioiu Sorry, the code above is just a simple example. I'm managing the lifecycle of the ScrollController in the StatefulWidget, and yes, the ScrollController is destroyed in the disposed method. So far, he's working.

Also, I found another solution that doesn't require a ScrollController to be set. Replacing CupertinoPageScaffold with Material, the issue of sheet not displaying has been unexpectedly fixed. Also again, I don't know how it works.😆

gukong commented 4 months ago

Yes, eventually I found the code that caused the sheet to not appear

The goBallistic method in the file sheet/lib/src/scroll_controller.dart line 113

/// There is asynchronous data in the page, causing the page to be re-rendered, and goBallistic callbacks one more time  
/// If hasContentDimensions is true, sheetPosition.goBallistic(velocity) will be executed;  
/// Let the page hide again, so it adds judgment  
if (sheetPosition.pixels != 1.0 && sheetPosition.hasContentDimensions) {  
   sheetPosition.goBallistic(velocity);  
}  

As for why it's 1.0, because when I print the log, pixels are 1.0. yeah, it's not elegant

gukong commented 4 months ago

Another thing, the pre answer is not correct, controller should set to PrimaryScrollController.of(context)

Szymon-Gesicki commented 2 months ago

any update to this? I have the same problem. It happens when some widget in scroll changes its size, then bottom sheet closes