浏览代码
Merge remote-tracking branch 'origin/master' into text
Merge remote-tracking branch 'origin/master' into text
# Conflicts: # Assets/UIWidgets/editor/editor_window.cs # Assets/UIWidgets/rendering/editable.cs # Assets/UIWidgets/ui/window.cs # Assets/UIWidgets/widgets/binding.cs # Assets/UIWidgets/widgets/framework.cs/main
fzhangtj
6 年前
当前提交
2e4699a6
共有 47 个文件被更改,包括 1558 次插入 和 329 次删除
-
14Assets/UIWidgets/Tests/Gestures.cs
-
8Assets/UIWidgets/Tests/Paragraph.cs
-
12Assets/UIWidgets/Tests/RenderBoxes.cs
-
10Assets/UIWidgets/Tests/RenderEditable.cs
-
8Assets/UIWidgets/Tests/Widgets.cs
-
85Assets/UIWidgets/editor/editor_window.cs
-
4Assets/UIWidgets/foundation/assertions.cs
-
7Assets/UIWidgets/gestures/arena.cs
-
15Assets/UIWidgets/gestures/binding.cs
-
4Assets/UIWidgets/gestures/long_press.cs
-
16Assets/UIWidgets/gestures/monodrag.cs
-
21Assets/UIWidgets/gestures/multitap.cs
-
21Assets/UIWidgets/gestures/recognizer.cs
-
4Assets/UIWidgets/gestures/tap.cs
-
9Assets/UIWidgets/promise/Promise.cs
-
9Assets/UIWidgets/promise/Promise_NonGeneric.cs
-
28Assets/UIWidgets/rendering/binding.cs
-
5Assets/UIWidgets/rendering/editable.cs
-
36Assets/UIWidgets/rendering/object.cs
-
6Assets/UIWidgets/rendering/object.mixin.gen.cs
-
2Assets/UIWidgets/rendering/object.mixin.njk
-
11Assets/UIWidgets/rendering/proxy_box.cs
-
33Assets/UIWidgets/rendering/sliver_fixed_extent_list.cs
-
4Assets/UIWidgets/rendering/sliver_list.cs
-
6Assets/UIWidgets/rendering/sliver_multi_box_adaptor.cs
-
6Assets/UIWidgets/rendering/sliver_padding.cs
-
2Assets/UIWidgets/rendering/view.cs
-
32Assets/UIWidgets/scheduler/binding.cs
-
22Assets/UIWidgets/scheduler/ticker.cs
-
20Assets/UIWidgets/ui/window.cs
-
53Assets/UIWidgets/widgets/basic.cs
-
224Assets/UIWidgets/widgets/binding.cs
-
23Assets/UIWidgets/widgets/framework.cs
-
2Assets/UIWidgets/widgets/gesture_detector.cs
-
1Assets/UIWidgets/widgets/primary_scroll_controller.cs
-
2Assets/UIWidgets/widgets/scroll_activity.cs
-
2Assets/UIWidgets/widgets/scroll_configuration.cs
-
13Assets/UIWidgets/widgets/scroll_position.cs
-
2Assets/UIWidgets/widgets/scroll_position_with_single_context.cs
-
320Assets/UIWidgets/widgets/scroll_view.cs
-
20Assets/UIWidgets/widgets/scrollable.cs
-
21Assets/UIWidgets/widgets/ticker_provider.cs
-
13Assets/UIWidgets/widgets/viewport.cs
-
206Assets/UIWidgets/rendering/automatic_keep_alive.cs
-
3Assets/UIWidgets/rendering/automatic_keep_alive.cs.meta
-
519Assets/UIWidgets/widgets/sliver.cs
-
3Assets/UIWidgets/widgets/sliver.cs.meta
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UIWidgets.foundation; |
|||
using UIWidgets.scheduler; |
|||
using UIWidgets.ui; |
|||
using UIWidgets.widgets; |
|||
|
|||
namespace UIWidgets.rendering { |
|||
public class AutomaticKeepAlive : StatefulWidget { |
|||
public AutomaticKeepAlive( |
|||
Key key = null, |
|||
Widget child = null |
|||
) : base(key: key) { |
|||
} |
|||
|
|||
public readonly Widget child; |
|||
|
|||
public override State createState() { |
|||
return new _AutomaticKeepAliveState(); |
|||
} |
|||
} |
|||
|
|||
class _AutomaticKeepAliveState : State<AutomaticKeepAlive> { |
|||
Dictionary<Listenable, VoidCallback> _handles; |
|||
Widget _child; |
|||
bool _keepingAlive = false; |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
this._updateChild(); |
|||
} |
|||
|
|||
public override void didUpdateWidget(StatefulWidget oldWidget) { |
|||
base.didUpdateWidget(oldWidget); |
|||
this._updateChild(); |
|||
} |
|||
|
|||
void _updateChild() { |
|||
this._child = new NotificationListener<KeepAliveNotification>( |
|||
onNotification: this._addClient, |
|||
child: this.widget.child |
|||
); |
|||
} |
|||
|
|||
public override void dispose() { |
|||
if (this._handles != null) { |
|||
foreach (Listenable handle in this._handles.Keys) |
|||
handle.removeListener(this._handles[handle]); |
|||
} |
|||
|
|||
base.dispose(); |
|||
} |
|||
|
|||
bool _addClient(KeepAliveNotification notification) { |
|||
Listenable handle = notification.handle; |
|||
this._handles = this._handles ?? new Dictionary<Listenable, VoidCallback>(); |
|||
|
|||
D.assert(!this._handles.ContainsKey(handle)); |
|||
this._handles[handle] = this._createCallback(handle); |
|||
handle.addListener(this._handles[handle]); |
|||
if (!this._keepingAlive) { |
|||
this._keepingAlive = true; |
|||
ParentDataElement<SliverMultiBoxAdaptorWidget> childElement = this._getChildElement(); |
|||
if (childElement != null) { |
|||
this._updateParentDataOfChild(childElement); |
|||
} else { |
|||
SchedulerBinding.instance.addPostFrameCallback(timeStamp => { |
|||
ParentDataElement<SliverMultiBoxAdaptorWidget> childElement1 = this._getChildElement(); |
|||
D.assert(childElement1 != null); |
|||
this._updateParentDataOfChild(childElement1); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
ParentDataElement<SliverMultiBoxAdaptorWidget> _getChildElement() { |
|||
Element element = (Element) this.context; |
|||
Element childElement = null; |
|||
element.visitChildren((Element child) => { childElement = child; }); |
|||
|
|||
D.assert(childElement == null || childElement is ParentDataElement<SliverMultiBoxAdaptorWidget>); |
|||
return (ParentDataElement<SliverMultiBoxAdaptorWidget>) childElement; |
|||
} |
|||
|
|||
void _updateParentDataOfChild(ParentDataElement<SliverMultiBoxAdaptorWidget> childElement) { |
|||
childElement.applyWidgetOutOfTurn((ParentDataWidget<SliverMultiBoxAdaptorWidget>) this.build(this.context)); |
|||
} |
|||
|
|||
VoidCallback _createCallback(Listenable handle) { |
|||
return () => { |
|||
D.assert(() => { |
|||
if (!this.mounted) { |
|||
throw new UIWidgetsError( |
|||
"AutomaticKeepAlive handle triggered after AutomaticKeepAlive was disposed." + |
|||
"Widgets should always trigger their KeepAliveNotification handle when they are " + |
|||
"deactivated, so that they (or their handle) do not send spurious events later " + |
|||
"when they are no longer in the tree." |
|||
); |
|||
} |
|||
|
|||
return true; |
|||
}); |
|||
this._handles.Remove(handle); |
|||
if (this._handles.isEmpty()) { |
|||
if (SchedulerBinding.instance.schedulerPhase < SchedulerPhase.persistentCallbacks) { |
|||
this.setState(() => { this._keepingAlive = false; }); |
|||
} else { |
|||
this._keepingAlive = false; |
|||
Window.instance.scheduleMicrotask(() => { |
|||
if (this.mounted && this._handles.isEmpty()) { |
|||
this.setState(() => { D.assert(!this._keepingAlive); }); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
}; |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
D.assert(this._child != null); |
|||
return new KeepAlive( |
|||
keepAlive: this._keepingAlive, |
|||
child: this._child |
|||
); |
|||
} |
|||
|
|||
public override void debugFillProperties(DiagnosticPropertiesBuilder description) { |
|||
base.debugFillProperties(description); |
|||
description.add(new FlagProperty("_keepingAlive", value: this._keepingAlive, |
|||
ifTrue: "keeping subtree alive")); |
|||
description.add(new DiagnosticsProperty<Dictionary<Listenable, VoidCallback>>( |
|||
"handles", |
|||
this._handles, |
|||
description: this._handles != null ? this._handles.Count + " active clients" : null, |
|||
ifNull: "no notifications ever received" |
|||
)); |
|||
} |
|||
} |
|||
|
|||
public class KeepAliveNotification : Notification { |
|||
public KeepAliveNotification(Listenable handle) { |
|||
D.assert(handle != null); |
|||
this.handle = handle; |
|||
} |
|||
|
|||
public readonly Listenable handle; |
|||
} |
|||
|
|||
public class KeepAliveHandle : ChangeNotifier { |
|||
public void release() { |
|||
this.notifyListeners(); |
|||
} |
|||
} |
|||
|
|||
public abstract class AutomaticKeepAliveClientMixin<T> : State<T> where T : StatefulWidget { |
|||
KeepAliveHandle _keepAliveHandle; |
|||
|
|||
void _ensureKeepAlive() { |
|||
D.assert(this._keepAliveHandle == null); |
|||
this._keepAliveHandle = new KeepAliveHandle(); |
|||
new KeepAliveNotification(this._keepAliveHandle).dispatch(this.context); |
|||
} |
|||
|
|||
void _releaseKeepAlive() { |
|||
this._keepAliveHandle.release(); |
|||
this._keepAliveHandle = null; |
|||
} |
|||
|
|||
protected abstract bool wantKeepAlive { get; } |
|||
|
|||
protected void updateKeepAlive() { |
|||
if (this.wantKeepAlive) { |
|||
if (this._keepAliveHandle == null) |
|||
this._ensureKeepAlive(); |
|||
} else { |
|||
if (this._keepAliveHandle != null) |
|||
this._releaseKeepAlive(); |
|||
} |
|||
} |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
if (this.wantKeepAlive) { |
|||
this._ensureKeepAlive(); |
|||
} |
|||
} |
|||
|
|||
public override void deactivate() { |
|||
if (this._keepAliveHandle != null) { |
|||
this._releaseKeepAlive(); |
|||
} |
|||
|
|||
base.deactivate(); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
if (this.wantKeepAlive && this._keepAliveHandle == null) { |
|||
this._ensureKeepAlive(); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: a3c3b140ce174c61bfd25672b4ad6f21 |
|||
timeCreated: 1537325090 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UIWidgets.foundation; |
|||
using UIWidgets.painting; |
|||
using UIWidgets.rendering; |
|||
|
|||
namespace UIWidgets.widgets { |
|||
public abstract class SliverChildDelegate { |
|||
protected SliverChildDelegate() { |
|||
} |
|||
|
|||
public abstract Widget build(BuildContext context, int index); |
|||
|
|||
public virtual int? estimatedChildCount { |
|||
get { return null; } |
|||
} |
|||
|
|||
public virtual double? estimateMaxScrollOffset( |
|||
int firstIndex, |
|||
int lastIndex, |
|||
double leadingScrollOffset, |
|||
double trailingScrollOffset |
|||
) { |
|||
return null; |
|||
} |
|||
|
|||
public virtual void didFinishLayout(int firstIndex, int lastIndex) { |
|||
} |
|||
|
|||
public abstract bool shouldRebuild(SliverChildDelegate oldDelegate); |
|||
|
|||
public override string ToString() { |
|||
var description = new List<string>(); |
|||
this.debugFillDescription(description); |
|||
return string.Format("{0}({1})", Diagnostics.describeIdentity(this), |
|||
string.Join(", ", description.ToArray())); |
|||
} |
|||
|
|||
protected virtual void debugFillDescription(List<String> description) { |
|||
try { |
|||
var children = this.estimatedChildCount; |
|||
if (children != null) { |
|||
description.Add("estimated child count: " + children); |
|||
} |
|||
} |
|||
catch (Exception ex) { |
|||
description.Add("estimated child count: EXCEPTION (" + ex.GetType() + ")"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public class SliverChildBuilderDelegate : SliverChildDelegate { |
|||
public SliverChildBuilderDelegate( |
|||
IndexedWidgetBuilder builder, |
|||
int? childCount = null, |
|||
bool addAutomaticKeepAlives = true, |
|||
bool addRepaintBoundaries = true |
|||
) { |
|||
D.assert(builder != null); |
|||
this.builder = build; |
|||
this.childCount = childCount; |
|||
this.addAutomaticKeepAlives = addAutomaticKeepAlives; |
|||
this.addRepaintBoundaries = addRepaintBoundaries; |
|||
} |
|||
|
|||
|
|||
public readonly IndexedWidgetBuilder builder; |
|||
|
|||
public readonly int? childCount; |
|||
|
|||
public readonly bool addAutomaticKeepAlives; |
|||
|
|||
public readonly bool addRepaintBoundaries; |
|||
|
|||
public override Widget build(BuildContext context, int index) { |
|||
D.assert(this.builder != null); |
|||
if (index < 0 || (this.childCount != null && index >= this.childCount)) { |
|||
return null; |
|||
} |
|||
|
|||
Widget child = this.builder(context, index); |
|||
if (child == null) { |
|||
return null; |
|||
} |
|||
|
|||
if (this.addRepaintBoundaries) { |
|||
child = RepaintBoundary.wrap(child, index); |
|||
} |
|||
|
|||
if (this.addAutomaticKeepAlives) { |
|||
child = new AutomaticKeepAlive(child: child); |
|||
} |
|||
|
|||
return child; |
|||
} |
|||
|
|||
public override int? estimatedChildCount { |
|||
get { return this.childCount; } |
|||
} |
|||
|
|||
public override bool shouldRebuild(SliverChildDelegate oldDelegate) { |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
public class SliverChildListDelegate : SliverChildDelegate { |
|||
public SliverChildListDelegate( |
|||
List<Widget> children, |
|||
bool addAutomaticKeepAlives = true, |
|||
bool addRepaintBoundaries = true |
|||
) { |
|||
D.assert(children != null); |
|||
this.children = children; |
|||
this.addAutomaticKeepAlives = addAutomaticKeepAlives; |
|||
this.addRepaintBoundaries = addRepaintBoundaries; |
|||
} |
|||
|
|||
public readonly bool addAutomaticKeepAlives; |
|||
|
|||
public readonly bool addRepaintBoundaries; |
|||
|
|||
public readonly List<Widget> children; |
|||
|
|||
public override Widget build(BuildContext context, int index) { |
|||
D.assert(this.children != null); |
|||
if (index < 0 || index >= this.children.Count) { |
|||
return null; |
|||
} |
|||
|
|||
Widget child = this.children[index]; |
|||
D.assert(child != null); |
|||
if (this.addRepaintBoundaries) { |
|||
child = RepaintBoundary.wrap(child, index); |
|||
} |
|||
|
|||
if (this.addAutomaticKeepAlives) { |
|||
child = new AutomaticKeepAlive(child: child); |
|||
} |
|||
|
|||
return child; |
|||
} |
|||
|
|||
public override int? estimatedChildCount { |
|||
get { return this.children.Count; } |
|||
} |
|||
|
|||
public override bool shouldRebuild(SliverChildDelegate oldDelegate) { |
|||
return this.children != ((SliverChildListDelegate) oldDelegate).children; |
|||
} |
|||
} |
|||
|
|||
public abstract class SliverMultiBoxAdaptorWidget : RenderObjectWidget { |
|||
protected SliverMultiBoxAdaptorWidget( |
|||
Key key = null, |
|||
SliverChildDelegate del = null |
|||
) : base(key: key) { |
|||
D.assert(del != null); |
|||
this.del = del; |
|||
} |
|||
|
|||
public readonly SliverChildDelegate del; |
|||
|
|||
public override Element createElement() { |
|||
return new SliverMultiBoxAdaptorElement(this); |
|||
} |
|||
|
|||
public double? estimateMaxScrollOffset( |
|||
SliverConstraints constraints, |
|||
int firstIndex, |
|||
int lastIndex, |
|||
double leadingScrollOffset, |
|||
double trailingScrollOffset |
|||
) { |
|||
D.assert(lastIndex >= firstIndex); |
|||
return this.del.estimateMaxScrollOffset( |
|||
firstIndex, |
|||
lastIndex, |
|||
leadingScrollOffset, |
|||
trailingScrollOffset |
|||
); |
|||
} |
|||
|
|||
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
|||
base.debugFillProperties(properties); |
|||
properties.add(new DiagnosticsProperty<SliverChildDelegate>("del", this.del)); |
|||
} |
|||
} |
|||
|
|||
public class SliverList : SliverMultiBoxAdaptorWidget { |
|||
public SliverList( |
|||
Key key = null, |
|||
SliverChildDelegate del = null |
|||
) : base(key: key, del: del) { |
|||
} |
|||
|
|||
public override RenderObject createRenderObject(BuildContext context) { |
|||
SliverMultiBoxAdaptorElement element = (SliverMultiBoxAdaptorElement) context; |
|||
return new RenderSliverList(childManager: element); |
|||
} |
|||
} |
|||
|
|||
public class SliverFixedExtentList : SliverMultiBoxAdaptorWidget { |
|||
public SliverFixedExtentList( |
|||
Key key = null, |
|||
SliverChildDelegate del = null, |
|||
double itemExtent = 0 |
|||
) : base(key: key, del: del) { |
|||
this.itemExtent = itemExtent; |
|||
} |
|||
|
|||
public readonly double itemExtent; |
|||
|
|||
public override RenderObject createRenderObject(BuildContext context) { |
|||
SliverMultiBoxAdaptorElement element = (SliverMultiBoxAdaptorElement) context; |
|||
return new RenderSliverFixedExtentList(childManager: element, itemExtent: this.itemExtent); |
|||
} |
|||
|
|||
public override void updateRenderObject(BuildContext context, RenderObject renderObjectRaw) { |
|||
var renderObject = (RenderSliverFixedExtentList) renderObjectRaw; |
|||
renderObject.itemExtent = this.itemExtent; |
|||
} |
|||
} |
|||
|
|||
|
|||
public class SliverMultiBoxAdaptorElement : RenderObjectElement, RenderSliverBoxChildManager { |
|||
public SliverMultiBoxAdaptorElement(SliverMultiBoxAdaptorWidget widget) : base(widget) { |
|||
} |
|||
|
|||
public new SliverMultiBoxAdaptorWidget widget { |
|||
get { return (SliverMultiBoxAdaptorWidget) base.widget; } |
|||
} |
|||
|
|||
public new RenderSliverMultiBoxAdaptor renderObject { |
|||
get { return (RenderSliverMultiBoxAdaptor) base.renderObject; } |
|||
} |
|||
|
|||
public override void update(Widget newWidgetRaw) { |
|||
var newWidget = (SliverMultiBoxAdaptorWidget) newWidgetRaw; |
|||
SliverMultiBoxAdaptorWidget oldWidget = this.widget; |
|||
base.update(newWidget); |
|||
SliverChildDelegate newDelegate = newWidget.del; |
|||
SliverChildDelegate oldDelegate = oldWidget.del; |
|||
if (newDelegate != oldDelegate && |
|||
(newDelegate.GetType() != oldDelegate.GetType() || newDelegate.shouldRebuild(oldDelegate))) { |
|||
this.performRebuild(); |
|||
} |
|||
} |
|||
|
|||
Dictionary<int, Widget> _childWidgets = new Dictionary<int, Widget>(); |
|||
SortedDictionary<int, Element> _childElements = new SortedDictionary<int, Element>(); |
|||
RenderBox _currentBeforeChild; |
|||
|
|||
protected override void performRebuild() { |
|||
this._childWidgets.Clear(); |
|||
base.performRebuild(); |
|||
|
|||
this._currentBeforeChild = null; |
|||
D.assert(this._currentlyUpdatingChildIndex == null); |
|||
try { |
|||
int firstIndex = 0; |
|||
int lastIndex = 0; |
|||
|
|||
if (!this._childElements.isEmpty()) { |
|||
firstIndex = this._childElements.Keys.First(); |
|||
lastIndex = this._childElements.Keys.Last(); |
|||
if (this._didUnderflow) { |
|||
lastIndex += 1; |
|||
} |
|||
} |
|||
|
|||
for (int index = firstIndex; index <= lastIndex; ++index) { |
|||
this._currentlyUpdatingChildIndex = index; |
|||
Element newChild = this.updateChild(this._childElements[index], this._build(index), index); |
|||
if (newChild != null) { |
|||
this._childElements[index] = newChild; |
|||
this._currentBeforeChild = (RenderBox) newChild.renderObject; |
|||
} else { |
|||
this._childElements.Remove(index); |
|||
} |
|||
} |
|||
} |
|||
finally { |
|||
this._currentlyUpdatingChildIndex = null; |
|||
} |
|||
} |
|||
|
|||
Widget _build(int index) { |
|||
return this._childWidgets.putIfAbsent(index, () => this.widget.del.build(this, index)); |
|||
} |
|||
|
|||
public void createChild(int index, RenderBox after = null) { |
|||
D.assert(this._currentlyUpdatingChildIndex == null); |
|||
this.owner.buildScope(this, () => { |
|||
bool insertFirst = after == null; |
|||
D.assert(insertFirst || this._childElements[index - 1] != null); |
|||
this._currentBeforeChild = insertFirst ? null : (RenderBox) this._childElements[index - 1].renderObject; |
|||
Element newChild; |
|||
try { |
|||
this._currentlyUpdatingChildIndex = index; |
|||
newChild = this.updateChild(this._childElements[index], this._build(index), index); |
|||
} |
|||
finally { |
|||
this._currentlyUpdatingChildIndex = null; |
|||
} |
|||
|
|||
if (newChild != null) { |
|||
this._childElements[index] = newChild; |
|||
} else { |
|||
this._childElements.Remove(index); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
protected override Element updateChild(Element child, Widget newWidget, object newSlot) { |
|||
SliverMultiBoxAdaptorParentData oldParentData = null; |
|||
if (child != null && child.renderObject != null) { |
|||
oldParentData = (SliverMultiBoxAdaptorParentData) child.renderObject.parentData; |
|||
} |
|||
|
|||
Element newChild = base.updateChild(child, newWidget, newSlot); |
|||
SliverMultiBoxAdaptorParentData newParentData = null; |
|||
|
|||
if (child != null && child.renderObject != null) { |
|||
newParentData = (SliverMultiBoxAdaptorParentData) newChild.renderObject.parentData; |
|||
} |
|||
|
|||
if (oldParentData != newParentData && oldParentData != null && newParentData != null) { |
|||
newParentData.layoutOffset = oldParentData.layoutOffset; |
|||
} |
|||
|
|||
return newChild; |
|||
} |
|||
|
|||
protected override void forgetChild(Element child) { |
|||
D.assert(child != null); |
|||
D.assert(child.slot != null); |
|||
D.assert(this._childElements.ContainsKey((int) child.slot)); |
|||
this._childElements.Remove((int) child.slot); |
|||
} |
|||
|
|||
public void removeChild(RenderBox child) { |
|||
int index = this.renderObject.indexOf(child); |
|||
D.assert(this._currentlyUpdatingChildIndex == null); |
|||
D.assert(index >= 0); |
|||
this.owner.buildScope(this, () => { |
|||
D.assert(this._childElements.ContainsKey(index)); |
|||
try { |
|||
this._currentlyUpdatingChildIndex = index; |
|||
Element result = this.updateChild(this._childElements[index], null, index); |
|||
D.assert(result == null); |
|||
} |
|||
finally { |
|||
this._currentlyUpdatingChildIndex = null; |
|||
} |
|||
|
|||
this._childElements.Remove(index); |
|||
D.assert(!this._childElements.ContainsKey(index)); |
|||
}); |
|||
} |
|||
|
|||
static double _extrapolateMaxScrollOffset( |
|||
int firstIndex, |
|||
int lastIndex, |
|||
double leadingScrollOffset, |
|||
double trailingScrollOffset, |
|||
int childCount |
|||
) { |
|||
if (lastIndex == childCount - 1) |
|||
return trailingScrollOffset; |
|||
int reifiedCount = lastIndex - firstIndex + 1; |
|||
double averageExtent = (trailingScrollOffset - leadingScrollOffset) / reifiedCount; |
|||
int remainingCount = childCount - lastIndex - 1; |
|||
return trailingScrollOffset + averageExtent * remainingCount; |
|||
} |
|||
|
|||
public double? estimateMaxScrollOffset(SliverConstraints constraints, |
|||
int firstIndex = 0, |
|||
int lastIndex = 0, |
|||
double leadingScrollOffset = 0, |
|||
double trailingScrollOffset = 0 |
|||
) { |
|||
int? childCount = this.childCount; |
|||
if (childCount == null) { |
|||
return double.PositiveInfinity; |
|||
} |
|||
|
|||
return this.widget.estimateMaxScrollOffset( |
|||
constraints, |
|||
firstIndex, |
|||
lastIndex, |
|||
leadingScrollOffset, |
|||
trailingScrollOffset |
|||
) ?? _extrapolateMaxScrollOffset( |
|||
firstIndex, |
|||
lastIndex, |
|||
leadingScrollOffset, |
|||
trailingScrollOffset, |
|||
childCount.Value |
|||
); |
|||
} |
|||
|
|||
public int? childCount { |
|||
get { return this.widget.del.estimatedChildCount; } |
|||
} |
|||
|
|||
public void didStartLayout() { |
|||
D.assert(this.debugAssertChildListLocked()); |
|||
} |
|||
|
|||
public void didFinishLayout() { |
|||
D.assert(this.debugAssertChildListLocked()); |
|||
int firstIndex = this._childElements.Keys.FirstOrDefault(); |
|||
int lastIndex = this._childElements.Keys.LastOrDefault(); |
|||
this.widget.del.didFinishLayout(firstIndex, lastIndex); |
|||
} |
|||
|
|||
int? _currentlyUpdatingChildIndex; |
|||
|
|||
public bool debugAssertChildListLocked() { |
|||
D.assert(this._currentlyUpdatingChildIndex == null); |
|||
return true; |
|||
} |
|||
|
|||
public void didAdoptChild(RenderBox child) { |
|||
D.assert(this._currentlyUpdatingChildIndex != null); |
|||
SliverMultiBoxAdaptorParentData childParentData = (SliverMultiBoxAdaptorParentData) child.parentData; |
|||
childParentData.index = this._currentlyUpdatingChildIndex.Value; |
|||
} |
|||
|
|||
bool _didUnderflow = false; |
|||
|
|||
public void setDidUnderflow(bool value) { |
|||
this._didUnderflow = value; |
|||
} |
|||
|
|||
protected override void insertChildRenderObject(RenderObject child, object slotRaw) { |
|||
D.assert(slotRaw != null); |
|||
int slot = (int) slotRaw; |
|||
|
|||
D.assert(this._currentlyUpdatingChildIndex == slot); |
|||
D.assert(this.renderObject.debugValidateChild(child)); |
|||
this.renderObject.insert((RenderBox) child, after: this._currentBeforeChild); |
|||
D.assert(() => { |
|||
SliverMultiBoxAdaptorParentData childParentData = (SliverMultiBoxAdaptorParentData) child.parentData; |
|||
D.assert(slot == childParentData.index); |
|||
return true; |
|||
}); |
|||
} |
|||
|
|||
protected override void moveChildRenderObject(RenderObject child, object slotRaw) { |
|||
D.assert(false); |
|||
} |
|||
|
|||
protected override void removeChildRenderObject(RenderObject child) { |
|||
D.assert(this._currentlyUpdatingChildIndex != null); |
|||
this.renderObject.remove((RenderBox) child); |
|||
} |
|||
|
|||
public override void visitChildren(ElementVisitor visitor) { |
|||
D.assert(!this._childElements.Values.Any(child => child == null)); |
|||
this._childElements.Values.ToList().ForEach(e => visitor(e)); |
|||
} |
|||
|
|||
public override void debugVisitOnstageChildren(ElementVisitor visitor) { |
|||
this._childElements.Values.Where(child => { |
|||
SliverMultiBoxAdaptorParentData parentData = |
|||
(SliverMultiBoxAdaptorParentData) child.renderObject.parentData; |
|||
double itemExtent = 0; |
|||
switch (this.renderObject.constraints.axis) { |
|||
case Axis.horizontal: |
|||
itemExtent = child.renderObject.paintBounds.width; |
|||
break; |
|||
case Axis.vertical: |
|||
itemExtent = child.renderObject.paintBounds.height; |
|||
break; |
|||
} |
|||
|
|||
return parentData.layoutOffset < this.renderObject.constraints.scrollOffset + |
|||
this.renderObject.constraints.remainingPaintExtent && |
|||
parentData.layoutOffset + itemExtent > this.renderObject.constraints.scrollOffset; |
|||
}).ToList().ForEach(e => visitor(e)); |
|||
} |
|||
} |
|||
|
|||
public class KeepAlive : ParentDataWidget<SliverMultiBoxAdaptorWidget> { |
|||
public KeepAlive( |
|||
Key key = null, |
|||
bool keepAlive = true, |
|||
Widget child = null |
|||
) : base(key: key, child: child) { |
|||
D.assert(child != null); |
|||
this.keepAlive = keepAlive; |
|||
} |
|||
|
|||
public readonly bool keepAlive; |
|||
|
|||
public override void applyParentData(RenderObject renderObject) { |
|||
D.assert(renderObject.parentData is SliverMultiBoxAdaptorParentData); |
|||
SliverMultiBoxAdaptorParentData parentData = (SliverMultiBoxAdaptorParentData) renderObject.parentData; |
|||
if (parentData.keepAlive != this.keepAlive) { |
|||
parentData.keepAlive = this.keepAlive; |
|||
var targetParent = renderObject.parent; |
|||
if (targetParent is RenderObject && !this.keepAlive) { |
|||
((RenderObject) targetParent).markNeedsLayout(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public override bool debugCanApplyOutOfTurn() { |
|||
return this.keepAlive; |
|||
} |
|||
|
|||
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
|||
base.debugFillProperties(properties); |
|||
properties.add(new DiagnosticsProperty<bool>("keepAlive", this.keepAlive)); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 657ce5eaa41b4a498591bbb1682d04f4 |
|||
timeCreated: 1537323273 |
撰写
预览
正在加载...
取消
保存
Reference in new issue