【问题标题】:Flutter one time animation for each start of app(not first run)每次启动应用程序时颤动一次动画(不是第一次运行)
【发布时间】:2020-07-05 09:02:54
【问题描述】:

我想在我的主屏幕上使用一些动画,但只在应用启动时使用,因为在使用应用时,用户必须经常导航回主屏幕,而这些动画会导致加载时间变得很烦人,一次又一次地看到......所以, 有没有办法让动画只在应用程序的第一次启动(而不是第一次运行)时处于活动状态,然后在重新启动应用程序之前使其处于非活动状态?

这是一个简单的代码;与我使用的动画的逻辑不同但相似,我的代码太复杂而无法复制粘贴,所以我发送了一个示例代码,我将其发送给另一个问题作为答案;

import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() {
 runApp(MyApp());
}

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     title: 'Flutter Demo',
     theme: ThemeData(
       primarySwatch: Colors.blue,
     ),
     home: MyHomePage(title: 'Flutter Demo Home Page'),
   );
 }
}

class MyHomePage extends StatefulWidget {
 MyHomePage({Key key, this.title}) : super(key: key);

 final String title;

 @override
 _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     body: Center(
       child: ListView(
         children: [Container(
           color: Colors.blue,
           height: 1000,
           child: Column(
             mainAxisAlignment: MainAxisAlignment.center,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: <Widget>[
               SlideFadeTransition(
                   delayStart: Duration(milliseconds: 800),
                   offset: 2,
                   child: new Text('Test Text 1')),
               SlideFadeTransition(
                   delayStart: Duration(milliseconds: 1200),
                   offset: 4,
                   child: new Text('Test Text 2'))
             ],
           ),
         ),
           Container(
             color: Colors.red,
             height: 1000,
             child: Column(
               mainAxisAlignment: MainAxisAlignment.center,
               crossAxisAlignment: CrossAxisAlignment.center,
               children: <Widget>[
                 SlideFadeTransition(
                     delayStart: Duration(milliseconds: 1200),
                     offset: 2,
                     child: new Text('Test Text 1')),
                 SlideFadeTransition(
                     delayStart: Duration(milliseconds: 2400),
                     offset: 4,
                     child: new Text('Test Text 2'))
               ],
             ),
           ),
           Container(
             color: Colors.orange,
             height: 1000,
             child: Column(
               mainAxisAlignment: MainAxisAlignment.center,
               crossAxisAlignment: CrossAxisAlignment.center,
               children: <Widget>[
                 SlideFadeTransition(
                     delayStart: Duration(milliseconds: 1200),
                     offset: 2,
                     child: new Text('Test Text 1')),
                 SlideFadeTransition(
                     delayStart: Duration(milliseconds: 2400),
                     offset: 4,
                     child: new Text('Test Text 2'))
               ],
             ),
           ),
 ]
   )
   )
   );
 }
}


enum Direction { vertical, horizontal }

class SlideFadeTransition extends StatefulWidget {
 ///The child on which to apply the given [SlideFadeTransition]
 final Widget child;

 ///The offset by which to slide and [child] into view from [Direction].
 ///Defaults to 0.2
 final double offset;

 ///The curve used to animate the [child] into view.
 ///Defaults to [Curves.easeIn]
 final Curve curve;

 ///The direction from which to animate the [child] into view. [Direction.horizontal]
 ///will make the child slide on x-axis by [offset] and [Direction.vertical] on y-axis.
 ///Defaults to [Direction.vertical]
 final Direction direction;

 ///The delay with which to animate the [child]. Takes in a [Duration] and
 /// defaults to 0.0 seconds
 final Duration delayStart;

 ///The total duration in which the animation completes. Defaults to 800 milliseconds
 final Duration animationDuration;

 SlideFadeTransition({
   @required this.child,
   this.offset = 0.2,
   this.curve = Curves.easeIn,
   this.direction = Direction.vertical,
   this.delayStart = const Duration(seconds: 0),
   this.animationDuration = const Duration(milliseconds: 800),
 });
 @override
 _SlideFadeTransitionState createState() => _SlideFadeTransitionState();
}

class _SlideFadeTransitionState extends State<SlideFadeTransition>
   with SingleTickerProviderStateMixin {
 Animation<Offset> _animationSlide;

 AnimationController _animationController;

 Animation<double> _animationFade;

 @override
 void initState() {
   super.initState();
   _animationController = AnimationController(
     vsync: this,
     duration: widget.animationDuration,
   );

   //configure the animation controller as per the direction
   if (widget.direction == Direction.vertical) {
     _animationSlide =
         Tween<Offset>(begin: Offset(0, widget.offset), end: Offset(0, 0))
             .animate(CurvedAnimation(
           curve: widget.curve,
           parent: _animationController,
         ));
   } else {
     _animationSlide =
         Tween<Offset>(begin: Offset(widget.offset, 0), end: Offset(0, 0))
             .animate(CurvedAnimation(
           curve: widget.curve,
           parent: _animationController,
         ));
   }

   _animationFade =
       Tween<double>(begin: -1.0, end: 1.0).animate(CurvedAnimation(
         curve: widget.curve,
         parent: _animationController,
       ));

   Timer(widget.delayStart, () {
     _animationController.forward();
   });
 }

 @override
 Widget build(BuildContext context) {
   return FadeTransition(
     opacity: _animationFade,
     child: SlideTransition(
       position: _animationSlide,
       child: widget.child,
     ),
   );}}

