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

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

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

一、效果图

运行后效果图如下

在这里插入图片描述
在这里插入图片描述

二、代码实现

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 initStatesuper.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 disposeanimationDispose();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小于卡片在左侧的delayint reversalDelay =100;_flipReversalDelay = reversalDelay;} else {if (_flipReversal) {// 如果从右向左,翻转时,则卡片在右侧的delay小于卡片在左侧的delaydelay = _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信息。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/28651.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单例模式、指令重排序、锁、有序性

今天在回顾单例模式时&#xff0c;我们都知道懒汉式单例中有一种叫做双重检查锁的单例模式。 我们来看下下面的代码有没有问题&#xff1a; 这段代码我们可以看到&#xff0c;即优化了性能&#xff0c;在多线程情况下&#xff0c;如果实例不为空了&#xff0c;则直接返回了。…

[element-ui] el-select,虚拟滚动(vue-virtual-scroll-list)

一、问题描述 表单中某下拉框&#xff0c;由于数据过多&#xff0c;选择的时候会因为数据量过大导致页面卡顿&#xff0c;于是对于el-select进行二次封装&#xff0c;实现虚拟滚动。 二、实现如下&#xff1a; 看起来是加载了全部数据&#xff0c;实际上只加载了自己设定的1…

无需学习Python,一个公式搞定领导想看的大屏

摘要&#xff1a;本文由葡萄城技术团队于CSDN原创并首发。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 不要让“做不了”成为数字化转型的障碍 随着数字化的脚步加快&#xff0c;越来越多的企…

Spring Batch之读数据库—JdbcCursorItemReader之自定义PreparedStatementSetter(三十八)

一、自定义PreparedStatementSetter 详情参考我的另一篇博客&#xff1a; Spring Batch之读数据库——JdbcCursorItemReader&#xff08;三十五&#xff09;_人……杰的博客-CSDN博客 二、项目实例 1.项目实例 2.代码实现 BatchMain.java&#xff1a; package com.xj.dem…

制作Visual Studio离线安装包

vs2015之后官网就不提供离线安装包了&#xff0c;使用离线安装包就需要自己手动制作一个&#xff1b; 以vs2019为例&#xff1a; 先去官网下载在线安装器 官网下载地址&#xff1a;Visual Studio 较旧的下载 - 2019、2017、2015 和以前的版本 (microsoft.com) 展开2019的标签…

从小白到大神之路之学习运维第62天--------Ansible自动化运维工具(playbook配置深入了解2.0)

第三阶段基础 时 间&#xff1a;2023年7月17日 参加人&#xff1a;全班人员 内 容&#xff1a; playbook配置深入了解2.0 目录 一、角色 实验案例&#xff1a;&#xff08;安装Mariadb&#xff09; 二、变量 &#xff08;一&#xff09;在playbook中使用自定义变量&#xff1…

STM32芯片型号命名规则

意法半导体STM32和STM8系列的芯片可以通过下面一张图来确定芯片的各项参数&#xff0c;帮助选型。 STM32型号的说明&#xff1a;以STM32F103RBT6这个型号的芯片为例&#xff0c;该型号的组成为7个部分&#xff0c;其命名规则如下&#xff1a; ![在这里插入图片描述](https:…

文心一言 VS 讯飞星火 VS chatgpt (61)-- 算法导论6.4 5题

文心一言 VS 讯飞星火 VS chatgpt &#xff08;61&#xff09;-- 算法导论6.4 5题 五、证明:在所有元素都不同的情况下&#xff0c;HEAPSORT 的时间复杂度是 Ω (nlgn)。 文心一言&#xff1a; 要证明在所有元素都不同的情况下&#xff0c;HEAPSORT 的时间复杂度是 Ω(n log…

青岛大学_王卓老师【数据结构与算法】Week05_14_队列的顺序表示和实现2_学习笔记

本文是个人学习笔记&#xff0c;素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享&#xff0c; 另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权&#xff0c;请留言作删文处理。 课程视频链接&#xff1a; 数据结构与算法基础…

科研创新服务平台性能分析案例

前言 信息中心老师反应&#xff0c;用户反馈科研创新服务器平台有访问慢的情况&#xff0c;需要通过流量分析系统来了解系统的运行情况&#xff0c;此报告专门针对系统的性能数据做了分析。 信息中心已部署NetInside流量分析系统&#xff0c;使用流量分析系统提供实时和历史原…

走进人工智能|机器人技术 人机协作新纪元

前言&#xff1a; 机器人技术为人类提供协助、增强生产力&#xff0c;改善生活质量&#xff0c;并推动科技进步和社会发展。 文章目录 序言背景核心技术支持人机协作新纪元目前形式领跑人困难和挑战 总结 机器人技术作为现代科技领域的重要研究方向&#xff0c;已经在各个领域展…

TCP/IP网络编程 第十五章:套接字和标准I/O

标准I/O函数的优点 标准I/O函数的两个优点 将标准I/O函数用于数据通信并非难事。但仅掌握函数使用方法并没有太大意义&#xff0c;至少应该 了解这些函数具有的优点。下面列出的是标准I/O函数的两大优点: □标准I/O函数具有良好的移植性(Portability) □标准I/O函数可以利用缓…