Flutter 中数字的滚动动画

先上个图:

number_sroll.gif
//随机颜色
Color get _randomColor => Color.fromRGBO(
      Random().nextInt(256),
      Random().nextInt(256),
      Random().nextInt(256),
      1,
    );

class AnimatedNumberPage extends StatefulWidget {
  const AnimatedNumberPage({
    Key? key,
  }) : super(key: key);

  @override
  _AnimatedNumberPageState createState() => _AnimatedNumberPageState();
}
class _AnimatedNumberPageState extends State {
  Timer? _timer;
  late final ValueNotifier _notifier = ValueNotifier(0);

  void _startTimer() {
    if (_timer != null && _timer!.isActive) {
      _stopTimer();
    }
    _timer = Timer.periodic(const Duration(milliseconds: 1000), (timer) {
      _notifier.value++;
    });
  }

  void _stopTimer() {
    if (_timer != null) {
      _timer!.cancel();
    }
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0.5,
        title: const Text(
          'AnimatedSwitcher 动画',
          style: TextStyle(
            color: Colors.white,
          ),
        ),
      ),
      body: Column(
        children: [
          Container(
            width: MediaQuery.of(context).size.width,
            height: 180,
            alignment: Alignment.center,
            child: _buildAnimatedSwitcher(context), 
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: [
              TextButton(
                style: ButtonStyle(
                    backgroundColor:
                        MaterialStateProperty.all(Colors.blueAccent)),
                child: const Text(
                  '开始',
                  style: TextStyle(
                    color: Colors.white,
                  ),
                ),
                onPressed: () => _startTimer(),
              ),
              TextButton(
                style: ButtonStyle(
                    backgroundColor:
                        MaterialStateProperty.all(Colors.blueAccent)),
                child: const Text(
                  '停止',
                  style: TextStyle(
                    color: Colors.white,
                  ),
                ),
                onPressed: () => _stopTimer(),
              ),
            ],
          ),
        ],
      ),
    );
  }
}
Widget _buildAnimatedSwitcher(BuildContext context) {
    return ValueListenableBuilder(
      valueListenable: _notifier,
      builder: (BuildContext context, int value, Widget? child) {
        return AnimatedSwitcher(
          duration: const Duration(milliseconds: 500),
          transitionBuilder: (child, animation) {
            // 构建切换使用组合动画
            return _buildMultAnimation(animation, child);
          },
          child: Text(
            '$value',
            key: ValueKey(value), //⚠️重要: 必须设置。显示指定key,不同的key会被认为是不同的Text
            style: TextStyle(
              color: _randomColor,
              fontSize: 30,
              fontWeight: FontWeight.w400,
            ),
          ),
        );
      },
    );
  }

  Widget _buildMultAnimation(
    Animation animation,
    Widget child,
  ) {
    Offset beginOfsset = const Offset(0, -1.2);
    Offset endOffset = Offset.zero;

    if (animation.status == AnimationStatus.completed) {
      // Text移出的平移动画
      beginOfsset = const Offset(0.0, 1.2);
      endOffset = Offset.zero;
    }

    return SlideTransition(
      // 平移动画
      position: Tween(begin: beginOfsset, end: endOffset).animate(
        CurvedAnimation(
          parent: animation,
          curve: Curves.linear,
        ),
      ),
      child: FadeTransition(
        // 渐变动画
        opacity: Tween(begin: 0.0, end: 1.0).animate(
          CurvedAnimation(
            parent: animation,
            curve: Curves.linear,
          ),
        ),
        child: ScaleTransition(
          // 缩放动画
          scale: Tween(begin: 0.6, end: 1.0).animate(
            CurvedAnimation(
              parent: animation,
              curve: Curves.linear,
            ),
          ),
          child: child,
        ),
      ),
    );
  }

你可能感兴趣的:(Flutter 中数字的滚动动画)