Flutter水波纹边框

3g54o-00xsw (1).gif

使用AnimationController控制两种动画效果,分别是缩放动画ScaleTransition和淡出动画FadeTransition,多圈波纹需要多个AnimationController,把所有controller放在数组里退出时一并销毁,
波纹widget以Stack结构层层叠加

完整代码:

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

class WaveBorder extends StatefulWidget {
  final Widget child; // 子控件
  final int count; // 波纹圈数
  final double width; // 波纹直径
  final double maxWidth; // 波纹扩散后最大直径
  final Color borderColor; // 波纹边框颜色
  final double borderWidth; // 波纹粗细
  final Duration duration; // 波纹扩散动画时长(毫秒)

  WaveBorder({
    Key key,
    this.child,
    this.count = 1,
    this.width,
    this.maxWidth,
    this.borderColor = Colors.white,
    this.borderWidth = 1,
    this.duration = const Duration(milliseconds: 5000),
  }) : super(key: key);

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

class _WaveBorderState extends State with TickerProviderStateMixin {
  List _controllerList = []; // 动画控制器数组
  List children = []; // 子组件数组(所有波纹 + child)

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

    // 配置动画和子控件
    configAnimation();
  }

  configAnimation() {
    for (int i = 0; i < widget.count; i++) {
      // 动画控制器
      var controller = AnimationController(
        vsync: this,
        duration: widget.duration,
      );
      // 控制器放数组里方便销毁
      _controllerList.add(controller);

      // 波纹放大比例
      double endScale = widget.maxWidth / widget.width;

      // 放大动画
      var scaleAnimation = Tween(
        begin: 1.0,
        end: endScale,
      ).animate(controller);

      // 透明动画
      var opacityAnimation = Tween(
        begin: 1.0,
        end: 0.0,
      ).animate(controller);

      // 添加波纹组件
      children.add(_borderWidget(scaleAnimation, opacityAnimation));

      // 每道波纹动画间隔
      int interval = widget.duration.inMilliseconds ~/ widget.count;

      Future.delayed(Duration(milliseconds: i * interval), () {
        // 执行动画
        if (mounted) {
          controller.repeat();
        }
      });
    }

    // 添加子控件child
    if (widget.child != null) {
      children.add(widget.child);
    }
  }

  @override
  void dispose() {
    // 销毁动画控制器
    _controllerList.forEach((controller) {
      controller.dispose();
    });
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.center,
      children: children,
    );
  }

  Widget _borderWidget(Animation scaleAnimation, Animation opacityAnimation) {
    return ScaleTransition(
      alignment: Alignment.center,
      scale: scaleAnimation,
      child: FadeTransition(
        opacity: opacityAnimation,
        child: Container(
          width: widget.width,
          height: widget.width,
          decoration: BoxDecoration(
            color: Colors.transparent,
            borderRadius: BorderRadius.circular(widget.width / 2),
            border: Border.all(color: widget.borderColor, width: widget.borderWidth),
          ),
        ),
      ),
    );
  }
}

使用:

WaveBorder(
    width: 200.w,
    maxWidth: 300.w,
    count: 2,
    borderColor: Colors.white,
    borderWidth: 1,
    duration: Duration(milliseconds: 4000),
    child: MusicPlayBtn(playing: isPlaying.value),
);

你可能感兴趣的:(Flutter水波纹边框)