如何使颤动中的滚动计数器 [英] How to make scrolling counter in flutter

查看:68
本文介绍了如何使颤动中的滚动计数器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个滚动计数器,我想知道如何在flutter中实现它.

解决方案

我想在项目中执行此操作,因此我创建了一个称为 AnimatedFlipCounter 的隐式动画小部件,该控件实现了类似的效果./p>

用法:

  AnimatedFlipCounter(持续时间:持续时间(毫秒:500),值:_value,/*传递数字,例如2014 */颜色:黑色.大小:100,) 

源代码(无null安全):

只需将以下内容复制并粘贴到文件中,然后像上面的示例一样使用 AnimatedFlipCounter .

  import'package:flutter/cupertino.dart';导入'package:flutter/material.dart';类AnimatedFlipCounter扩展了StatelessWidget {最终的int值;最终持续时间;最终双倍大小;最终颜色const AnimatedFlipCounter({关键@需要this.value,@需要this.duration,this.size = 72,this.color = Colors.black,}):super(key:key);@override窗口小部件build(BuildContext context){List< int>位=值== 0?[0]:[];int v =值;如果(v< 0){v * = -1;}而(v> 0){digits.add(v);v = v〜/10;}返回行(mainAxisSize:MainAxisSize.min,子代:List.generate(digits.length,(int i){返回_SingleDigitFlipCounter(键:ValueKey(digits.length-i),值:digits [digits.length-i-1] .toDouble(),持续时间:持续时间,高度:大小,宽度:尺寸/1.8,颜色:);}),);}}_SingleDigitFlipCounter类扩展了StatelessWidget {最终的双精度值;最终持续时间;最终双倍高度;最终双倍宽度;最终颜色const _SingleDigitFlipCounter({关键@需要this.value,@需要this.duration,@需要this.height,@需要this.width,@需要this.color,}):super(key:key);@override窗口小部件build(BuildContext context){返回TweenAnimationBuilder(补间:补间(开始:值,结束:值),持续时间:持续时间,生成器:(上下文,值,子项){最终整数=值〜/1;最后的小数=值-整数;返回SizedBox(高度:高度宽度:宽度,子代:Stack(适合:StackFit.expand,子代:< Widget> [_buildSingleDigit(数字:整数%10,偏移量:高度*小数,不透明度:1-十进制,),_buildSingleDigit(位数:(整体+ 1)%10,偏移量:高度*小数-高度,不透明度:十进制,),],),);},);}小部件_buildSingleDigit({int digit,double offset,double opacity}){返回定位(子代:SizedBox(宽度:宽度,子:不透明度(不透明度:不透明度,子代:文字("$ digit",样式:TextStyle(字体大小:高度,颜色:颜色),textAlign:TextAlign.center,),),),下:偏移量,);}} 

具有空安全性的源代码::

在Flutter 2.0发行版中,您可能想使用null安全版本.

  import'package:flutter/material.dart';类AnimatedFlipCounter扩展StatelessWidget {最终的int值;最终持续时间;最终双倍大小;最终颜色textColor;const AnimatedFlipCounter({钥匙?钥匙,需要this.value,需要这个持续时间,this.size = 100,this.textColor = Colors.black,}):super(key:key);@override窗口小部件build(BuildContext context){List< int>位=值== 0?[0]:[];int v =值;如果(v< 0){v * = -1;}而(v> 0){digits.add(v);v = v〜/10;}返回行(mainAxisSize:MainAxisSize.min,子代:List.generate(digits.length,(int i){返回_SingleDigitFlipCounter(键:ValueKey(digits.length-i),值:digits [digits.length-i-1] .toDouble(),持续时间:持续时间,高度:大小,宽度:尺寸/1.8,颜色:textColor,);}),);}}_SingleDigitFlipCounter类扩展了StatelessWidget {最终的双精度值;最终持续时间;最终双倍高度;最终双倍宽度;最终颜色const _SingleDigitFlipCounter({钥匙?钥匙,需要this.value,需要这个持续时间,需要这个高度.需要this.width,需要this.color,}):super(key:key);@override窗口小部件build(BuildContext context){返回TweenAnimationBuilder(补间:补间(开始:值,结束:值),持续时间:持续时间,生成器:(上下文,双精度值,子代){最终整数=值〜/1;最后的小数=值-整数;返回SizedBox(高度:高度宽度:宽度,子代:Stack(子代:< Widget> [_buildSingleDigit(数字:整数%10,偏移量:高度*小数,不透明度:1-十进制,),_buildSingleDigit(位数:(整体+ 1)%10,偏移量:高度*小数-高度,不透明度:十进制,),],),);},);}小部件_buildSingleDigit({所需的整数位,需要双偏移量需要双重不透明性}){返回定位(下:偏移量,子代:文字("$ digit",样式:TextStyle(fontSize:高度,颜色:color.withOpacity(opacity),),),);}} 

I would like to create a scrolling counter and I'm wondering on how to implement this in flutter.

