您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

213 行
9.1 KiB

using System;
using UIWidgets.foundation;
namespace UIWidgets.rendering {
public class RenderSliverList : RenderSliverMultiBoxAdaptor {
public RenderSliverList(
RenderSliverBoxChildManager childManager = null
) : base(childManager: childManager) {
}
protected override void performLayout() {
this.childManager.didStartLayout();
this.childManager.setDidUnderflow(false);
double scrollOffset = this.constraints.scrollOffset + this.constraints.cacheOrigin;
D.assert(scrollOffset >= 0.0);
double remainingExtent = this.constraints.remainingCacheExtent;
D.assert(remainingExtent >= 0.0);
double targetEndScrollOffset = scrollOffset + remainingExtent;
BoxConstraints childConstraints = this.constraints.asBoxConstraints();
int leadingGarbage = 0;
int trailingGarbage = 0;
bool reachedEnd = false;
if (this.firstChild == null) {
if (!this.addInitialChild()) {
this.geometry = SliverGeometry.zero;
this.childManager.didFinishLayout();
return;
}
}
RenderBox leadingChildWithLayout = null, trailingChildWithLayout = null;
RenderBox earliestUsefulChild = this.firstChild;
for (double earliestScrollOffset = this.childScrollOffset(earliestUsefulChild);
earliestScrollOffset > scrollOffset;
earliestScrollOffset = this.childScrollOffset(earliestUsefulChild)) {
earliestUsefulChild = this.insertAndLayoutLeadingChild(childConstraints, parentUsesSize: true);
if (earliestUsefulChild == null) {
var childParentData = (SliverMultiBoxAdaptorParentData) this.firstChild.parentData;
childParentData.layoutOffset = 0.0;
if (scrollOffset == 0.0) {
earliestUsefulChild = this.firstChild;
leadingChildWithLayout = earliestUsefulChild;
trailingChildWithLayout = trailingChildWithLayout ?? earliestUsefulChild;
break;
} else {
this.geometry = new SliverGeometry(
scrollOffsetCorrection: -scrollOffset
);
return;
}
} else {
double firstChildScrollOffset = earliestScrollOffset - this.paintExtentOf(this.firstChild);
if (firstChildScrollOffset < 0.0) {
double correction = 0.0;
while (earliestUsefulChild != null) {
D.assert(this.firstChild == earliestUsefulChild);
correction += this.paintExtentOf(this.firstChild);
earliestUsefulChild =
this.insertAndLayoutLeadingChild(childConstraints, parentUsesSize: true);
}
this.geometry = new SliverGeometry(
scrollOffsetCorrection: correction - earliestScrollOffset
);
var childParentData = (SliverMultiBoxAdaptorParentData) this.firstChild.parentData;
childParentData.layoutOffset = 0.0;
return;
} else {
var childParentData = (SliverMultiBoxAdaptorParentData) earliestUsefulChild.parentData;
childParentData.layoutOffset = firstChildScrollOffset;
D.assert(earliestUsefulChild == this.firstChild);
leadingChildWithLayout = earliestUsefulChild;
trailingChildWithLayout = trailingChildWithLayout ?? earliestUsefulChild;
}
}
}
D.assert(earliestUsefulChild == this.firstChild);
D.assert(this.childScrollOffset(earliestUsefulChild) <= scrollOffset);
if (leadingChildWithLayout == null) {
earliestUsefulChild.layout(childConstraints, parentUsesSize: true);
leadingChildWithLayout = earliestUsefulChild;
trailingChildWithLayout = earliestUsefulChild;
}
bool inLayoutRange = true;
RenderBox child = earliestUsefulChild;
int index = this.indexOf(child);
double endScrollOffset = this.childScrollOffset(child) + this.paintExtentOf(child);
Func<bool> advance = () => {
D.assert(child != null);
if (child == trailingChildWithLayout) {
inLayoutRange = false;
}
child = this.childAfter(child);
if (child == null) {
inLayoutRange = false;
}
index += 1;
if (!inLayoutRange) {
if (child == null || this.indexOf(child) != index) {
child = this.insertAndLayoutChild(childConstraints,
after: trailingChildWithLayout,
parentUsesSize: true
);
if (child == null) {
return false;
}
} else {
child.layout(childConstraints, parentUsesSize: true);
}
trailingChildWithLayout = child;
}
D.assert(child != null);
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
childParentData.layoutOffset = endScrollOffset;
D.assert(childParentData.index == index);
endScrollOffset = this.childScrollOffset(child) + this.paintExtentOf(child);
return true;
};
while (endScrollOffset < scrollOffset) {
leadingGarbage += 1;
if (!advance()) {
D.assert(leadingGarbage == this.childCount);
D.assert(child == null);
this.collectGarbage(leadingGarbage - 1, 0);
D.assert(this.firstChild == this.lastChild);
double extent = this.childScrollOffset(this.lastChild) + this.paintExtentOf(this.lastChild);
this.geometry = new SliverGeometry(
scrollExtent: extent,
paintExtent: 0.0,
maxPaintExtent: extent
);
return;
}
}
while (endScrollOffset < targetEndScrollOffset) {
if (!advance()) {
reachedEnd = true;
break;
}
}
if (child != null) {
child = this.childAfter(child);
while (child != null) {
trailingGarbage += 1;
child = this.childAfter(child);
}
}
this.collectGarbage(leadingGarbage, trailingGarbage);
D.assert(this.debugAssertChildListIsNonEmptyAndContiguous());
double? estimatedMaxScrollOffset;
if (reachedEnd) {
estimatedMaxScrollOffset = endScrollOffset;
} else {
estimatedMaxScrollOffset = this.childManager.estimateMaxScrollOffset(
this.constraints,
firstIndex: this.indexOf(this.firstChild),
lastIndex: this.indexOf(this.lastChild),
leadingScrollOffset: this.childScrollOffset(this.firstChild),
trailingScrollOffset: endScrollOffset
);
D.assert(estimatedMaxScrollOffset >= endScrollOffset - this.childScrollOffset(this.firstChild));
}
double paintExtent = this.calculatePaintOffset(
this.constraints,
from: this.childScrollOffset(this.firstChild),
to: endScrollOffset
);
double cacheExtent = this.calculateCacheOffset(
this.constraints,
from: this.childScrollOffset(this.firstChild),
to: endScrollOffset
);
double targetEndScrollOffsetForPaint =
this.constraints.scrollOffset + this.constraints.remainingPaintExtent;
this.geometry = new SliverGeometry(
scrollExtent: estimatedMaxScrollOffset.Value,
paintExtent: paintExtent,
cacheExtent: cacheExtent,
maxPaintExtent: estimatedMaxScrollOffset.Value,
hasVisualOverflow: endScrollOffset > targetEndScrollOffsetForPaint ||
this.constraints.scrollOffset > 0.0
);
if (estimatedMaxScrollOffset == endScrollOffset) {
this.childManager.setDidUnderflow(true);
}
this.childManager.didFinishLayout();
}
}
}