2017-09-28 1 views
1

Ich fange an zu flattern und versuche eine Animation zu machen, die sich beim Ein- und Ausblenden ständig dreht. Bisher funktioniert die Rotation, aber ich habe Schwierigkeiten mit dem verblassenden Effekt. Das Widget wird nach und nach transparent, aber nach einer Drehung springt es wieder in Opak, bevor es wieder transparent wird. Ich versuche das zu beheben, aber ich kann nicht herausfinden, wie. Die Verwendung von .forward() und .reverse() funktioniert nicht, aber es ist möglich, dass ich die undurchsichtige Animation falsch implementiert habe.Flatter-Animation, wie langsam Ein-/Ausblenden

class AnimatedLoader extends AnimatedWidget { 
    static final _opacityTween = new Tween<double>(begin: 1.0, end: 0.3); 

    AnimatedLoader({ 
    Key key, 
    this.alignment: FractionalOffset.center, 
    Animation<double> turns, 
    Animation<double> animation, 
    this.child, 
    }) : super(key: key, listenable: turns); 

    Animation<double> get turns => listenable; 

    final FractionalOffset alignment; 
    final Widget child; 

    @override 
    Widget build(BuildContext context) { 
    final Animation<double> animation = listenable; 
    final double turnsValue = turns.value; 
    final Matrix4 transform = new Matrix4.rotationZ(turnsValue * math.PI * 2.0); 
    return new Transform(
     alignment: alignment, 
     transform: transform, 
     child: new Opacity(
     opacity: _opacityTween.evaluate(animation), 
     child: child, 
    ) 
    ); 
    } 
} 

class AppLoader extends StatefulWidget { 
    AppLoaderState createState() => new AppLoaderState(); 
} 

class AppLoaderState extends State<AppLoader> with TickerProviderStateMixin { 
    AnimationController _controller; 
    AnimationController _controllerOp; 
    Animation<double> animation; 

    @override initState(){ 
    super.initState(); 
    _controller = new AnimationController(
     duration: const Duration(milliseconds: 1500), 
     vsync: this, 
    )..repeat(); 

    _controllerOp = new AnimationController(
     duration: const Duration(milliseconds: 800), 
     vsync: this, 
    ); 
    animation = new Tween(begin: 0.0, end: 300.0).animate(_controllerOp); 

    animation.addStatusListener((status) { 
     if (status == AnimationStatus.completed) { 
     _controllerOp.reverse(); 
     } else if (status == AnimationStatus.dismissed) { 
     _controllerOp.forward(); 
     } 
    }); 
    _controllerOp.forward(); 
    } 

    @override 
    Widget build(BuildContext context) { 
    return new Center (
     child: new AnimatedLoader(
     turns: _controller, 
     alignment: FractionalOffset.center, 
     animation: _controllerOp, 
     child: new Container(
      margin: new EdgeInsets.symmetric(vertical: 10.0), 
      height: 150.0, 
      width: 150.0, 
      child: new FlutterLogo(), 
     ) 
    ), 
    ); 
    } 

Sorry für das große Stück Code, ich bin nicht sicher, welchen Teil ich in einen Fehler gemacht haben könnte.

+0

Können Sie versuchen AnimatedOpacity anstelle von Opazität? Nur ein Gedanke :) –

Antwort

0

Ich glaube, Sie auf dem richtigen Weg sind, aber Sie sollten nur eine verwenden AnimationController pro AnimatedWidget. Ich habe einige Fehler in deinem Code behoben.

video of pulsing flutter logo

import 'package:flutter/material.dart'; 
import 'dart:math' as math; 

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

class MyApp extends StatelessWidget { 
    @override 
    Widget build(BuildContext context) { 
    return new MaterialApp(
     home: new MyHomePage(), 
    ); 
    } 
} 

class MyHomePage extends StatelessWidget { 
    Widget build(BuildContext context) { 
    return new Scaffold(
     body: new AppLoader(), 
    ); 
    } 
} 

class PulsateCurve extends Curve { 
    @override 
    double transform(double t) { 
    if (t == 0 || t == 1) 
     return 0.3; 
    return math.sin(t * math.PI) * 0.35 + 0.65; 
    } 
} 

class AnimatedLoader extends AnimatedWidget { 
    static final _opacityTween = new CurveTween(curve: new PulsateCurve()); 

    AnimatedLoader({ 
    Key key, 
    this.alignment: FractionalOffset.center, 
    Animation<double> animation, 
    this.child, 
    }) : super(key: key, listenable: animation); 

    final FractionalOffset alignment; 
    final Widget child; 

    @override 
    Widget build(BuildContext context) { 
    final Animation<double> animation = listenable; 
    final Matrix4 transform = new Matrix4.rotationZ(animation.value * math.PI * 2.0); 
    return new Transform(
     alignment: alignment, 
     transform: transform, 
     child: new Opacity(
      opacity: _opacityTween.evaluate(animation), 
      child: child, 
     ) 
    ); 
    } 
} 

class AppLoader extends StatefulWidget { 
    AppLoaderState createState() => new AppLoaderState(); 
} 

class AppLoaderState extends State<AppLoader> with TickerProviderStateMixin { 
    AnimationController _controller; 

    @override initState() { 
    super.initState(); 
    _controller = new AnimationController(
     duration: const Duration(milliseconds: 1500), 
     vsync: this, 
    )..repeat(); 
    } 

    @override 
    Widget build(BuildContext context) { 
    return new Center (
     child: new AnimatedLoader(
      animation: _controller, 
      alignment: FractionalOffset.center, 
      child: new Container(
      margin: new EdgeInsets.symmetric(vertical: 10.0), 
      height: 150.0, 
      width: 150.0, 
      child: new FlutterLogo(), 
     ) 
    ), 
    ); 
    } 
}