Измените значение анимации и перезапустите ее - PullRequest
0 голосов
/ 07 мая 2020

Я создал анимацию счетчика, которая увеличивается на x секунд. Когда пользователь достигает виджета, анимация запускается правильно через initState. Я также создал текстовое поле begin и end, чтобы пользователь мог обновить начальное и конечное значение и перезапустить анимацию. Проблема, когда пользователь нажал кнопку для перезапуска анимации, она не работает.

PS: Вы можете протестировать код, если хотите, скопировав весь код в новый проект в main.dart

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: ShowCounter(),
    );
  }
}

//
// The animation
//

class AnimatedCounter extends StatefulWidget {
  // Variables
  int startValue;
  int endValue;
  Duration timeAnim;
  Color color;
  double factor;

  // Constructor
  AnimatedCounter({
    int startValue,
    int endValue,
    Duration timeAnim: const Duration(seconds: 3),
    color: Colors.black,
    factor: 5.4,
  }) {
    this.startValue = startValue;
    this.endValue = endValue;
    this.timeAnim = timeAnim;
    this.color = color;
    this.factor = factor;
  }

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

class _AnimatedCounterState extends State<AnimatedCounter>
    with SingleTickerProviderStateMixin {
  Animation<double> animCounter;
  AnimationController _controller;
  String i;

  @override
  void initState() {
    super.initState();

    // AnimationController
    _controller = AnimationController(duration: widget.timeAnim, vsync: this);

    // Animation
    animCounter = Tween<double>(
            begin: widget.startValue.toDouble(),
            end: widget.endValue.toDouble())
        .animate(CurvedAnimation(
      parent: _controller,
      curve: Curves.easeOutCirc,
    ))
          ..addListener(() {
            setState(() {
              i = animCounter.value.toStringAsFixed(0);
            });
          });
    _controller.forward().orCancel;
  }

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

  // Layout
  @override
  Widget build(BuildContext context) {
    return Text(
      '$i',
      textScaleFactor: widget.factor,
      style: TextStyle(color: widget.color),
    );
  }
}

//
// Display and layout
//

class ShowCounter extends StatefulWidget {
  @override
  _ShowCounterState createState() => _ShowCounterState();
}

class _ShowCounterState extends State<ShowCounter> {
  // Variable
  AnimatedCounter counter;
  int startvalue;
  int endValue;

  @override
  void initState() {
    super.initState();
    startvalue = 0;
    endValue = 42;
    counter = AnimatedCounter(startValue: startvalue, endValue: endValue);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Counter animated"),
      ),
      body: Scaffold(
        backgroundColor: Colors.blue[100],
        body: Center(
          child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                counter,
                Card(
                    margin: EdgeInsets.only(left: 20.0, right: 20.0),
                    child: Container(
                      padding: EdgeInsets.all(10),
                      child: Column(children: <Widget>[
                        TextField(
                          keyboardType: TextInputType.number,
                          decoration:
                              InputDecoration(labelText: "Starting value"),
                          onChanged: (String string) {
                            setState(() {
                              startvalue = int.tryParse(string);
                            });
                          },
                        ),
                        TextField(
                          keyboardType: TextInputType.number,
                          decoration: InputDecoration(labelText: "End value"),
                          onChanged: (String string) {
                            setState(() {
                              endValue = int.tryParse(string);
                            });
                          },
                        ),
                        Container(
                          height: 10,
                        ),
                        SizedBox(
                          width: double.infinity,
                          child: RaisedButton(
                            child: Text("Run"),
                            onPressed: () {
                              setState(() {
                                // Desperate attempt to restart animation with new start/end value (not working)
                                counter = AnimatedCounter(
                                    startValue: startvalue, endValue: endValue);
                              });
                            },
                          ),
                        ),
                      ]),
                    ))
              ]),
        ),
      ),
    );
  }
}

1 Ответ

0 голосов
/ 07 мая 2020

Вы должны создать глобальный ключ состояния, чтобы вы могли получить доступ к методу состояния из родительского виджета.

Вы должны передать глобальный ключ этому виджету, а затем создать метод из содержимого initstate и вызвать этот метод из родительского виджета.

следующий полный код поможет вам больше.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: ShowCounter(),
    );
  }
}

//
// The animation
//

class AnimatedCounter extends StatefulWidget {
  // Variables
  int startValue;
  int endValue;
  Duration timeAnim;
  Color color;
  double factor;

  AnimatedCounter(
      {int startValue,
      int endValue,
      Duration timeAnim: const Duration(seconds: 3),
      color: Colors.black,
      factor: 5.4,
      Key key})
      : super(key: key) {
    this.startValue = startValue;
    this.endValue = endValue;
    this.timeAnim = timeAnim;
    this.color = color;
    this.factor = factor;
  }

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

class AnimatedCounterState extends State<AnimatedCounter>
    with TickerProviderStateMixin {
  Animation<double> animCounter;
  AnimationController _controller;
  String i;

  @override
  void initState() {
    print("object");
    super.initState();
    // AnimationController
    startanimation();
  }

  startanimation() {
    _controller = AnimationController(duration: widget.timeAnim, vsync: this);

    // Animation
    animCounter = Tween<double>(
            begin: widget.startValue.toDouble(),
            end: widget.endValue.toDouble())
        .animate(CurvedAnimation(
      parent: _controller,
      curve: Curves.easeOutCirc,
    ))
          ..addListener(() {
            setState(() {
              i = animCounter.value.toStringAsFixed(0);
            });
          });
    _controller.forward();
  }

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

  // Layout
  @override
  Widget build(BuildContext context) {
    return Text(
      '$i',
      textScaleFactor: widget.factor,
      style: TextStyle(color: widget.color),
    );
  }
}

//
// Display and layout
//

class ShowCounter extends StatefulWidget {
  @override
  _ShowCounterState createState() => _ShowCounterState();
}

class _ShowCounterState extends State<ShowCounter> {
  // Variable
  AnimatedCounter counter;
  int startvalue;
  int endValue;
  GlobalKey<AnimatedCounterState> state = GlobalKey<AnimatedCounterState>();
  @override
  void initState() {
    super.initState();
    startvalue = 0;
    endValue = 42;
    counter = AnimatedCounter(
      startValue: startvalue,
      endValue: endValue,
      key: state,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Counter animated"),
      ),
      body: Scaffold(
        backgroundColor: Colors.blue[100],
        body: Center(
          child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                counter,
                Card(
                    margin: EdgeInsets.only(left: 20.0, right: 20.0),
                    child: Container(
                      padding: EdgeInsets.all(10),
                      child: Column(children: <Widget>[
                        TextField(
                          keyboardType: TextInputType.number,
                          decoration:
                              InputDecoration(labelText: "Starting value"),
                          onChanged: (String string) {
                            setState(() {
                              startvalue = int.tryParse(string);
                            });
                          },
                        ),
                        TextField(
                          keyboardType: TextInputType.number,
                          decoration: InputDecoration(labelText: "End value"),
                          onChanged: (String string) {
                            setState(() {
                              endValue = int.tryParse(string);
                            });
                          },
                        ),
                        Container(
                          height: 10,
                        ),
                        SizedBox(
                          width: double.infinity,
                          child: RaisedButton(
                            child: Text("Run"),
                            onPressed: () {
                              setState(() {
                                counter = AnimatedCounter(
                                  startValue: startvalue,
                                  endValue: endValue,
                                  key: state,
                                );
                                state.currentState.startanimation();
                              });
                            },
                          ),
                        ),
                      ]),
                    ))
              ]),
        ),
      ),
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...