Skip to content

Commit

Permalink
fix(ObserverCore): improve the logic of handleListObserve and handleG…
Browse files Browse the repository at this point in the history
…ridObserve
  • Loading branch information
LinXunFeng committed Aug 26, 2024
1 parent 458d837 commit c379fa7
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 4 deletions.
45 changes: 42 additions & 3 deletions lib/src/observer_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class ObserverCore {
var parentData = firstChild.parentData as SliverMultiBoxAdaptorParentData;
var index = parentData.index ?? 0;

// Whether the first child being displayed is not found.
bool isNotFound = false;
// Find out the first child which is displaying
var targetFirstChild = firstChild;

Expand All @@ -63,15 +65,34 @@ class ObserverCore {
)) {
index = index + 1;
var nextChild = _obj.childAfter(targetFirstChild);
if (nextChild == null) break;
if (nextChild == null) {
isNotFound = true;
break;
}

if (nextChild is! RenderIndexedSemantics) {
// It is separator
nextChild = _obj.childAfter(nextChild);
}
if (nextChild == null) break;
if (nextChild == null) {
isNotFound = true;
break;
}
targetFirstChild = nextChild;
}

// The first child being displayed is not found, indicating that the
// ScrollView is not visible.
if (isNotFound) {
return ListViewObserveModel(
sliverList: _obj,
viewport: viewport,
visible: false,
firstChild: null,
displayingChildModelList: [],
);
}

if (targetFirstChild is! RenderIndexedSemantics) return null;

List<ListViewObserveDisplayingChildModel> displayingChildModelList = [
Expand Down Expand Up @@ -159,6 +180,8 @@ class ObserverCore {
final rawScrollViewOffset = _obj.constraints.scrollOffset + overlap;
var scrollViewOffset = rawScrollViewOffset + offset;

// Whether the first child being displayed is not found.
bool isNotFound = false;
// Find out the first child which is displaying
var targetFirstChild = firstChild;
var lastFirstGroupChildWidget = targetFirstChild;
Expand All @@ -171,9 +194,25 @@ class ObserverCore {
)) {
/// Entering here means it is not the target object
RenderBox? nextChild = _obj.childAfter(targetFirstChild);
if (nextChild == null) break;
if (nextChild == null) {
isNotFound = true;
break;
}
targetFirstChild = nextChild;
}

// The first child being displayed is not found, indicating that the
// ScrollView is not visible.
if (isNotFound) {
return GridViewObserveModel(
sliverGrid: _obj,
viewport: viewport,
visible: false,
firstGroupChildList: [],
displayingChildModelList: [],
);
}

if (targetFirstChild is! RenderIndexedSemantics) return null;
lastFirstGroupChildWidget = targetFirstChild;

Expand Down
98 changes: 97 additions & 1 deletion test/sliver_observer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,7 @@ void main() {
late SliverObserverController observerController;
late Widget widget;
BuildContext? _sliverHeaderListCtx;
BuildContext? _sliverHeaderGridCtx;
BuildContext? _sliverBodyListCtx;
BuildContext? _sliverBodyGridCtx;
GlobalKey appBarKey = GlobalKey();
Expand Down Expand Up @@ -551,6 +552,22 @@ void main() {
),
itemExtent: 50,
),
SliverGrid.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
childAspectRatio: 2.0,
),
itemBuilder: (context, index) {
if (_sliverHeaderGridCtx != context) {
_sliverHeaderGridCtx = context;
nestedScrollUtil?.headerSliverContexts.add(context);
}
return Text("Item $index");
},
itemCount: 10,
),
];
},
body: Builder(builder: (context) {
Expand Down Expand Up @@ -587,6 +604,7 @@ void main() {
sliverContexts: () {
return [
if (_sliverHeaderListCtx != null) _sliverHeaderListCtx!,
if (_sliverHeaderGridCtx != null) _sliverHeaderGridCtx!,
if (_sliverBodyListCtx != null) _sliverBodyListCtx!,
if (_sliverBodyGridCtx != null) _sliverBodyGridCtx!,
];
Expand All @@ -610,6 +628,7 @@ void main() {
tearDown(() {
outerScrollController.dispose();
_sliverHeaderListCtx = null;
_sliverHeaderGridCtx = null;
_sliverBodyListCtx = null;
_sliverBodyGridCtx = null;
});
Expand Down Expand Up @@ -758,7 +777,7 @@ void main() {
(tester) async {
resetAll();
await tester.pumpWidget(widget);
expect(nestedScrollUtil?.headerSliverContexts.length, 1);
expect(nestedScrollUtil?.headerSliverContexts.length, 2);
expect(nestedScrollUtil?.bodySliverContexts.length, 2);
expect(nestedScrollUtil?.remainingSliverContext == null, true);
expect(nestedScrollUtil?.remainingSliverRenderObj == null, true);
Expand All @@ -774,6 +793,83 @@ void main() {
expect(nestedScrollUtil?.remainingSliverRenderObj, null);
},
);

testWidgets(
'Check the observed data when the sliver in the header is not visible',
(tester) async {
resetAll();
await tester.pumpWidget(widget);
await observerController.dispatchOnceObserve(
sliverContext: _sliverHeaderListCtx!,
);
var headerListObservationResult =
(resultMap[_sliverHeaderListCtx] as ListViewObserveModel);
expect(
headerListObservationResult.displayingChildIndexList,
isNotEmpty,
);

nestedScrollUtil?.jumpTo(
nestedScrollViewKey: nestedScrollViewKey,
observerController: observerController,
sliverContext: _sliverHeaderGridCtx,
position: NestedScrollUtilPosition.header,
index: 0,
offset: (targetOffset) {
return calcPersistentHeaderExtent(
offset: targetOffset,
widgetKey: appBarKey,
);
},
);
await tester.pumpAndSettle();
await tester.pump(observerController.observeIntervalForScrolling);

headerListObservationResult =
(resultMap[_sliverHeaderListCtx] as ListViewObserveModel);
expect(
headerListObservationResult.displayingChildIndexList,
isEmpty,
);

var headerGridObservationResult =
(resultMap[_sliverHeaderGridCtx] as GridViewObserveModel);
expect(
headerGridObservationResult.firstGroupChildList.first.index,
0,
);

nestedScrollUtil?.jumpTo(
nestedScrollViewKey: nestedScrollViewKey,
observerController: observerController,
sliverContext: _sliverBodyListCtx,
position: NestedScrollUtilPosition.body,
index: 0,
offset: (targetOffset) {
return calcPersistentHeaderExtent(
offset: targetOffset,
widgetKey: appBarKey,
);
},
);
await tester.pumpAndSettle();
await tester.pump(observerController.observeIntervalForScrolling);

var bodyListObservationResult =
(resultMap[_sliverBodyListCtx] as ListViewObserveModel);
expect(
bodyListObservationResult.firstChild?.index,
0,
);

headerGridObservationResult =
(resultMap[_sliverHeaderGridCtx] as GridViewObserveModel);
expect(
headerGridObservationResult.displayingChildIndexList,
isEmpty,
);
},
);
},
);

Expand Down

0 comments on commit c379fa7

Please sign in to comment.