directory
- Create a nested slide PageView with Flutter from scratch
- Create a nested slide PageView with Flutter from scratch
- Create a nested slide PageView with Flutter from scratch
preface
In the first place, why is there a need for PageView nesting PageView?
Let’s take a look at Tiktok’s interaction:
It is not difficult to analyze from the figure that there are two tabs in the home page and the menu bar on the right is an independent page
Plus nested sliding, so the implementation is, inside PageView again nested a layout, home page that piece can not be in this nested layout to join a TabBarView it is good, menu bar with status management to update the menu content, so easy~
But it turns out I was still too young… TabBarView is actually the extension of PageView implementation, but goose, PageView is not support nested sliding……
The solution
-
Gesture monitor, animate all views, and animate the bottom TAB bar when highlighting the menu
-
NestedScrollerView and PageView physics?
-
Implement a nested sliding PageView
Of course, if I had adopted the first option, this article would not have been written, without mentioning the bloody history of the project research.
First things to know (Preparation before class)
-
When a Flutter is mentioned, the first thing that comes to mind is NestedScrollView. Therefore, if we want to add a nested slide mechanism to PageView, it will be helpful to learn about NestedScrollView and its core principles.
-
Dart ScrollerController, ScrollerPosition, etc. Learn about their purpose, basic meaning, and usage. Just look at ScrollerController and ScrollerPosition, and you can use beginActivity and ScrollActivity in this article. With ScrollPositionWithSingleContext copy paste).
The first step is to let it slide
After preparing for class, we can simply describe the nested sliding steps of NestedScrollView:
-
Create _NestedScrollCoordinator and create two ScrollControllers to manage the overall CunstomScrollerView and the sliding layout of the internal primary
-
Using a custom ScrollController, return the custom ScrollPosition, passing the Delegate implementation to the _NestedScrollCoordinator.
-
The Delegate controls the contents of the entire list through the specific applyUserOffset method, sliding up or left first to the outside, sliding down or right first to the inside.
If you implement nested sliding of PageView, you can also take this idea.
Some little pits
-
PageView does not support primary, so if you want to use NestedScrollerView without passing a specific controller to child, you need to implement a PageView that supports primary.
-
PageView will not survive, so if you pull to the second page of the main PageView, the first page containing the child PageView will be disposed, so the sliding state will be lost, and when you pull back, the natural display is the first page, rather than the largest page after nested sliding. So this one needs to be preserved for a while
The core code
1class _ChildPagePosition extends ScrollPosition
2 implements PageMetrics.ScrollActivityDelegate {
3 _ChildPagePosition({
4 this.parentController,
5 ScrollPhysics physics,
6 ScrollContext context,
7 this.initialPage = 0.
8 bool keepPage = true.
9 double viewportFraction = 1.0.
10 double initialPixels = 0.0.
11 ScrollPosition oldPosition,
12 })
13 : assert(initialPage ! =null),
14 assert(keepPage ! =null),
15 assert(viewportFraction ! =null),
16 assert(viewportFraction > 0.0),
17 _viewportFraction = viewportFraction,
18 _pageToUseOnStartup = initialPage.toDouble(),
19 super(
20 physics: physics,
21 context: context,
22 keepScrollOffset: keepPage,
23 oldPosition: oldPosition,
24 ) {
25 // If oldPosition is not null, the superclass will first call absorb(),
26 // which may set _pixels and _activity.
27 if (pixels == null&& initialPixels ! =null)
28 correctPixels(initialPixels);
29 if (activity == null)
30 goIdle();
31 assert(activity ! =null);
32 }
33
34 /// a bunch of irrelevant methods are skipped in the middle
35
36 @override
37 void applyUserOffset(double delta) {
38 updateUserScrollDirection(
39 delta > 0.0 ? ScrollDirection.forward : ScrollDirection.reverse);
40 final double newPixels = pixels -
41 physics.applyPhysicsToUserOffset(this, delta);
42 final double overScroll = physics.applyBoundaryConditions(this, newPixels);
43 if (overScroll == 0) {
44 setPixels(newPixels);
45 } else {
46 if(parentController! =null) {
47 if(parentController.position is _PagePosition){
48 (parentController.position as _PagePosition).applyClampedDragUpdate(-overScroll);
49 }
50 }
51 print("Trigger superior slide");
52 }
53 }
54}
Copy the code
Look Look effect
Afterword.
Of course, supporting nested sliding is just the beginning…
As shown in the picture, it is only nested sliding at present, and there is no special handling of the physics effect after releasing the hand, and then pulling it back in the middle. But that is a matter for the future…