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

228 行
8.2 KiB

using System;
using System.Collections.Generic;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
namespace Unity.UIWidgets.widgets {
public enum CrossFadeState {
showFirst,
showSecond
}
public delegate Widget AnimatedCrossFadeBuilder(Widget topChild, Key topChildKey, Widget bottomChild,
Key bottomChildKey);
public class AnimatedCrossFade : StatefulWidget {
public AnimatedCrossFade(
Key key = null,
Widget firstChild = null,
Widget secondChild = null,
Curve firstCurve = null,
Curve secondCurve = null,
Curve sizeCurve = null,
Alignment alignment = null,
CrossFadeState? crossFadeState = null,
TimeSpan? duration = null,
AnimatedCrossFadeBuilder layoutBuilder = null
) : base(key: key) {
D.assert(firstChild != null);
D.assert(secondChild != null);
D.assert(crossFadeState != null);
D.assert(duration != null);
this.firstChild = firstChild;
this.secondChild = secondChild;
this.firstCurve = firstCurve ?? Curves.linear;
this.secondCurve = secondCurve ?? Curves.linear;
this.sizeCurve = sizeCurve ?? Curves.linear;
this.alignment = alignment ?? Alignment.topCenter;
this.crossFadeState = crossFadeState ?? CrossFadeState.showFirst;
this.duration = duration ?? TimeSpan.Zero;
this.layoutBuilder = layoutBuilder ?? defaultLayoutBuilder;
}
public readonly Widget firstChild;
public readonly Widget secondChild;
public readonly CrossFadeState crossFadeState;
public readonly TimeSpan duration;
public readonly Curve firstCurve;
public readonly Curve secondCurve;
public readonly Curve sizeCurve;
public readonly Alignment alignment;
public readonly AnimatedCrossFadeBuilder layoutBuilder;
static Widget defaultLayoutBuilder(Widget topChild, Key topChildKey, Widget bottomChild, Key bottomChildKey) {
return new Stack(
overflow: Overflow.visible,
children: new List<Widget> {
new Positioned(
key: bottomChildKey,
left: 0.0f,
top: 0.0f,
right: 0.0f,
child: bottomChild),
new Positioned(
key: topChildKey,
child: topChild)
}
);
}
public override State createState() {
return new _AnimatedCrossFadeState();
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new EnumProperty<CrossFadeState>("crossFadeState", crossFadeState));
properties.add(new DiagnosticsProperty<Alignment>("alignment", alignment,
defaultValue: Alignment.topCenter));
}
}
public class _AnimatedCrossFadeState : TickerProviderStateMixin<AnimatedCrossFade> {
AnimationController _controller;
Animation<float> _firstAnimation;
Animation<float> _secondAnimation;
public override void initState() {
base.initState();
_controller = new AnimationController(duration: widget.duration, vsync: this);
if (widget.crossFadeState == CrossFadeState.showSecond) {
_controller.setValue(1.0f);
}
_firstAnimation = _initAnimation(widget.firstCurve, true);
_secondAnimation = _initAnimation(widget.secondCurve, false);
_controller.addStatusListener((AnimationStatus status) => { setState(() => { }); });
}
Animation<float> _initAnimation(Curve curve, bool inverted) {
Animation<float> result = _controller.drive(new CurveTween(curve: curve));
if (inverted) {
result = result.drive(new FloatTween(begin: 1.0f, end: 0.0f));
}
return result;
}
public override void dispose() {
_controller.dispose();
base.dispose();
}
public override void didUpdateWidget(StatefulWidget oldWidget) {
base.didUpdateWidget(oldWidget);
AnimatedCrossFade _oldWidget = (AnimatedCrossFade) oldWidget;
if (widget.duration != _oldWidget.duration) {
_controller.duration = widget.duration;
}
if (widget.firstCurve != _oldWidget.firstCurve) {
_firstAnimation = _initAnimation(widget.firstCurve, true);
}
if (widget.secondCurve != _oldWidget.secondCurve) {
_secondAnimation = _initAnimation(widget.secondCurve, false);
}
if (widget.crossFadeState != _oldWidget.crossFadeState) {
switch (widget.crossFadeState) {
case CrossFadeState.showFirst:
_controller.reverse();
break;
case CrossFadeState.showSecond:
_controller.forward();
break;
}
}
}
bool _isTransitioning {
get {
return _controller.status == AnimationStatus.forward ||
_controller.status == AnimationStatus.reverse;
}
}
public override Widget build(BuildContext context) {
Key kFirstChildKey = new ValueKey<CrossFadeState>(CrossFadeState.showFirst);
Key kSecondChildKey = new ValueKey<CrossFadeState>(CrossFadeState.showSecond);
bool transitioningForwards = _controller.status == AnimationStatus.completed ||
_controller.status == AnimationStatus.forward;
Key topKey;
Widget topChild;
Animation<float> topAnimation;
Key bottomKey;
Widget bottomChild;
Animation<float> bottomAnimation;
if (transitioningForwards) {
topKey = kSecondChildKey;
topChild = widget.secondChild;
topAnimation = _secondAnimation;
bottomKey = kFirstChildKey;
bottomChild = widget.firstChild;
bottomAnimation = _firstAnimation;
}
else {
topKey = kFirstChildKey;
topChild = widget.firstChild;
topAnimation = _firstAnimation;
bottomKey = kSecondChildKey;
bottomChild = widget.secondChild;
bottomAnimation = _secondAnimation;
}
bottomChild = new TickerMode(
key: bottomKey,
enabled: _isTransitioning,
child: new FadeTransition(
opacity: bottomAnimation,
child: bottomChild
)
);
topChild = new TickerMode(
key: topKey,
enabled: true,
child: new FadeTransition(
opacity: topAnimation,
child: topChild
)
);
return new ClipRect(
child: new AnimatedSize(
alignment: widget.alignment,
duration: widget.duration,
curve: widget.sizeCurve,
vsync: this,
child: widget.layoutBuilder(topChild, topKey, bottomChild, bottomKey)
)
);
}
public override void debugFillProperties(DiagnosticPropertiesBuilder description) {
base.debugFillProperties(description);
description.add(new EnumProperty<CrossFadeState>("crossFadeState", widget.crossFadeState));
description.add(
new DiagnosticsProperty<AnimationController>("controller", _controller, showName: false));
description.add(new DiagnosticsProperty<Alignment>("alignment", widget.alignment,
defaultValue: Alignment.topCenter));
}
}
}