解决方案

I wanted to do this in a project, so I create an implicit animation widget, called AnimatedFlipCounter, that achieves similar effect.

Usage:

AnimatedFlipCounter(
   duration: Duration(milliseconds: 500),
   value: _value, /* pass in a number like 2014 */
   color: Colors.black,
   size: 100,
)

Source code (without null-safety):

Just copy and paste the following into a file, and use the AnimatedFlipCounter like above example.

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

class AnimatedFlipCounter extends StatelessWidget {
  final int value;
  final Duration duration;
  final double size;
  final Color color;

  const AnimatedFlipCounter({
    Key key,
    @required this.value,
    @required this.duration,
    this.size = 72,
    this.color = Colors.black,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    List<int> digits = value == 0 ? [0] : [];

    int v = value;
    if (v < 0) {
      v *= -1;
    }
    while (v > 0) {
      digits.add(v);
      v = v ~/ 10;
    }

    return Row(
      mainAxisSize: MainAxisSize.min,
      children: List.generate(digits.length, (int i) {
        return _SingleDigitFlipCounter(
          key: ValueKey(digits.length - i),
          value: digits[digits.length - i - 1].toDouble(),
          duration: duration,
          height: size,
          width: size / 1.8,
          color: color,
        );
      }),
    );
  }
}

class _SingleDigitFlipCounter extends StatelessWidget {
  final double value;
  final Duration duration;
  final double height;
  final double width;
  final Color color;

  const _SingleDigitFlipCounter({
    Key key,
    @required this.value,
    @required this.duration,
    @required this.height,
    @required this.width,
    @required this.color,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TweenAnimationBuilder(
      tween: Tween(begin: value, end: value),
      duration: duration,
      builder: (context, value, child) {
        final whole = value ~/ 1;
        final decimal = value - whole;
        return SizedBox(
          height: height,
          width: width,
          child: Stack(
            fit: StackFit.expand,
            children: <Widget>[
              _buildSingleDigit(
                digit: whole % 10,
                offset: height * decimal,
                opacity: 1 - decimal,
              ),
              _buildSingleDigit(
                digit: (whole + 1) % 10,
                offset: height * decimal - height,
                opacity: decimal,
              ),
            ],
          ),
        );
      },
    );
  }

  Widget _buildSingleDigit({int digit, double offset, double opacity}) {
    return Positioned(
      child: SizedBox(
        width: width,
        child: Opacity(
          opacity: opacity,
          child: Text(
            "$digit",
            style: TextStyle(fontSize: height, color: color),
            textAlign: TextAlign.center,
          ),
        ),
      ),
      bottom: offset,
    );
  }
}

Source code with null-safety::

With the release of Flutter 2.0, you might want to use the null-safety version instead.

import 'package:flutter/material.dart';

class AnimatedFlipCounter extends StatelessWidget {
  final int value;
  final Duration duration;
  final double size;
  final Color textColor;

  const AnimatedFlipCounter({
    Key? key,
    required this.value,
    required this.duration,
    this.size = 100,
    this.textColor = Colors.black,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    List<int> digits = value == 0 ? [0] : [];

    int v = value;
    if (v < 0) {
      v *= -1;
    }
    while (v > 0) {
      digits.add(v);
      v = v ~/ 10;
    }

    return Row(
      mainAxisSize: MainAxisSize.min,
      children: List.generate(digits.length, (int i) {
        return _SingleDigitFlipCounter(
          key: ValueKey(digits.length - i),
          value: digits[digits.length - i - 1].toDouble(),
          duration: duration,
          height: size,
          width: size / 1.8,
          color: textColor,
        );
      }),
    );
  }
}

class _SingleDigitFlipCounter extends StatelessWidget {
  final double value;
  final Duration duration;
  final double height;
  final double width;
  final Color color;

  const _SingleDigitFlipCounter({
    Key? key,
    required this.value,
    required this.duration,
    required this.height,
    required this.width,
    required this.color,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TweenAnimationBuilder(
      tween: Tween(begin: value, end: value),
      duration: duration,
      builder: (context, double value, child) {
        final whole = value ~/ 1;
        final decimal = value - whole;
        return SizedBox(
          height: height,
          width: width,
          child: Stack(
            children: <Widget>[
              _buildSingleDigit(
                digit: whole % 10,
                offset: height * decimal,
                opacity: 1 - decimal,
              ),
              _buildSingleDigit(
                digit: (whole + 1) % 10,
                offset: height * decimal - height,
                opacity: decimal,
              ),
            ],
          ),
        );
      },
    );
  }

  Widget _buildSingleDigit({
    required int digit,
    required double offset,
    required double opacity,
  }) {
    return Positioned(
      bottom: offset,
      child: Text(
        "$digit",
        style: TextStyle(
          fontSize: height,
          color: color.withOpacity(opacity),
        ),
      ),
    );
  }
}

这篇关于如何使颤动中的滚动计数器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