Animation 如何在颤振中创建滑入和滑出动画?

Animation 如何在颤振中创建滑入和滑出动画?,animation,flutter,dart,flutter-animation,Animation,Flutter,Dart,Flutter Animation,我正在尝试在颤振中创建滑入和滑出动画。动画应如下所示: ----- Widget slides in ---> Wait for 1 seconds -----Widget slides out of screen --> 我尝试了以下代码,但我的动画陷入了循环 class _MyStatefulWidgetState extends State<MyStatefulWidget> with SingleTickerProviderStateMixin { Anim

我正在尝试在颤振中创建滑入和滑出动画。动画应如下所示:

----- Widget slides in ---> Wait for 1 seconds -----Widget slides out of screen -->
我尝试了以下代码,但我的动画陷入了循环

class _MyStatefulWidgetState extends State<MyStatefulWidget> with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<Offset> _positionAnimation;
  Animation<double> opacityAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    );

    _positionAnimation = Tween<Offset>(
      begin: const Offset(-1, 0),
      end: const Offset(0, 0.0),
    ).animate(
      CurvedAnimation(
          parent: _controller,
          curve: Curves.elasticOut),
    )..addStatusListener((status) {
        print('animation 1 status $status');
        if (status == AnimationStatus.completed) {
          _controller.reset();
        }
        if (status == AnimationStatus.dismissed) {
          _positionAnimation = Tween<Offset>(
            begin: const Offset(0, 0),
            end: const Offset(1, 0.0),
          ).animate(
            CurvedAnimation(
                parent: _controller,
                curve: Curves.elasticIn),
          )..addStatusListener((status2) {
              print('animation 2 status $status2');
            if (status == AnimationStatus.dismissed) {
              _controller.reset();
            }
            });
          _controller.forward();
        }
      });
    _controller.forward();
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      builder: _buildAnimation,
      animation: _controller,
    );
  }

  Widget _buildAnimation(BuildContext context, Widget child) {
    return Opacity(
      opacity: 1,
      child: SlideTransition(
        position: _positionAnimation,
        child: Container(
          color: Colors.blueAccent,
          height: 100,
          child: Center(
            child: Text(
              'Hello, World!',
              style: Theme.of(context).textTheme.display1,
            ),
          ),
        ),
      ),
    );
  }
class\u MyStatefulWidgetState使用SingleTickerProviderStateMixin扩展状态{
动画控制器_控制器;
动画(动画),;
动画不透明;
@凌驾
void initState(){
super.initState();
_控制器=动画控制器(
持续时间:常数持续时间(秒数:2),
vsync:这个,,
);
_位置动画=吐温(
开始:常量偏移量(-1,0),
结束:常数偏移(0,0.0),
).制作动画(
曲线化(
父节点:_控制器,
曲线:曲线。elasticOut),
)..addStatusListener((状态){
打印(“动画1状态$status”);
如果(状态==AnimationStatus.completed){
_controller.reset();
}
如果(状态==AnimationStatus.discomered){
_位置动画=吐温(
开始:常量偏移量(0,0),
结束:常数偏移(1,0.0),
).制作动画(
曲线化(
父节点:_控制器,
曲线:曲线。弹力素),
)..addStatusListener((状态2){
打印(“动画2状态$status2”);
如果(状态==AnimationStatus.discomered){
_controller.reset();
}
});
_controller.forward();
}
});
_controller.forward();
}
@凌驾
无效处置(){
super.dispose();
_controller.dispose();
}
@凌驾
小部件构建(构建上下文){
返回动画生成器(
生成器:_buildAnimation,
动画:_控制器,
);
}
Widget\u buildAnimation(BuildContext上下文,Widget子项){
返回不透明度(
不透明度:1,
子:幻灯片转换(
位置:_位置动画,
子:容器(
颜色:Colors.blueAccent,
身高:100,
儿童:中心(
子:文本(
“你好,世界!”,
样式:Theme.of(context).textTheme.display1,
),
),
),
),
);
}
使用这种方法,动画会陷入循环中

我无法使用交错动画,因为我正在尝试为同一属性设置动画。(或者有没有办法在同一属性上使用交错动画?)。
有没有更好的方法来实现这一点?

使用
Marquee
文本动画插件

安装:

  marquee: ^1.3.1
例如:

Marquee(
  text: 'There once was a boy who told this story about a boy: "',
)

要了解更多信息,请尝试使用
字幕
插件制作文本动画

安装:

