Flutter 12 实现双击屏幕显示点赞爱心多种动画(AnimationIcon)效果

本文主要是使用Flutter封装一个双击屏幕显示点赞爱心UI效果,并实现了爱心Icon 透明度、缩放、旋转、渐变等动画效果。

实现效果:

实现逻辑:

1、封装FavoriteGesture(爱心手势)实现双击屏幕显示爱心Icon;

2、封装FavoriteAnimationIcon(爱心Icon)实现双击屏幕显示爱心Icon,快速双击时同时显示多个爱心Icon;

3、给FavoriteAnimationIcon增加透明度淡入淡出动画效果;

4、给FavoriteAnimationIcon增加缩放动画效果;

5、给FavoriteAnimationIcon增加旋转动画效果;

7、给FavoriteAnimationIcon增加渐变动画效果;

一、封装FavoriteGesture爱心手势

1)Stack实现多界面堆叠

实现爱心Icon显示在视频界面上层,视频界面由上层child传入,使用Stack实现多界面堆叠;

class FavoriteGesture extends StatefulWidget {
  static const double defaultSize = 100;

  final Widget child;
  final double size;

  const FavoriteGesture({super.key, this.size = defaultSize, required this.child});

  @override
  State<FavoriteGesture> createState() => _FavoriteGestureState();
}

class _FavoriteGestureState extends State<FavoriteGesture> {

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        widget.child,
        Icon(Icons.favorite, size: widget.size, color: Colors.redAccent)
      ],
    );
  }
}

2)GestureDetector监听双击事件

使用GestureDetector监听屏幕双击事件和点击的坐标,使用Positioned将Icon显示到点击坐标的位置;当用户双击屏幕时,显示爱心Icon,延迟600毫秒,爱心Icon消失。

class FavoriteGesture extends StatefulWidget {
  static const double defaultSize = 100;

  final Widget child;
  final double size;

  const FavoriteGesture({super.key, this.size = defaultSize, required this.child});

  @override
  State<FavoriteGesture> createState() => _FavoriteGestureState();
}

class _FavoriteGestureState extends State<FavoriteGesture> {
  final GlobalKey _key = GlobalKey();

  bool inFavorite = false;

  // temp表示最近的一次双击坐标
  Offset temp = Offset.zero;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        key: _key,
        onDoubleTapDown: (details) {
          temp = details.globalPosition;
        },
        onDoubleTap: () {
          setState(() {
            inFavorite = true;
          });
          Future.delayed(const Duration(milliseconds: 600), () {
            setState(() {
              inFavorite = false;
            });
          });
        },
        child: Stack(
          children: [
            widget.child,
            if (inFavorite)
              Positioned(
                  top: temp.dy - widget.size / 2,
                  left: temp.dx - widget.size / 2,
                  child: Icon(Icons.favorite, size: widget.size, color: Colors.redAccent)),
          ],
        ));
  }
}

3)RenderBox 实现屏幕坐标转换本地坐标

onDoubleTapDown: (details) {temp = details.globalPosition;} 获取到的点击坐标是屏幕的坐标,需要转换成Icon的父布局Stack的坐标,通过RenderBox 来实现屏幕坐标转换本地坐标。

class FavoriteGesture extends StatefulWidget {
  static const double defaultSize = 100;

  final Widget child;
  final double size;

  const FavoriteGesture({super.key, this.size = defaultSize, required this.child});

  @override
  State<FavoriteGesture> createState() => _FavoriteGestureState();
}

class _FavoriteGestureState extends State<FavoriteGesture> {
  final GlobalKey _key = GlobalKey();

  bool inFavorite = false;

  // temp表示最近的一次双击坐标
  Offset temp = Offset.zero;

  Offset _globalToLocal(Offset global) {
    RenderBox renderBox = _key.currentContext?.findRenderObject() as RenderBox;
    return renderBox.globalToLocal(global);
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        key: _key,
        onDoubleTapDown: (details) {
          temp = _globalToLocal(details.globalPosition);
        },
        on
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sziitjin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值