Flutter擴展NestedScrollView(二)列表滾動同步解決
接著上篇,沒看上篇的小夥伴建議先看下上篇,免得斷片中..
我繼續講下第2個問題的解決方案。
當在裡面放上TabView的,並且選項卡是緩存狀態的時候,會出現滾動會互相影響的問題
上篇我們說到在我們的主角NestedScrollView當中,有2個ScrollController。
class _NestedScrollController extends ScrollController {
_NestedScrollController(
this.coordinator, {
double initialScrollOffset = 0.0,
String debugLabel,
一個是內,一個外。外部負責headerSliv??erBuilder裡面的滾動小部件內部是負責體內面的滾動小部件當外滾動到底了之後,就會看看內裡面是否有能滾動的東東,開始滾動
Tabview是在體裡面,這裡我們肯定需要對內進行處理。首先我們要明白,NestedScrollView是怎麼處理外和內的關係的。
找到這個_NestedScrollCoordinator的applyUserOffset方法中處理了整個NestedScrollView的滑動處理
@override
void applyUserOffset(double delta) {
updateUserScrollDirection(delta > 0.0 ? ScrollDirection.forward : ScrollDirection.reverse);
assert(delta != 0.0);
if (_innerPositions.isEmpty) {
_outerPosition.applyFullDragUpdate(delta);
} else if (delta < 0.0) {
// dragging "up"
// TODO(ianh): prioritize first getting rid of overscroll, and then the
// outer view, so that the app bar will scroll out of the way asap.
// Right now we ignore overscroll. This works fine on Android but looks
// weird on iOS if you fling down then up. The problem is its not at all
// clear what this should do when you have multiple inner positions at
// different levels of overscroll.
final double innerDelta = _outerPosition.applyClampedDragUpdate(delta);
if (innerDelta != 0.0) {
for (_NestedScrollPosition position in _innerPositions)
position.applyFullDragUpdate(innerDelta);
}
} else {
// dragging "down" - delta is positive
// prioritize the inner views, so that the inner content will move before the app bar grows
double outerDelta = 0.0; // it will go positive if it changes
final List<double> overscrolls = <double>[];
final List<_NestedScrollPosition> innerPositions = _innerPositions.toList();
for (_NestedScrollPosition position in innerPositions) {
final double overscroll = position.applyClampedDragUpdate(delta);
outerDelta = math.max(outerDelta, overscroll);
overscrolls.add(overscroll);
}
if (outerDelta != 0.0)
outerDelta -= _outerPosition.applyClampedDragUpdate(outerDelta);
// now deal with any overscroll
for (int i = 0; i < innerPositions.length; ++i) {
final double remainingDelta = overscrolls[i] - outerDelta;
if (remainingDelta > 0.0)
innerPositions[i].applyFullDragUpdate(remainingDelta);
}
}
}
Iterable<_NestedScrollPosition> get _innerPositions {
return _innerController.nestedPositions;
}
看到_innerPositions是我們要關注的東西,通過調試,我發現,如果tabview的每個tab做了緩存,那麼每個tab裡面列表的ScrollPosition將一直緩存在這個ScrollController裡面。當tab到tabview的某個tab的時候,ScrollController將會這個ScrollPosition附上,如果沒有緩存,將會在離開的時候脫離掉。
@override
void attach(ScrollPosition position) {
assert(position is _NestedScrollPosition);
super.attach(position);
coordinator.updateParent();
coordinator.updateCanDrag();
position.addListener(_scheduleUpdateShadow);
_scheduleUpdateShadow();
}
@override
void detach(ScrollPosition position) {
assert(position is _NestedScrollPosition);
position.removeListener(_scheduleUpdateShadow);
super.detach(position);
_scheduleUpdateShadow();
}