How do I create an animated number counter?

dart, flutter

Solution

You should use an `AnimationController` with an `AnimatedBuilder` to rebuild your text when the controller changes. Here's an example that increments the miles when the floating action button is pressed (`double.toStringAsFixed` to get the decimal to show), with a curve on the animation speed:

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

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

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

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);
  @override
  createState() => new MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  AnimationController _controller;
  Animation<double> _animation;
  double _miles = 0.0;

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

  @override
  Widget build(BuildContext context) {
    TextTheme textTheme = Theme.of(context).textTheme;
    return new Scaffold(
      body: new Material(
        color: const Color.fromRGBO(246, 251, 8, 1.0),
        child: new Center(
          child: new Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              new AnimatedBuilder(
                animation: _animation,
                builder: (BuildContext context, Widget child) {
                  return new Text(
                    _animation.value.toStringAsFixed(1),
                    style: textTheme.display4.copyWith(fontStyle: FontStyle.italic),
                  );
                },
              ),
              new Text(
                  "MILES",
                  style: textTheme.display1.copyWith(fontStyle: FontStyle.italic),
              )
            ],
          ),
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        child: new Icon(Icons.directions_run),
        onPressed: () {
          Random rng = new Random();
          setState(() {
            _miles += rng.nextInt(20) + 0.3;
            _animation = new Tween<double>(
                begin: _animation.value,
                end: _miles,
            ).animate(new CurvedAnimation(
              curve: Curves.fastOutSlowIn,
              parent: _controller,
            ));
          });
          _controller.forward(from: 0.0);
        }
      ),
    );
  }

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

Problem

I'd like to create a number counter that animates from a starting value to an end value. I've looked into using a Timer but can't seem to animate/update state properly. Including the decimal value would be great, but a simple integer animation is fine. Number counter that needs to animate ``` double _mileCounter = 643.6; _animateMileCounter() { Duration duration = new Duration(milliseconds: 300); return new Timer(duration, _updateMileCounter); } _updateMileCounter() { setState(() { _mileCounter += 1; }); } ``` How would I increment the counter X number of times (with animation)? Similar to how a car's odometer increments.

Original source