【问题讨论】:

    标签: flutter flutter-layout flutter-animation


    【解决方案1】:

    您可以在下面复制粘贴运行完整代码
    第 1 步:您可以定义一个 bool firstRun = true
    第 2 步:导航到其他页面时,将 firstRun 设置为 false
    第三步:在_SlideFadeTransitionStatebuild方法中检查是否不是firstRun并直接返回widget.child

    return firstRun? FadeTransition(...widget.child) : widget.child
    

    工作演示

    代码sn-p

    bool firstRun = true;
    ...
    RaisedButton(
            child: Text('Open route'),
            onPressed: () {
              firstRun = false;
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => SecondRoute()),
              );
            },
          )
    ...
    
      @override
      Widget build(BuildContext context) {
        print('first run ${firstRun}');
        return firstRun? FadeTransition(
          opacity: _animationFade,
          child: SlideTransition(
            position: _animationSlide,
            child: widget.child,
          ),
        ) : widget.child;
      } 
    

    完整代码

    import 'dart:async';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    bool firstRun = true;
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            body: Center(
                child: ListView(children: [
          Container(
            color: Colors.blue,
            height: 1000,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                SlideFadeTransition(
                    delayStart: Duration(milliseconds: 800),
                    offset: 2,
                    child: new Text('Test Text 1')),
                SlideFadeTransition(
                    delayStart: Duration(milliseconds: 1200),
                    offset: 4,
                    child: new Text('Test Text 2'))
              ],
            ),
          ),
          Container(
            color: Colors.red,
            height: 1000,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                SlideFadeTransition(
                    delayStart: Duration(milliseconds: 1200),
                    offset: 2,
                    child: new Text('Test Text 1')),
                SlideFadeTransition(
                    delayStart: Duration(milliseconds: 2400),
                    offset: 4,
                    child: new Text('Test Text 2'))
              ],
            ),
          ),
          Container(
            color: Colors.orange,
            height: 1000,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                SlideFadeTransition(
                    delayStart: Duration(milliseconds: 1200),
                    offset: 2,
                    child: new Text('Test Text 1')),
                SlideFadeTransition(
                    delayStart: Duration(milliseconds: 2400),
                    offset: 4,
                    child: new Text('Test Text 2'))
              ],
            ),
          ),
          RaisedButton(
            child: Text('Open route'),
            onPressed: () {
              firstRun = false;
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => SecondRoute()),
              );
            },
          ),
        ])));
      }
    }
    
    enum Direction { vertical, horizontal }
    
    class SlideFadeTransition extends StatefulWidget {
      ///The child on which to apply the given [SlideFadeTransition]
      final Widget child;
    
      ///The offset by which to slide and [child] into view from [Direction].
      ///Defaults to 0.2
      final double offset;
    
      ///The curve used to animate the [child] into view.
      ///Defaults to [Curves.easeIn]
      final Curve curve;
    
      ///The direction from which to animate the [child] into view. [Direction.horizontal]
      ///will make the child slide on x-axis by [offset] and [Direction.vertical] on y-axis.
      ///Defaults to [Direction.vertical]
      final Direction direction;
    
      ///The delay with which to animate the [child]. Takes in a [Duration] and
      /// defaults to 0.0 seconds
      final Duration delayStart;
    
      ///The total duration in which the animation completes. Defaults to 800 milliseconds
      final Duration animationDuration;
    
      SlideFadeTransition({
        @required this.child,
        this.offset = 0.2,
        this.curve = Curves.easeIn,
        this.direction = Direction.vertical,
        this.delayStart = const Duration(seconds: 0),
        this.animationDuration = const Duration(milliseconds: 800),
      });
      @override
      _SlideFadeTransitionState createState() => _SlideFadeTransitionState();
    }
    
    class _SlideFadeTransitionState extends State<SlideFadeTransition>
        with SingleTickerProviderStateMixin {
      Animation<Offset> _animationSlide;
    
      AnimationController _animationController;
    
      Animation<double> _animationFade;
    
      @override
      void initState() {
        super.initState();
        _animationController = AnimationController(
          vsync: this,
          duration: widget.animationDuration,
        );
    
        //configure the animation controller as per the direction
        if (widget.direction == Direction.vertical) {
          _animationSlide =
              Tween<Offset>(begin: Offset(0, widget.offset), end: Offset(0, 0))
                  .animate(CurvedAnimation(
            curve: widget.curve,
            parent: _animationController,
          ));
        } else {
          _animationSlide =
              Tween<Offset>(begin: Offset(widget.offset, 0), end: Offset(0, 0))
                  .animate(CurvedAnimation(
            curve: widget.curve,
            parent: _animationController,
          ));
        }
    
        _animationFade =
            Tween<double>(begin: -1.0, end: 1.0).animate(CurvedAnimation(
          curve: widget.curve,
          parent: _animationController,
        ));
    
        Timer(widget.delayStart, () {
          _animationController.forward();
        });
      }
    
      @override
      Widget build(BuildContext context) {
        print('first run ${firstRun}');
        return firstRun? FadeTransition(
          opacity: _animationFade,
          child: SlideTransition(
            position: _animationSlide,
            child: widget.child,
          ),
        ) : widget.child;
      }
    }
    
    class SecondRoute extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("Second Route"),
          ),
          body: Center(
            child: RaisedButton(
              onPressed: () {
                // Navigate back to first route when tapped.
              },
              child: Text('Go back!'),
            ),
          ),
        );
      }
    }
    

    【讨论】:

    • 我做了一些安排,因为我将动画设置保存在不同的 dart 文件中,但它可以按我的意愿工作,非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 2013-08-22
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    • 2011-06-12
    相关资源
    最近更新 更多