Во время работы вы ни в коем случае не захотите сделать эти анимации в пределах вашего макета, как объясняет @filleduchaos.
Это недостаточно оптимизировано, поскольку вы перестраиваете намного больше, чем нужно для анимации.И писать себе тяжело.
Для этого вам понадобится семья AnimatedWidget
.Они делятся на два вида:
Первый - это низкий слой, который потребляет Animation
и слушает его так,что вам не нужно делать это безобразно:
..addListener(() {
setState(() {});
});
Второй обрабатывает оставшиеся части: AnimationController
, TickerProvider
и Tween
.
Это делает использование анимаций намного проще, поскольку это почти полностью автоматически.
В вашем случае пример поворота будет следующим:
class RotationExample extends StatefulWidget {
final Widget child;
const RotationExample({
Key key,
this.child,
}) : super(key: key);
@override
RotationExampleState createState() {
return new RotationExampleState();
}
}
class RotationExampleState extends State<RotationExample> {
final _random = math.Random();
double rad = 0.0;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _rotate,
child: AnimatedTransform(
duration: const Duration(seconds: 1),
alignment: Alignment.center,
transform: Matrix4.rotationZ(rad),
child: Container(
color: Colors.red,
height: 42.0,
width: 42.0,
),
),
);
}
void _rotate() {
setState(() {
rad = math.pi * 2 / 25 * _random.nextInt(25);
});
}
}
Проще, правда?
Ирония в том, что Флаттер забыл предоставить AnimatedTransform
(хотяу нас много других!).Но не беспокойтесь, я сделал это для вас!
Реализация AnimatedTransform
выглядит следующим образом:
class AnimatedTransform extends ImplicitlyAnimatedWidget {
final Matrix4 transform;
final AlignmentGeometry alignment;
final bool transformHitTests;
final Offset origin;
final Widget child;
const AnimatedTransform({
Key key,
@required this.transform,
@required Duration duration,
this.alignment,
this.transformHitTests = true,
this.origin,
this.child,
Curve curve = Curves.linear,
}) : assert(transform != null),
assert(duration != null),
super(
key: key,
duration: duration,
curve: curve,
);
@override
_AnimatedTransformState createState() => _AnimatedTransformState();
}
class _AnimatedTransformState
extends AnimatedWidgetBaseState<AnimatedTransform> {
Matrix4Tween _transform;
@override
void forEachTween(TweenVisitor<dynamic> visitor) {
_transform = visitor(_transform, widget.transform,
(dynamic value) => Matrix4Tween(begin: value));
}
@override
Widget build(BuildContext context) {
return Transform(
alignment: widget.alignment,
transform: _transform.evaluate(animation),
transformHitTests: widget.transformHitTests,
origin: widget.origin,
child: widget.child,
);
}
}
Я отправлю запрос на извлечение, чтобы в будущем вам не понадобилсяэтот бит кода.