您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
218 行
6.7 KiB
218 行
6.7 KiB
using System;
|
|
using Unity.UIWidgets.animation;
|
|
using Unity.UIWidgets.foundation;
|
|
using Unity.UIWidgets.painting;
|
|
using Unity.UIWidgets.scheduler;
|
|
using Unity.UIWidgets.ui;
|
|
|
|
namespace Unity.UIWidgets.rendering {
|
|
public enum RenderAnimatedSizeState {
|
|
start,
|
|
stable,
|
|
changed,
|
|
unstable
|
|
}
|
|
|
|
public class RenderAnimatedSize : RenderAligningShiftedBox {
|
|
public RenderAnimatedSize(
|
|
TickerProvider vsync = null,
|
|
TimeSpan? duration = null,
|
|
TimeSpan? reverseDuration = null,
|
|
Curve curve = null,
|
|
AlignmentGeometry alignment = null,
|
|
TextDirection? textDirection = null,
|
|
RenderBox child = null
|
|
) : base(child: child, alignment: alignment ?? Alignment.center, textDirection: textDirection) {
|
|
curve = curve ?? Curves.linear;
|
|
D.assert(vsync != null);
|
|
D.assert(duration != null);
|
|
_vsync = vsync;
|
|
_controller = new AnimationController(
|
|
vsync: this.vsync,
|
|
duration: duration,
|
|
reverseDuration: reverseDuration);
|
|
_controller.addListener(() => {
|
|
if (_controller.value != _lastValue) {
|
|
markNeedsLayout();
|
|
}
|
|
});
|
|
_animation = new CurvedAnimation(
|
|
parent: _controller,
|
|
curve: curve);
|
|
}
|
|
|
|
AnimationController _controller;
|
|
CurvedAnimation _animation;
|
|
readonly SizeTween _sizeTween = new SizeTween();
|
|
bool _hasVisualOverflow;
|
|
float _lastValue;
|
|
|
|
public RenderAnimatedSizeState state {
|
|
get { return _state; }
|
|
}
|
|
|
|
RenderAnimatedSizeState _state = RenderAnimatedSizeState.start;
|
|
|
|
public TimeSpan? duration {
|
|
get { return _controller.duration; }
|
|
set {
|
|
D.assert(value != null);
|
|
if (value == _controller.duration) {
|
|
return;
|
|
}
|
|
|
|
_controller.duration = value;
|
|
}
|
|
}
|
|
|
|
/// The duration of the animation when running in reverse.
|
|
public TimeSpan? reverseDuration {
|
|
get { return _controller.reverseDuration; }
|
|
set {
|
|
if (value == _controller.reverseDuration) {
|
|
return;
|
|
}
|
|
|
|
_controller.reverseDuration = value;
|
|
}
|
|
}
|
|
|
|
public Curve curve {
|
|
get { return _animation.curve; }
|
|
set {
|
|
D.assert(value != null);
|
|
if (value == _animation.curve) {
|
|
return;
|
|
}
|
|
|
|
_animation.curve = value;
|
|
}
|
|
}
|
|
|
|
public bool isAnimating {
|
|
get { return _controller.isAnimating; }
|
|
}
|
|
|
|
public TickerProvider vsync {
|
|
get { return _vsync; }
|
|
set {
|
|
D.assert(value != null);
|
|
if (value == _vsync) {
|
|
return;
|
|
}
|
|
|
|
_vsync = value;
|
|
_controller.resync(vsync);
|
|
}
|
|
}
|
|
|
|
TickerProvider _vsync;
|
|
|
|
public override void detach() {
|
|
_controller.stop();
|
|
base.detach();
|
|
}
|
|
|
|
Size _animatedSize {
|
|
get { return _sizeTween.evaluate(_animation); }
|
|
}
|
|
|
|
protected override void performLayout() {
|
|
_lastValue = _controller.value;
|
|
_hasVisualOverflow = false;
|
|
BoxConstraints constraints = this.constraints;
|
|
if (child == null || constraints.isTight) {
|
|
_controller.stop();
|
|
size = _sizeTween.begin = _sizeTween.end = constraints.smallest;
|
|
_state = RenderAnimatedSizeState.start;
|
|
child?.layout(constraints);
|
|
return;
|
|
}
|
|
|
|
child.layout(constraints, parentUsesSize: true);
|
|
|
|
switch (_state) {
|
|
case RenderAnimatedSizeState.start:
|
|
_layoutStart();
|
|
break;
|
|
case RenderAnimatedSizeState.stable:
|
|
_layoutStable();
|
|
break;
|
|
case RenderAnimatedSizeState.changed:
|
|
_layoutChanged();
|
|
break;
|
|
case RenderAnimatedSizeState.unstable:
|
|
_layoutUnstable();
|
|
break;
|
|
}
|
|
|
|
size = constraints.constrain(_animatedSize);
|
|
alignChild();
|
|
|
|
if (size.width < _sizeTween.end.width ||
|
|
size.height < _sizeTween.end.height) {
|
|
_hasVisualOverflow = true;
|
|
}
|
|
}
|
|
|
|
void _restartAnimation() {
|
|
_lastValue = 0.0f;
|
|
_controller.forward(from: 0.0f);
|
|
}
|
|
|
|
void _layoutStart() {
|
|
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child.size);
|
|
_state = RenderAnimatedSizeState.stable;
|
|
}
|
|
|
|
void _layoutStable() {
|
|
if (_sizeTween.end != child.size) {
|
|
_sizeTween.begin = size;
|
|
_sizeTween.end = debugAdoptSize(child.size);
|
|
_restartAnimation();
|
|
_state = RenderAnimatedSizeState.changed;
|
|
}
|
|
else if (_controller.value == _controller.upperBound) {
|
|
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child.size);
|
|
}
|
|
else if (!_controller.isAnimating) {
|
|
_controller.forward();
|
|
}
|
|
}
|
|
|
|
void _layoutChanged() {
|
|
if (_sizeTween.end != child.size) {
|
|
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child.size);
|
|
_restartAnimation();
|
|
_state = RenderAnimatedSizeState.unstable;
|
|
}
|
|
else {
|
|
_state = RenderAnimatedSizeState.stable;
|
|
if (!_controller.isAnimating) {
|
|
_controller.forward();
|
|
}
|
|
}
|
|
}
|
|
|
|
void _layoutUnstable() {
|
|
if (_sizeTween.end != child.size) {
|
|
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child.size);
|
|
_restartAnimation();
|
|
}
|
|
else {
|
|
_controller.stop();
|
|
_state = RenderAnimatedSizeState.stable;
|
|
}
|
|
}
|
|
|
|
public override void paint(PaintingContext context, Offset offset) {
|
|
if (child != null && _hasVisualOverflow) {
|
|
Rect rect = Offset.zero & size;
|
|
context.pushClipRect(needsCompositing, offset, rect, base.paint);
|
|
}
|
|
else {
|
|
base.paint(context, offset);
|
|
}
|
|
}
|
|
}
|
|
}
|