Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[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 this issue Sep 12, 2023 · 11 comments

Comments

@AlexDochioiu
Copy link

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
Copy link
Author

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
Copy link

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
Copy link
Author

@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
Copy link

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
Copy link

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
Copy link

gukong commented Feb 19, 2024

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
Copy link
Author

AlexDochioiu commented Feb 20, 2024

@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
Copy link

gukong commented Feb 20, 2024

@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
Copy link

gukong commented Feb 23, 2024

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
Copy link

gukong commented Feb 23, 2024

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

@Szymon-Gesicki
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants