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

397 行
16 KiB

using System;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.scheduler;
using Unity.UIWidgets.ui;
using UnityEngine;
namespace Unity.UIWidgets.rendering {
public abstract class RenderSliverPersistentHeader : RenderObjectWithChildMixinRenderSliver<RenderBox> {
public RenderSliverPersistentHeader(RenderBox child = null) {
this.child = child;
}
public virtual float? maxExtent { get; }
public virtual float? minExtent { get; }
public float childExtent {
get {
if (this.child == null) {
return 0.0f;
}
D.assert(this.child.hasSize);
switch (this.constraints.axis) {
case Axis.vertical:
return this.child.size.height;
case Axis.horizontal:
return this.child.size.width;
default:
throw new Exception("Unknown axis: " + this.constraints.axis);
}
}
}
bool _needsUpdateChild = true;
float _lastShrinkOffset = 0.0f;
bool _lastOverlapsContent = false;
protected virtual void updateChild(float shrinkOffset, bool overlapsContent) {
}
public override void markNeedsLayout() {
this._needsUpdateChild = true;
base.markNeedsLayout();
}
protected void layoutChild(float scrollOffset, float maxExtent, bool overlapsContent = false) {
float shrinkOffset = Mathf.Min(scrollOffset, maxExtent);
if (this._needsUpdateChild || this._lastShrinkOffset != shrinkOffset ||
this._lastOverlapsContent != overlapsContent) {
this.invokeLayoutCallback<SliverConstraints>((SliverConstraints constraints) => {
D.assert(constraints == this.constraints);
this.updateChild(shrinkOffset, overlapsContent);
});
this._lastShrinkOffset = shrinkOffset;
this._lastOverlapsContent = overlapsContent;
this._needsUpdateChild = false;
}
D.assert(this.minExtent != null);
D.assert(() => {
if (this.minExtent <= maxExtent) {
return true;
}
throw new UIWidgetsError(
"The maxExtent for this $runtimeType is less than its minExtent.\n" +
"The specified maxExtent was: ${maxExtent.toStringAsFixed(1)}\n" +
"The specified minExtent was: ${minExtent.toStringAsFixed(1)}\n"
);
});
this.child?.layout(
this.constraints.asBoxConstraints(
maxExtent: Mathf.Max(this.minExtent ?? 0.0f, maxExtent - shrinkOffset)),
parentUsesSize: true
);
}
public override float childMainAxisPosition(RenderObject child) {
return base.childMainAxisPosition(this.child);
}
protected override bool hitTestChildren(HitTestResult result, float mainAxisPosition, float crossAxisPosition) {
D.assert(this.geometry.hitTestExtent > 0.0f);
if (this.child != null) {
return RenderSliverHelpers.hitTestBoxChild(this, result, this.child, mainAxisPosition: mainAxisPosition,
crossAxisPosition: crossAxisPosition);
}
return false;
}
public override void applyPaintTransform(RenderObject child, Matrix3 transform) {
D.assert(child != null);
D.assert(child == this.child);
RenderSliverHelpers.applyPaintTransformForBoxChild(this, this.child, transform);
}
public override void paint(PaintingContext context, Offset offset) {
if (this.child != null && this.geometry.visible) {
switch (GrowthDirectionUtils.applyGrowthDirectionToAxisDirection(this.constraints.axisDirection,
this.constraints.growthDirection)) {
case AxisDirection.up:
offset += new Offset(0.0f,
this.geometry.paintExtent - this.childMainAxisPosition(this.child) - this.childExtent);
break;
case AxisDirection.down:
offset += new Offset(0.0f, this.childMainAxisPosition(this.child));
break;
case AxisDirection.left:
offset += new Offset(
this.geometry.paintExtent - this.childMainAxisPosition(this.child) - this.childExtent,
0.0f);
break;
case AxisDirection.right:
offset += new Offset(this.childMainAxisPosition(this.child), 0.0f);
break;
}
context.paintChild(this.child, offset);
}
}
protected bool excludeFromSemanticsScrolling {
get { return this._excludeFromSemanticsScrolling; }
set {
if (this._excludeFromSemanticsScrolling == value) {
return;
}
this._excludeFromSemanticsScrolling = value;
}
}
bool _excludeFromSemanticsScrolling = false;
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(FloatProperty.lazy("maxExtent", () => this.maxExtent));
properties.add(FloatProperty.lazy("child position", () => this.childMainAxisPosition(this.child)));
}
}
public abstract class RenderSliverScrollingPersistentHeader : RenderSliverPersistentHeader {
public RenderSliverScrollingPersistentHeader(
RenderBox child = null
) : base(child: child) {
}
float _childPosition;
protected override void performLayout() {
float? maxExtent = this.maxExtent;
this.layoutChild(this.constraints.scrollOffset, maxExtent ?? 0.0f);
float? paintExtent = maxExtent - this.constraints.scrollOffset;
this.geometry = new SliverGeometry(
scrollExtent: maxExtent ?? 0.0f,
paintOrigin: Mathf.Min(this.constraints.overlap, 0.0f),
paintExtent: paintExtent?.clamp(0.0f, this.constraints.remainingPaintExtent) ?? 0.0f,
maxPaintExtent: maxExtent ?? 0.0f,
hasVisualOverflow: true
);
this._childPosition = Mathf.Min(0.0f, paintExtent ?? 0.0f - this.childExtent);
}
public override float childMainAxisPosition(RenderObject child) {
D.assert(child == this.child);
return this._childPosition;
}
}
public abstract class RenderSliverPinnedPersistentHeader : RenderSliverPersistentHeader {
public RenderSliverPinnedPersistentHeader(
RenderBox child = null
) : base(child: child) {
}
protected override void performLayout() {
float? maxExtent = this.maxExtent;
bool overlapsContent = this.constraints.overlap > 0.0f;
this.excludeFromSemanticsScrolling =
overlapsContent || (this.constraints.scrollOffset > maxExtent - this.minExtent);
this.layoutChild(this.constraints.scrollOffset, maxExtent ?? 0.0f, overlapsContent: overlapsContent);
float? layoutExtent =
(maxExtent - this.constraints.scrollOffset)?.clamp(0.0f, this.constraints.remainingPaintExtent);
this.geometry = new SliverGeometry(
scrollExtent: maxExtent ?? 0.0f,
paintOrigin: this.constraints.overlap,
paintExtent: Mathf.Min(this.childExtent, this.constraints.remainingPaintExtent),
layoutExtent: layoutExtent,
maxPaintExtent: maxExtent ?? 0.0f,
maxScrollObstructionExtent: this.minExtent ?? 0.0f,
cacheExtent: layoutExtent > 0.0f ? -this.constraints.cacheOrigin + layoutExtent : layoutExtent,
hasVisualOverflow: true
);
}
public override float childMainAxisPosition(RenderObject child) {
return 0.0f;
}
}
public class FloatingHeaderSnapConfiguration {
public FloatingHeaderSnapConfiguration(
TickerProvider vsync,
Curve curve = null,
TimeSpan? duration = null
) {
D.assert(vsync != null);
this.vsync = vsync;
this.curve = curve ?? Curves.ease;
this.duration = duration ?? new TimeSpan(0, 0, 0, 0, 300);
}
public readonly TickerProvider vsync;
public readonly Curve curve;
public readonly TimeSpan duration;
}
public abstract class RenderSliverFloatingPersistentHeader : RenderSliverPersistentHeader {
public RenderSliverFloatingPersistentHeader(
RenderBox child = null,
FloatingHeaderSnapConfiguration snapConfiguration = null
) : base(child: child) {
this._snapConfiguration = snapConfiguration;
}
AnimationController _controller;
Animation<float> _animation;
protected float _lastActualScrollOffset;
protected float _effectiveScrollOffset;
float _childPosition;
public override void detach() {
this._controller?.dispose();
this._controller = null;
base.detach();
}
public FloatingHeaderSnapConfiguration snapConfiguration {
get { return this._snapConfiguration; }
set {
if (value == this._snapConfiguration) {
return;
}
if (value == null) {
this._controller?.dispose();
this._controller = null;
}
else {
if (this._snapConfiguration != null && value.vsync != this._snapConfiguration.vsync) {
this._controller?.resync(value.vsync);
}
}
this._snapConfiguration = value;
}
}
FloatingHeaderSnapConfiguration _snapConfiguration;
protected virtual float updateGeometry() {
float? maxExtent = this.maxExtent;
float? paintExtent = maxExtent - this._effectiveScrollOffset;
float? layoutExtent = maxExtent - this.constraints.scrollOffset;
this.geometry = new SliverGeometry(
scrollExtent: maxExtent ?? 0.0f,
paintOrigin: Mathf.Min(this.constraints.overlap, 0.0f),
paintExtent: paintExtent?.clamp(0.0f, this.constraints.remainingPaintExtent) ?? 0.0f,
layoutExtent: layoutExtent?.clamp(0.0f, this.constraints.remainingPaintExtent),
maxPaintExtent: maxExtent ?? 0.0f,
maxScrollObstructionExtent: maxExtent ?? 0.0f,
hasVisualOverflow: true
);
return Mathf.Min(0.0f, paintExtent ?? 0.0f - this.childExtent);
}
public void maybeStartSnapAnimation(ScrollDirection direction) {
if (this.snapConfiguration == null) {
return;
}
if (direction == ScrollDirection.forward && this._effectiveScrollOffset <= 0.0f) {
return;
}
if (direction == ScrollDirection.reverse && this._effectiveScrollOffset >= this.maxExtent) {
return;
}
TickerProvider vsync = this.snapConfiguration.vsync;
TimeSpan duration = this.snapConfiguration.duration;
this._controller = this._controller ?? new AnimationController(vsync: vsync, duration: duration);
this._controller.addListener(() => {
if (this._effectiveScrollOffset == this._animation.value) {
return;
}
this._effectiveScrollOffset = this._animation.value;
this.markNeedsLayout();
});
this._animation = this._controller.drive(
new FloatTween(
begin: this._effectiveScrollOffset,
end: direction == ScrollDirection.forward ? 0.0f : this.maxExtent ?? 0.0f
).chain(new CurveTween(
curve: this.snapConfiguration.curve
))
);
this._controller.forward(from: 0.0f);
}
public void maybeStopSnapAnimation(ScrollDirection direction) {
this._controller?.stop();
}
protected override void performLayout() {
float? maxExtent = this.maxExtent;
if (((this.constraints.scrollOffset < this._lastActualScrollOffset) ||
(this._effectiveScrollOffset < maxExtent))) {
float delta = this._lastActualScrollOffset - this.constraints.scrollOffset;
bool allowFloatingExpansion = this.constraints.userScrollDirection == ScrollDirection.forward;
if (allowFloatingExpansion) {
if (this._effectiveScrollOffset > maxExtent) {
this._effectiveScrollOffset = maxExtent ?? 0.0f;
}
}
else {
if (delta > 0.0f) {
delta = 0.0f;
}
}
this._effectiveScrollOffset =
(this._effectiveScrollOffset - delta).clamp(0.0f, this.constraints.scrollOffset);
}
else {
this._effectiveScrollOffset = this.constraints.scrollOffset;
}
bool overlapsContent = this._effectiveScrollOffset < this.constraints.scrollOffset;
this.excludeFromSemanticsScrolling = overlapsContent;
this.layoutChild(this._effectiveScrollOffset, maxExtent ?? 0.0f, overlapsContent: overlapsContent);
this._childPosition = this.updateGeometry();
this._lastActualScrollOffset = this.constraints.scrollOffset;
}
public override float childMainAxisPosition(RenderObject child) {
D.assert(child == this.child);
return this._childPosition;
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new FloatProperty("effective scroll offset", this._effectiveScrollOffset));
}
}
public abstract class RenderSliverFloatingPinnedPersistentHeader : RenderSliverFloatingPersistentHeader {
public RenderSliverFloatingPinnedPersistentHeader(
RenderBox child = null,
FloatingHeaderSnapConfiguration snapConfiguration = null
) : base(child: child, snapConfiguration: snapConfiguration) {
}
protected override float updateGeometry() {
float? minExtent = this.minExtent;
float? minAllowedExtent = this.constraints.remainingPaintExtent > minExtent
? minExtent
: this.constraints.remainingPaintExtent;
float? maxExtent = this.maxExtent;
float? paintExtent = maxExtent - this._effectiveScrollOffset;
float? clampedPaintExtent =
paintExtent?.clamp(minAllowedExtent ?? 0.0f, this.constraints.remainingPaintExtent);
float? layoutExtent = maxExtent - this.constraints.scrollOffset;
this.geometry = new SliverGeometry(
scrollExtent: maxExtent ?? 0.0f,
paintExtent: clampedPaintExtent ?? 0.0f,
layoutExtent: layoutExtent?.clamp(0.0f, clampedPaintExtent ?? 0.0f),
maxPaintExtent: maxExtent ?? 0.0f,
maxScrollObstructionExtent: maxExtent ?? 0.0f,
hasVisualOverflow: true
);
return 0.0f;
}
}
}