  marquee: ^1.3.1
例如:

Marquee(
  text: 'There once was a boy who told this story about a boy: "',
)

在获得更多信息之前,请尝试在注释中从@pskink代码中获取想法,使用TweenAnimationBuilder通过以下代码达到预期效果:

class _SlideInOutWidgetState extends State<SlideInOutWidget>
    with SingleTickerProviderStateMixin {
  double startPos = -1.0;
  double endPos = 0.0;
  Curve curve = Curves.elasticOut;
  @override
  Widget build(BuildContext context) {
    return TweenAnimationBuilder(
      tween: Tween<Offset>(begin: Offset(startPos, 0), end: Offset(endPos, 0)),
      duration: Duration(seconds: 1),
      curve: curve,
      builder: (context, offset, child) {
        return FractionalTranslation(
          translation: offset,
          child: Container(
            width: double.infinity,
            child: Center(
              child: child,
            ),
          ),
        );
      },
      child: Text('animated text', textScaleFactor: 3.0,),
      onEnd: () {
        print('onEnd');
        Future.delayed(
          Duration(milliseconds: 500),
          () {
            curve = curve == Curves.elasticOut
                ? Curves.elasticIn
                : Curves.elasticOut;
            if (startPos == -1) {
              setState(() {
                startPos = 0.0;
                endPos = 1.0;
              });
            }
          },
        );
      },
    );
  }
}
类_slideInowdgetState扩展状态
使用SingleTickerProviderStateMixin{
双启动OS=-1.0;
双端POS=0.0;
曲线=Curves.elasticOut;
@凌驾
小部件构建(构建上下文){
返回TweenAnimationBuilder(
吐温:吐温(开始:偏移量(起始点,0),结束:偏移量(结束点,0)),
持续时间:持续时间(秒数:1),
曲线:曲线,
生成器:(上下文、偏移、子对象){
返回分馏翻译(
翻译:抵销,
子:容器(
宽度:double.infinity,
儿童:中心(
孩子:孩子,
),
),
);
},
子项:Text('animated Text',textScaleFactor:3.0,),
ONED:(){
打印('onEnd');
推迟(
持续时间(毫秒:500),
() {
曲线=曲线==曲线.elasticOut
?弹性蛋白
:Curves.elasticOut;
如果(startPos==-1){
设置状态(){
startPos=0.0;
endPos=1.0;
});
}
},
);
},
);
}
}

在注释中借鉴@pskink代码的思想,使用
TweenAnimationBuilder
,使用以下代码达到了预期效果:

class _SlideInOutWidgetState extends State<SlideInOutWidget>
    with SingleTickerProviderStateMixin {
  double startPos = -1.0;
  double endPos = 0.0;
  Curve curve = Curves.elasticOut;
  @override
  Widget build(BuildContext context) {
    return TweenAnimationBuilder(
      tween: Tween<Offset>(begin: Offset(startPos, 0), end: Offset(endPos, 0)),
      duration: Duration(seconds: 1),
      curve: curve,
      builder: (context, offset, child) {
        return FractionalTranslation(
          translation: offset,
          child: Container(
            width: double.infinity,
            child: Center(
              child: child,
            ),
          ),
        );
      },
      child: Text('animated text', textScaleFactor: 3.0,),
      onEnd: () {
        print('onEnd');
        Future.delayed(
          Duration(milliseconds: 500),
          () {
            curve = curve == Curves.elasticOut
                ? Curves.elasticIn
                : Curves.elasticOut;
            if (startPos == -1) {
              setState(() {
                startPos = 0.0;
                endPos = 1.0;
              });
            }
          },
        );
      },
    );
  }
}
类_slideInowdgetState扩展状态
使用SingleTickerProviderStateMixin{
双启动OS=-1.0;
双端POS=0.0;
曲线=Curves.elasticOut;
@凌驾
小部件构建(构建上下文){
返回TweenAnimationBuilder(
吐温:吐温(开始:偏移量(起始点,0),结束:偏移量(结束点,0)),
持续时间:持续时间(秒数:1),
曲线:曲线,
生成器:(上下文、偏移、子对象){
返回分馏翻译(
翻译:抵销,
子:容器(
宽度:double.infinity,
儿童:中心(
孩子:孩子,
),
),
);
},
子项:Text('animated Text',textScaleFactor:3.0,),
ONED:(){
打印('onEnd');
推迟(
持续时间(毫秒:500),
() {
曲线=曲线==曲线.elasticOut
?弹性蛋白
:Curves.elasticOut;
如果(startPos==-1){
设置状态(){
startPos=0.0;
endPos=1.0;
});
}
},
);
},
);
}
}

如果您使用SlideTransition@pskink我也尝试过SlideTransition,但未能实现所需的行为。
child:TweenAnimationBuilder(onEnd:(){print('onEnd');Future.delayed(持续时间(毫秒:1000),()=>setState(()=>xpos=xpos==0?1:0));},持续时间:持续时间(毫秒:750),tween:tween(开始:偏移量(1,0),结束:偏移量(xpos,0)),生成器:(上下文,偏移量,子项){返回部分翻译(翻译:偏移量,子项:容器(宽度:double.infinity,子项:文本('animated Text',textScaleFactor:3.0,);},,,,,,,