-
Notifications
You must be signed in to change notification settings - Fork 30.1k
Description
Please read here first
This issue may seem long but please do not hesitate to read it since I put lots of effort into writing these and I am sure that there are a considerable amount of people who suffer the implementation difficulty of the combination of NestedScrollView - TabBarView - CustomScrollView.
This is probably related to prioritizing overscroll as dear @Piinks noted in the source file of NestedScrollView :
Configure which scrollable receives overscroll support stretching app bars. createOuterBallisticScrollActivity need to be updated as it currently assumes the outer position never overscroll,
Versions
Flutter 2.0.6 stable sound-nullsafe
extended_nested_scroll_view: ^3.0.0
waterfall_flow: ^3.0.1
Flutter Doctor (Click to expand)
[✓] Flutter (Channel unknown, 2.0.6, on Mac OS X 10.15.5 19F101 darwin-x64, locale tr-TR)
• Flutter version 2.0.6 at /Users/yasinarik/fvm/versions/2.0.6
• Framework revision 1d9032c7e1 (10 days ago), 2021-04-29 17:37:58 -0700
• Engine revision 05e680e202
• Dart version 2.12.3
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
• Android SDK at /Users/yasinarik/Library/Android/sdk
• Platform android-29, build-tools 29.0.2
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 12.2, Build version 12B45b
• CocoaPods version 1.10.1
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 3.5)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
[✓] Connected device (3 available)
• iPhone 8 (mobile) • BC9D4992-201C-4A6D-B237-850E45ED7CBC • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-2 (simulator)
• macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.5 19F101 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 90.0.4430.85
! Error: My iPhone’u is not connected. Xcode will continue when My iPhone’u is connected. (code -13)
• No issues found!
The Problem
For the sake of simplicity, I want to start with the end result I want to have in my app. I want to build a scroll view that will have the same UI & UX as the well-known iOS Instagram Profile Screen.
Here is what I have already achieved as a feature list. Because the reproducible code is very long, complex in structure, and depends on 3rd party pub.dev packages, I can't write it so easily. I will try my best to provide a producible code.
Features of the Instagram Profile Screen UI, UX, Behavior vs. Which of them I can achieve
-
✅ It has a nested scroll view.
-
✅ Inside the nested scroll view, it has a header section where you see the profile picture, stats, buttons, etc.
-
✅ Inside the nested scroll view, just below the header section it has a tab view.
-
✅ All the tabs have their respective inner custom scroll views.
-
✅ The tab view can be scrolled horizontally to switch tabs. Or the tab buttons can be pressed to switch tabs. Either way, the inner scrollers (or slivers to be more correct) do not rebuild from scratch which is a very good thing for performance.
-
✅ When scrolled vertically, the header section should leave the screen but the tab buttons should stick at the top.
-
✅ (For vertical scrolling) After the tab buttons stick at the top, the individual inner scrollers should scroll respecting the existing scroll ballistics, (momentum, friction, velocity, .etc)
-
✅ The scroll positions of the inner scrollers should be independent and they have to be stored as a part of the state. Shouldn't be affected by tab switching.
-
✅ This is not directly related to the bug but I wanted to write) Layout the inner scroller items as a grid. Use skeleton (or shimmer) wrapper for initial fetching. When scrolled to the very bottom of an inner scroller, show a
loading indicatorand load more items if available. -
❌ For vertical scrolling, the nested scroll view does not behave as expected. The expected behavior is that for leading and trailing ends, over scrolling can be applied.
- Before you say, none of the
physics: AlwaysScrollableScrollPhysics()solve this issue. Believe me, I've tried everything even writingCustomScrollPhysics. - Even if the over-scrolling happens, it happens in the wrong place. It happens in between the tab buttons and the inner scroller. However, it should occur on top of the outer scroller. Because the use case of the NestedScrollView is that we want the whole scrollable area to act as one combined.
- There is certainly something wrong with the
NestedScrollView(original or from the 3rd party package, doesn't matter).
- Before you say, none of the
-
❌ Since the scroll physics work wrong, I have to use ClampingScrollPhysics(), no other choices. Thus, it is not possible for NestedScrollView to over scroll, bounce at the edge, etc. As a result, I can't implement the pull to refresh mechanism. This is the only missing part.
Image Explanation
Here are some sample images explaining the aimed result. Of course, these are not how the actual app looks like. I have removed lots of things in this NestedScrollView for simplicity and privacy but I am sure those are just enough to represent the wrong (or an unpreferred) behavior.
If you are an iOS Instagram user, please just go to a profile screen and just try scrolling, refreshing by yourself.
| Bottom Overscroll Is Fıne (Trailing edge) | Top Overscroll Is Wrong (Leading edge) | How It Should Be |
|---|---|---|
![]() |
![]() |
![]() |


