【问题标题】:Ripple animation flutter波纹动画颤动
【发布时间】:2019-08-31 20:56:10
【问题描述】:

我想使用颤振创建波纹动画。我已经知道涟漪效应,但这不是我想要的,我想要link

【问题讨论】:

    标签: flutter dart flutter-layout flutter-animation


    【解决方案1】:

    输出

      AnimationController _controller;
    
      @override
      void initState() {
        super.initState();
        _controller = AnimationController(
          vsync: this,
          lowerBound: 0.5,
          duration: Duration(seconds: 3),
        )..repeat();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text("Title")),
          body: _buildBody(),
        );
      }
    
      Widget _buildBody() {
        return AnimatedBuilder(
          animation: CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn),
          builder: (context, child) {
            return Stack(
              alignment: Alignment.center,
              children: <Widget>[
                _buildContainer(150 * _controller.value),
                _buildContainer(200 * _controller.value),
                _buildContainer(250 * _controller.value),
                _buildContainer(300 * _controller.value),
                _buildContainer(350 * _controller.value),
                Align(child: Icon(Icons.phone_android, size: 44,)),
              ],
            );
          },
        );
      }
    
      Widget _buildContainer(double radius) {
        return Container(
          width: radius,
          height: radius,
          decoration: BoxDecoration(
            shape: BoxShape.circle,
            color: Colors.blue.withOpacity(1 - _controller.value),
          ),
        );
      }
    

    【讨论】:

    • 我需要更多帮助,我想将它与整个布局的底部中心对齐。我正在尝试但没有得到它
    • AnimatedBuilder 包裹在Align 中并将alignment 更改为Alignment.bottomCenter
    • 我做到了列小部件
    • 这是一个非常好的答案。非常感谢!
    • with TickerProviderStateMixin 将此 mixin 添加到您的状态类中,如果您在 vsync 上遇到错误
    【解决方案2】:

    这是另一个使用CustomPaint的版本

    import 'dart:math' as math show sin, pi, sqrt;
    
    import 'package:flutter/animation.dart';
    import 'package:flutter/material.dart';
    
    class Ripples extends StatefulWidget {
      const Ripples({
        Key key,
        this.size = 80.0,
        this.color = Colors.pink,
        this.onPressed,
        @required this.child,
      }) : super(key: key);
    
      final double size;
      final Color color;
      final Widget child;
      final VoidCallback onPressed;
    
      @override
      _RipplesState createState() => _RipplesState();
    }
    
    class _CirclePainter extends CustomPainter {
      _CirclePainter(
        this._animation, {
        @required this.color,
      }) : super(repaint: _animation);
    
      final Color color;
      final Animation<double> _animation;
    
      void circle(Canvas canvas, Rect rect, double value) {
        final double opacity = (1.0 - (value / 4.0)).clamp(0.0, 1.0);
        final Color _color = color.withOpacity(opacity);
    
        final double size = rect.width / 2;
        final double area = size * size;
        final double radius = math.sqrt(area * value / 4);
    
        final Paint paint = Paint()..color = _color;
        canvas.drawCircle(rect.center, radius, paint);
      }
    
      @override
      void paint(Canvas canvas, Size size) {
        final Rect rect = Rect.fromLTRB(0.0, 0.0, size.width, size.height);
    
        for (int wave = 3; wave >= 0; wave--) {
          circle(canvas, rect, wave + _animation.value);
        }
      }
    
      @override
      bool shouldRepaint(_CirclePainter oldDelegate) => true;
    }
    
    class _RipplesState extends State<Ripples> with TickerProviderStateMixin {
      AnimationController _controller;
    
      @override
      void initState() {
        super.initState();
        _controller = AnimationController(
          duration: const Duration(milliseconds: 2000),
          vsync: this,
        )..repeat();
      }
    
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    
      Widget _button() {
        return Center(
          child: ClipRRect(
            borderRadius: BorderRadius.circular(widget.size),
            child: DecoratedBox(
              decoration: BoxDecoration(
                gradient: RadialGradient(
                  colors: <Color>[
                    widget.color,
                    Color.lerp(widget.color, Colors.black, .05)
                  ],
                ),
              ),
              child: ScaleTransition(
                scale: Tween(begin: 0.95, end: 1.0).animate(
                  CurvedAnimation(
                    parent: _controller,
                    curve: const _PulsateCurve(),
                  ),
                ),
                child: widget.child,
              ),
            ),
          ),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return CustomPaint(
          painter: _CirclePainter(
            _controller,
            color: widget.color,
          ),
          child: SizedBox(
            width: widget.size * 2.125,
            height: widget.size * 2.125,
            child: _button(),
          ),
        );
      }
    }
    
    class _PulsateCurve extends Curve {
      const _PulsateCurve();
    
      @override
      double transform(double t) {
        if (t == 0 || t == 1) {
          return 0.01;
        }
        return math.sin(t * math.pi);
      }
    }
    

    【讨论】:

    • 老天...这么多样板对于一个简单的事情!
    • 它并不像你想象的那么简单。这只是使用画家的替代实现。
    • 信不信由你,这比公认的解决方案性能更高。 CustomPainter 是冗长的,但是是高性能的 AF,甚至这个块也比你应该只为此安装一个库的 java 解决方案更好
    【解决方案3】:

    你也可以使用这个源代码flutter_ripple_animation_demo来实现这个

    只需将这些文件添加到您的项目中并像下面这样使用它们

    例子在这里

    import 'package:flutter/material.dart';
    import 'package:flutter/animation.dart';
    import 'package:rippledemo/circle_painter.dart';
    import 'package:rippledemo/curve_wave.dart';
    
    
    class RipplesAnimation extends StatefulWidget {
      const RipplesAnimation({Key key, this.size = 80.0, this.color = Colors.red,
        this.onPressed, @required this.child,}) : super(key: key);
      final double size;
      final Color color;
      final Widget child;
      final VoidCallback onPressed;
      @override
      _RipplesAnimationState createState() => _RipplesAnimationState();
    }
    
    class _RipplesAnimationState extends State<RipplesAnimation> with TickerProviderStateMixin {
      AnimationController _controller;
      @override
      void initState() {
        super.initState();
        _controller = AnimationController(
          duration: const Duration(milliseconds: 2000),
          vsync: this,
        )..repeat();
      }
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
      Widget _button() {
        return Center(
          child: ClipRRect(
            borderRadius: BorderRadius.circular(widget.size),
            child: DecoratedBox(
              decoration: BoxDecoration(
                gradient: RadialGradient(
                  colors: <Color>[
                    widget.color,
                    Color.lerp(widget.color, Colors.black, .05)
                  ],
                ),
              ),
              child: ScaleTransition(
                  scale: Tween(begin: 0.95, end: 1.0).animate(
                    CurvedAnimation(
                      parent: _controller,
                      curve: const CurveWave(),
                    ),
                  ),
                  child: Icon(Icons.speaker_phone, size: 44,)
              ),
            ),
          ),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("Flutter Ripple Demo"),
          ),
          body: Center(
            child: CustomPaint(
              painter: CirclePainter(
                _controller,
                color: widget.color,
              ),
              child: SizedBox(
                width: widget.size * 4.125,
                height: widget.size * 4.125,
                child: _button(),
              ),
            ),
          ),
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-01-17
      • 2023-03-30
      • 1970-01-01
      • 2020-09-26
      • 2019-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多