Ata*_*yev 5 flutter flutter-animation
我正在寻找一种在 Flutter 中结合重复和不重复动画的方法。例如,开始打开动画(不重复),然后显示一些重复的动画,例如弹跳动画。目前,我在一个小部件上方使用了 2 个动画控制器和 2 个动画构建器。这是我的示例代码:
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _outerAnimationController, //starting animation, not repetitive
builder: (context, _) {
return AnimatedBuilder(
animation: _innerCurvedAnimation, //repetitive animation, bouncing
builder: (context, _) {
return CustomPaint(
size: Size(MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height),
painter: ShowCasePainter(
centerPosition: Offset(
MediaQuery.of(context).size.width / 2,
MediaQuery.of(context).size.height / 2),
innerCircleRadius: widget.innerCircleRadius +
(_innerCurvedAnimation.value * PaddingSmall), //repetitive animation value, bouncing
outerCircleRadius: _outerAnimationTween.value, //starting animation value, not repetitive
),
);
});
});
}
Run Code Online (Sandbox Code Playgroud)
以这种方式使用多个控制器是一个好习惯吗?如何从代表不同动画的两个控制器影响animatedBuilder?
感谢您的帮助!
Ata*_*yev 18
在@pskink的帮助下我终于找到了解决方案。这里不需要使用多个 AnimatedBuilder,Listenable.merge 与多个 AnimationController 就足够了。合并是可能的,因为 AnimationControllers 扩展自 Listenable 类。这是正确的代码:
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: Listenable.merge(
[_innerAnimationController, _outerAnimationController]),
builder: (context, _) {
return CustomPaint(
size: Size(MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height),
painter: ShowCasePainter(
centerPosition: Offset(MediaQuery.of(context).size.width / 2,
MediaQuery.of(context).size.height / 2),
innerCircleRadius: widget.innerCircleRadius +
(_innerCurvedAnimation.value * PaddingSmall),
outerCircleRadius: _outerAnimationTween.value,
),
);
});
}
Run Code Online (Sandbox Code Playgroud)
此解决方案适用于任何小部件,但使用 CustomPainter 有更好的解决方案。在自定义画家的情况下,动画控制器可以通过构造函数传递到自定义画家中,并且应该合并此类的内部。父构建方法:
@override
Widget build(BuildContext context) {
return CustomPaint(
willChange: true,
size: Size(MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height),
painter: ShowCasePainter(
centerPosition: Offset(MediaQuery.of(context).size.width / 2,
MediaQuery.of(context).size.height / 2),
innerCircleRadius: widget.innerCircleRadius,
outerCircleRadius: widget.outerCircleRadius,
innerAnimationController: _innerAnimationController,
outerAnimationController: _outerAnimationController,
),
);
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我仅传递了不可变值,而不是使用控制器/动画中的值。这是 CustomPainter 构造函数:
class ShowCasePainter extends CustomPainter {
final Offset centerPosition;
final double innerCircleRadius;
final double outerCircleRadius;
final Color backgroundColor;
final Color ringColor;
final Animation<double> innerAnimationController;
final Animation<double> outerAnimationController;
Animation<double> _innerCurvedAnimation;
Animation<double> _outerAnimationTween;
Animation<Color> _backgroudColorTween;
ShowCasePainter(
{this.innerAnimationController,
this.outerAnimationController,
this.centerPosition,
this.innerCircleRadius = 32.0,
this.outerCircleRadius = 128.0,
this.backgroundColor,
this.ringColor})
: super(
repaint: Listenable.merge(
[innerAnimationController, outerAnimationController])) {
_innerCurvedAnimation =
CurvedAnimation(parent: innerAnimationController, curve: Curves.easeIn);
_outerAnimationTween =
Tween(begin: innerCircleRadius, end: outerCircleRadius)
.animate(outerAnimationController);
_backgroudColorTween = ColorTween(
begin: Colors.transparent,
end: backgroundColor ?? Colors.black.withOpacity(0.2))
.animate(outerAnimationController);
}
Run Code Online (Sandbox Code Playgroud)
现在动画可以正常工作了。
| 归档时间: |
|
| 查看次数: |
2612 次 |
| 最近记录: |