handleListObserve static method
ListViewObserveModel?
handleListObserve({
- required BuildContext context,
- double fetchLeadingOffset()?,
- double? customOverlap()?,
- double toNextOverPercent = 1,
Handles observation logic of a sliver similar to SliverList.
Implementation
static ListViewObserveModel? handleListObserve({
required BuildContext context,
double Function()? fetchLeadingOffset,
double? Function(BuildContext)? customOverlap,
double toNextOverPercent = 1,
}) {
var _obj = ObserverUtils.findRenderObject(context);
if (_obj is! RenderSliverMultiBoxAdaptor) return null;
final viewport = ObserverUtils.findViewport(_obj);
if (viewport == null) return null;
if (kDebugMode) {
if (viewport.debugNeedsPaint) return null;
}
// The geometry.visible is not absolutely reliable.
if (!(_obj.geometry?.visible ?? false) ||
_obj.constraints.remainingPaintExtent < 1e-10) {
return ListViewObserveModel(
sliverList: _obj,
viewport: viewport,
visible: false,
firstChild: null,
displayingChildModelList: [],
);
}
final scrollDirection = _obj.constraints.axis;
var firstChild = _obj.firstChild;
if (firstChild == null) return null;
final offset = fetchLeadingOffset?.call() ?? 0;
final overlap = customOverlap?.call(context) ?? _obj.constraints.overlap;
final rawScrollViewOffset = _obj.constraints.scrollOffset + overlap;
var scrollViewOffset = rawScrollViewOffset + offset;
var parentData = firstChild.parentData as SliverMultiBoxAdaptorParentData;
var index = parentData.index ?? 0;
// Find out the first child which is displaying
var targetFirstChild = firstChild;
while (!ObserverUtils.isBelowOffsetWidgetInSliver(
scrollViewOffset: scrollViewOffset,
scrollDirection: scrollDirection,
targetChild: targetFirstChild,
toNextOverPercent: toNextOverPercent,
)) {
index = index + 1;
var nextChild = _obj.childAfter(targetFirstChild);
if (nextChild == null) break;
if (nextChild is! RenderIndexedSemantics) {
// It is separator
nextChild = _obj.childAfter(nextChild);
}
if (nextChild == null) break;
targetFirstChild = nextChild;
}
if (targetFirstChild is! RenderIndexedSemantics) return null;
List<ListViewObserveDisplayingChildModel> displayingChildModelList = [
ListViewObserveDisplayingChildModel(
sliverList: _obj,
viewport: viewport,
index: targetFirstChild.index,
renderObject: targetFirstChild,
),
];
// Find the remaining children that are being displayed
final showingChildrenMaxOffset =
rawScrollViewOffset + _obj.constraints.remainingPaintExtent - overlap;
var displayingChild = _obj.childAfter(targetFirstChild);
while (ObserverUtils.isDisplayingChildInSliver(
targetChild: displayingChild,
showingChildrenMaxOffset: showingChildrenMaxOffset,
scrollViewOffset: scrollViewOffset,
scrollDirection: scrollDirection,
toNextOverPercent: toNextOverPercent,
)) {
if (displayingChild == null) {
break;
}
if (displayingChild is! RenderIndexedSemantics) {
// It is separator
displayingChild = _obj.childAfter(displayingChild);
continue;
}
displayingChildModelList.add(ListViewObserveDisplayingChildModel(
sliverList: _obj,
viewport: viewport,
index: displayingChild.index,
renderObject: displayingChild,
));
displayingChild = _obj.childAfter(displayingChild);
}
return ListViewObserveModel(
sliverList: _obj,
viewport: viewport,
visible: true,
firstChild: ListViewObserveDisplayingChildModel(
sliverList: _obj,
viewport: viewport,
index: targetFirstChild.index,
renderObject: targetFirstChild,
),
displayingChildModelList: displayingChildModelList,
);
}