flutter开发实战-卡片翻转动画效果Transform+IndexedStack+rotateAnimation

flutter开发实战-实现卡片翻转动画效果

之前开发中遇到了商品卡片翻转,商品正面是商品图片、商品名称;背面是商品价格,需要做卡片翻转动画。
动画实现即:在一段时间内,快速地多次改变UI外观;由于人眼会产生视觉暂留,所以最终看到的就是一个“连续”的动画。
这里实现翻转动画,实现方案Transform+IndexedStack
IndexedStack在翻转角度不同,显示对应的card信息
index: _rotateAnimation.value < pi / 2.0 ? 0 : 1,

一、效果图

运行后效果图如下

flutter开发实战-卡片翻转动画效果Transform+IndexedStack+rotateAnimation_第1张图片
flutter开发实战-卡片翻转动画效果Transform+IndexedStack+rotateAnimation_第2张图片

二、代码实现

IndexedStack

IndexedStack({
    super.key,
    super.alignment,
    super.textDirection,
    super.clipBehavior,
    StackFit sizing = StackFit.loose,
    this.index = 0,
    super.children,
  }) : super(fit: sizing);

完整动画效果代码如下

import 'dart:async';
import 'dart:math';
import 'dart:ui';

import 'package:flutter/material.dart';

class GoodsCardFlip extends StatefulWidget {
  const GoodsCardFlip({super.key, required this.cardSize});

  final Size cardSize;

  
  State<GoodsCardFlip> createState() => _GoodsCardFlipState();
}

class _GoodsCardFlipState extends State<GoodsCardFlip>
    with TickerProviderStateMixin {
  late AnimationController _animationController;

  // 翻转动画
  late Animation<double> _rotateAnimation;

  late AnimationStatus _lastStatus = AnimationStatus.dismissed;

  Timer? _globalFlipTimer;

  // 定义一个翻转从左往右,为false,如果为true,则从右往左开始翻转
  bool _flipReversal = false;
  int _flipDelay = 0; // 从左向右延迟翻转时间
  int _flipReversalDelay = 0; // 从右向左延迟翻转时间
  bool _isSetFlipDelay = false;

  bool _isDisposed = false;

  
  void initState() {
    // TODO: implement initState
    super.initState();
    _isDisposed = false;

    _flipReversal = false;
    _animationController =
        AnimationController(vsync: this, duration: Duration(milliseconds: 500));

    //使用弹性曲线
    _rotateAnimation =
        CurvedAnimation(parent: _animationController, curve: Curves.linear);
    _rotateAnimation = Tween(begin: 0.0, end: pi).animate(_rotateAnimation);

    _animationController.addListener(() {
      if (mounted) {
        setState(() {});
      }
    });

    _animationController.addStatusListener((status) {
      if (status == _lastStatus) return;
      _lastStatus = status;
    });


    // 横屏的全部翻转到价值的控制定时器
    _globalFlipTimer = new Timer.periodic(new Duration(seconds: 15), (timer) {
      // 整体翻转动画
      flipCards();
    });
  }

  void timerDispose() {
    _globalFlipTimer?.cancel();
    _globalFlipTimer = null;
  }

  void animationDispose() {
    _animationController.dispose();
  }

  
  void dispose() {
    // TODO: implement dispose
    animationDispose();
    timerDispose();
    super.dispose();
    _isDisposed = true;
  }

  void switchCard() {}

  
  Widget build(BuildContext context) {
    return buildGlobal();
  }

  Matrix4 _buildTransform() {
    final matrix = Matrix4.identity()
      ..rotateY(_rotateAnimation.value);
    return matrix;
  }

  Widget buildGlobal() {
    return Container(
      width: widget.cardSize.width,
      height: widget.cardSize.height,
      alignment: Alignment.center,
      child: ClipRRect(
        borderRadius:
        BorderRadius.all(Radius.circular(13.0)),
        child: Transform(
          transform: _buildTransform(),
          alignment: Alignment.center,
          child: IndexedStack(
            alignment: Alignment.center,
            children: <Widget>[
              buildFront(),
              buildBack(),
            ],
            index: _rotateAnimation.value < pi / 2.0 ? 0 : 1,
          ),
        ),
      ),
    );
  }

  Widget buildFront() {
    return GoodsImageCard(
      cardSize: widget.cardSize,
    );
  }

  Widget buildBack() {
    return Transform(
      alignment: Alignment.center,
      transform: Matrix4.identity()
        ..rotateY(pi),
      child: GoodsPriceCard(
        cardSize: widget.cardSize,
      ),
    );
  }

// 处理定时器
  void flipCards() {
    int delay = 0;
    if (_isSetFlipDelay == false) {
      // 如果从右向左,翻转时,则卡片在右侧的delay小于卡片在左侧的delay
      // 每次间隔的翻转延迟时间,100毫秒
      double perDelay = 100.0;
      _flipDelay = delay;
      // 如果从右向左,翻转时,则卡片在右侧的delay小于卡片在左侧的delay
      int reversalDelay =
      100;
      _flipReversalDelay = reversalDelay;
    } else {
      if (_flipReversal) {
        // 如果从右向左,翻转时,则卡片在右侧的delay小于卡片在左侧的delay
        delay = _flipReversalDelay;
      } else {
        delay = _flipDelay;
      }
    }

    _isSetFlipDelay = true;

    Future.delayed(Duration(milliseconds: delay), () {
      cardFlip(_flipReversal);
    });
  }

  // 翻转动画
  void cardFlip(bool reverse) {
    if (_isDisposed == true) {
      return;
    }

    if (_animationController.isAnimating) return;
    if (reverse) {
      _animationController.reverse();
    } else {
      _animationController.forward();
    }
    _flipReversal = !_flipReversal;

    if (_flipReversal == true) {
      Future.delayed(Duration(seconds: 5), () {
        flipCards();
      });
    }
  }
}

class GoodsImageCard extends StatelessWidget {
  const GoodsImageCard({super.key, required this.cardSize});
  final Size cardSize;

  
  Widget build(BuildContext context) {
    return Container(
      width: cardSize.width,
      height: cardSize.height,
      color: Colors.greenAccent,
      alignment: Alignment.center,
      child: Text('详情card',style: TextStyle(
        fontSize: 26,
        fontWeight: FontWeight.w700,
        fontStyle: FontStyle.normal,
        color: Colors.white,
        decoration: TextDecoration.none,
      ),),
    );
  }
}

class GoodsPriceCard extends StatelessWidget {
  const GoodsPriceCard({super.key, required this.cardSize});
  final Size cardSize;

  
  Widget build(BuildContext context) {
    return Container(
      width: cardSize.width,
      height: cardSize.height,
      color: Colors.blueAccent,
      alignment: Alignment.center,
      child: Text('价格card',style: TextStyle(
        fontSize: 26,
        fontWeight: FontWeight.w700,
        fontStyle: FontStyle.normal,
        color: Colors.white,
        decoration: TextDecoration.none,
      ),),
    );
  }
}

三、小结

flutter开发实战-Canvas绘图之Path路径动画

flutter开发实战-实现卡片翻转动画效果,实现方案Transform+IndexedStack,IndexedStack在翻转角度不同,显示对应的card信息。

学习记录,每天不停进步。

你可能感兴趣的:(flutter,flutter开发实战,移动开发,flutter,Transform,IndexedStack,开发实战,移动开发,动画)