当前位置: 首页 > news >正文

Android Flutter在点击事件上添加动画效果

在Android App的开发项目中,我们需要在点击事件上实现一个动画效果来提高用户的体验度。比如闲鱼底部中间按钮的那种。该怎么实现呢? 一起来看看吧

实现效果如图:

​实现思路

根据UI的设计图,对每个模块设计好动画效果,需要实现以下四个效果。

1、底部返回键旋转动画

底部返回按钮动画其实就是个旋转动画,利用Transform.rotate设置angle的值即可,这里使用了GetX来对angle进行动态控制。

//返回键旋转角度,初始旋转45度,使其初始样式为 +
var angle = (pi / 4).obs;///关闭按钮旋转动画控制器
late final AnimationController closeController;
late final Animation<double> closeAnimation;///返回键旋转动画
closeController = AnimationController(duration: const Duration(milliseconds: 300),vsync: provider,
);///返回键旋转动画
closeController = AnimationController(duration: const Duration(milliseconds: 300),vsync: provider,
);///页面渲染完才开始执行,不然第一次打开不会启动动画
WidgetsBinding.instance.addPostFrameCallback((duration) {closeAnimation =Tween(begin: pi / 4, end: pi / 2).animate(closeController)..addListener(() {angle.value = closeAnimation.value;});closeController.forward();
});///关闭按钮点击事件
void close() {///反转动画,并关闭页面Future.delayed(const Duration(milliseconds: 120), () {Get.back();});closeController.reverse();
}IconButton(onPressed: null,alignment: Alignment.center,icon: Transform.rotate(angle: controller.angle.value,child: SvgPicture.asset("assets/user/ic-train-car-close.svg",width: 18,height: 18,color: Colors.black,),))

2、底部四个栏目变速上移动画+渐变动画

四个栏目其实就是个平移动画,只不过闲鱼是四个栏目一起平移,而我选择了变速平移,这样视觉效果上会好一点。

//透明度变化
List<AnimationController> opacityControllerList = [];
//上移动画,由于每个栏目的移动速度不一样,需要用List保存四个AnimationController,
//如果想像闲鱼那种整体上移,则只用一个AnimationController即可。
List<AnimationController> offsetControllerList = [];
List<Animation<Offset>> offsetAnimationList = [];//之所以用addIf,是因为项目中这几个栏目的显示是动态显示的,这里就直接写成true
Column(children: []..addIf(true,buildItem('assets/user/ic-train-nomal-car.webp',"学车加练","自主预约,快速拿证"))..addIf(true,buildItem('assets/user/ic-train-fuuxn-car.webp',"有证复训","优质陪练,轻松驾车"))..addIf(true,buildItem('assets/user/ic-train-jiaxun-car.webp',"模拟加训","考前加训,临考不惧"))..addIf(true,buildItem('assets/user/ic-train-jiakao-car.webp',"驾考报名","快捷报名无门槛"))..add(playWidget())..addAll([17.space,]),)//仅仅是为了在offsetController全部初始化完后执行play()
Widget playWidget() {//执行动画play();return Container();
}int i = 0;Widget buildItem(String img,String tab,String slogan) {//由于底部栏目是动态显示的,需要在创建Widget时一同创建offsetController和offsetAnimationi++;AnimationController offsetController = AnimationController(duration: Duration(milliseconds: 100 + i * 20),vsync: this,);Animation<Offset> offsetAnimation = Tween<Offset>(begin: const Offset(0, 2.5),end: const Offset(0, 0),).animate(CurvedAnimation(parent: offsetController,// curve: Curves.easeInOutSine,curve: const Cubic(0.12, 0.28, 0.48, 1),));AnimationController opacityController = AnimationController(duration: const Duration(milliseconds: 500),lowerBound: 0.2,upperBound: 1.0,vsync: this);opacityControllerList.add(opacityController);offsetControllerList.add(offsetController);offsetAnimationList.add(offsetAnimation);return SlideTransition(position: offsetAnimation,child: FadeTransition(opacity: opacityController,child: Container(margin: EdgeInsets.only(bottom: 16),height: 62,decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(12)),color: const Color(0xfffafafa)),child:Row(mainAxisAlignment: MainAxisAlignment.center, children: [24.space,Image.asset(img, width: 44, height: 44),12.space,Column(crossAxisAlignment: CrossAxisAlignment.start,mainAxisSize: MainAxisSize.min,children: [Text(tab,style: const TextStyle(color: Color(0XFF000000),fontSize: 16,fontWeight: FontWeight.bold)),Text(slogan,style: const TextStyle(color: Color(0XFF6e6e6e), fontSize: 12)),]).expanded,Image.asset("assets/user/ic-train-arrow.webp",width: 44, height: 44),17.space])).inkWell(onTap: () {},delayMilliseconds: 50)),);
}//执行动画
void play() async {for (int i = 0; i < offsetControllerList.length; i++) {opacityControllerList[i].forward();///栏目正序依次延迟(40 + 2 * i) * i的时间,曲线速率Future.delayed(Duration(milliseconds: (40 + 2 * i) * i), () {offsetControllerList[i].forward().whenComplete(() => offsetControllerList[i].stop());});}
}///关闭按钮点击事件
void close() {///反转动画,并关闭页面Future.delayed(const Duration(milliseconds: 120), () {Get.back();});for (int i = offsetControllerList.length - 1; i >= 0; i--) {///栏目倒叙依次延迟(40 + 2 * (offsetControllerList.length-1-i)) * (offsetControllerList.length-1-i))的时间Future.delayed(Duration(milliseconds:(40 + 2 * (offsetControllerList.length-1-i)) * (offsetControllerList.length-1-i)), () {offsetControllerList[i].reverse();});}opacityTopController.reverse();
}

3、中间图片渐变动画

渐变动画使用FadeTransition即可。

///图片透明度渐变动画控制器
late final AnimationController imgController;///图片透明度渐变动画
imgController = AnimationController(duration: const Duration(milliseconds: 500),lowerBound: 0.0,upperBound: 1.0,vsync: provider);
imgController.forward().whenComplete(() => imgController.stop());///渐变过渡
FadeTransition(opacity: imgController,child:Image.asset("assets/user/ic-traincar-guide.webp"),
),///关闭按钮点击事件
void close() {imgController.reverse();
}

4、顶部文案渐变动画+下移动画

///顶部标题下移动画控制器
late final AnimationController offsetTopController;
late final Animation<Offset> offsetTopAnimation;///顶部标题渐变动画控制器
late final AnimationController opacityTopController;///顶部标题上移动画
offsetTopController = AnimationController(duration: const Duration(milliseconds: 300),vsync: provider,
);
offsetTopController.forward().whenComplete(() => offsetTopController.stop());
offsetTopAnimation = Tween<Offset>(begin: const Offset(0, -0.8),end: const Offset(0, 0),
).animate(CurvedAnimation(parent: offsetTopController,curve: Curves.easeInOutCubic,
));
offsetTopController.forward().whenComplete(() => offsetTopController.stop());//UI
SlideTransition(position: offsetTopAnimation,child: FadeTransition(opacity: opacityTopController,child: Column(crossAxisAlignment: CrossAxisAlignment.start,mainAxisAlignment: MainAxisAlignment.start,mainAxisSize: MainAxisSize.min,children: [80.space,const Text('练车指南',style: TextStyle(color: Color(0XFF141414),fontSize: 32,fontWeight: FontWeight.w800,),),2.space,const Text('易练只为您提供优质教练,为您的安全保驾护航',style: TextStyle(color: Color(0XFF141414),fontSize: 15)),],))),///关闭按钮点击事件
void close() {offsetTopController.reverse();opacityTopController.reverse();}

5、注销动画

最后,在关闭页面的时候不要忘记注销动画。

///关闭时注销动画
void dispose() {for (int i = offsetControllerList.length - 1; i > 0; i--) {offsetControllerList[i].dispose();}offsetTopController.dispose();opacityTopController.dispose();imgController.dispose();closeController.dispose();
}

以上就是Android Flutter实现仿闲鱼动画效果的详细内容,更多关于Android Flutter知识可以参考

Android Futtter学习文档​

 

相关文章:

Android Flutter在点击事件上添加动画效果

在Android App的开发项目中&#xff0c;我们需要在点击事件上实现一个动画效果来提高用户的体验度。比如闲鱼底部中间按钮的那种。该怎么实现呢&#xff1f; 一起来看看吧 实现效果如图&#xff1a; ​实现思路 根据UI的设计图&#xff0c;对每个模块设计好动画效果&#xff0…...

VSCode嵌入式开发环境搭建

Vscode开发环境搭建 看这个链接就可以了&#xff0c;后面下载调试有点问题看下3.3。 在VSCode上部署STM32F1的开发环境 1. MXCube配置工程生成Makefile文件 借助正确的编译工具链进行编译&#xff0c; 2. 编译工具链搭建 编译工具链使用GCC的ARM版本 arm-none-eabi-gcc &am…...

数据结构之栈的使用

栈是计算机科学中一个重要的数据结构。它是一种特殊的线性表&#xff0c;只允许在一端进行进出操作。这一端被称为栈顶&#xff0c;另外一端被称为栈底。栈的特点是后进先出&#xff0c;即最后进入栈的元素会先被弹出栈。栈的应用广泛&#xff0c;例如在编译器中&#xff0c;栈…...

QMessageBox手动添加按钮并绑定按钮的信号

视频展示效果&#xff08;结合代码看效果更佳哦&#xff0c;代码在最下面&#xff09;&#xff1a; QMessageBox手动添加有重试效果的按钮效果图&#xff1a; 点击详细文本之后展开如下图&#xff1a; 图标可选&#xff1a; QMessageBox::Critical错误图标QMessageBox::NoIco…...

【C++进阶】位图和布隆过滤器

文章目录位图位图概念位图使用场景位图的结构构造setresettest完整代码布隆过滤器布隆过滤器概念布隆过滤器结构构造setresettest完整版代码位图 位图概念 所谓位图&#xff0c;就是用每一位来存放某种状态&#xff0c;适用于海量数据&#xff0c;数据无重复的场景。通常是用…...

Android开发-Android UI与布局

01 Android UI 1.1 UI 用户界面(User Interface&#xff0c;简称 UI&#xff0c;亦称使用者界面)是系统和用户之间进行交互和信息交换的媒介&#xff0c;它实现信息的内部形式与人类可以接受形式之间的转换。软件设计可分为两个部分&#xff1a;编码设计与UI设计。 1.2 Andr…...

在不丢失数据的情况下解锁锁定的 Android 手机的 4 种方法

尽管您可以使用指纹解锁手机&#xff0c;但大多数智能手机都需要 PIN 码、图案或字母数字代码作为主密码。如果您有一段时间没有输入手机密码&#xff0c;很容易忘记。正是由于这个原因&#xff0c;即使您打开了指纹解锁&#xff0c;大多数智能手机也会让您每天至少输入一次 PI…...

【11】核心易中期刊推荐——人工智能 | 图形图像处理

🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…...

Spring 中的事件发布与监听

主要代码在org.springframework.context&#xff0c;org.springframework.context.event包中 事件发布与监听主要包含以下角色&#xff1a; 事件&#xff1a;ApplicationEvent事件监听器&#xff1a;ApplicationListener SmartApplicationListener GenericApplicationListene…...

c++ 一些常识 2

前言 今天主要讲类相关概念。 构造和析构函数是否可以抛出异常 在构造函数中抛出异常&#xff0c;控制权会转出构造函数之外&#xff0c;对象的析构函数不会被调用&#xff0c;造成内存泄漏。 如果析构函数中抛出异常&#xff0c;而且没有在当地捕捉&#xff0c;析构函数便执…...

用嘴写代码?继ChatGPT和NewBing之后,微软又开始整活了,Github Copilot X!

用嘴写代码&#xff1f;继ChatGPT和NewBing之后&#xff0c;微软又开始整活了&#xff0c;Github Copilot X&#xff01; AI盛行的时代来临了&#xff0c;在这段时间&#xff0c;除了爆火的GPT3.5后&#xff0c;OpenAI发布了GPT4版本&#xff0c;同时微软也在Bing上开始加入了A…...

3分钟阐述这些年我的 接口自动化测试 职业生涯经验分享

接口自动化测试学习教程地址&#xff1a;https://www.bilibili.com/video/BV1914y1F7Bv/ 你好&#xff0c;我是凡哥。 很高兴能够分享我的接口自动化测试经验和心得体会。在我目前的职业生涯中&#xff0c;接口自动化测试是我经常进行的一项任务。通过不断地学习和实践&#xf…...

十大Python可视化工具,太强了

今天介绍Python当中十大可视化工具&#xff0c;每一个都独具特色&#xff0c;惊艳一方。 Matplotlib Matplotlib 是 Python 的一个绘图库&#xff0c;可以绘制出高质量的折线图、散点图、柱状图、条形图等等。它也是许多其他可视化库的基础。 import matplotlib.pyplot as p…...

五.ElasticSearch的基础+实战

五.ElasticSearch的基础+实战 1.Elasticsearch的是什么? 2.Elasticsearch的作用是什么? 3.Elasticsearch的核心思想? 4.Elasticsearch启动与简单使用 5.kibana结合elasticsearch实现简单的增删改查 6.elasticsearch安装中文分词器 7.elasticsearch结合springboot开发…...

Oracle的学习心得和知识总结(十三)|Oracle数据库Real Application Testing之Database Reply实操(一)

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《Oracle Database SQL Language Reference》 2、参考书籍&#xff1a;《PostgreSQL中文手册》 3、EDB Postgres Advanced Server User Guid…...

CAD外部参照如何重新定位?CAD外部参照重定位步骤

CAD外部参照如何重新定位&#xff1f;这个问题并不算是一个常见的问题&#xff0c;但偶尔也会遇到&#xff0c;今天小编就来给大家简单介绍一下浩辰CAD软件中CAD外部参照重定位的操作步骤&#xff0c;一起来看看吧&#xff01; CAD外部参照重定位步骤&#xff1a; 浩辰CAD软件…...

11. C#高级进阶

一、C# 异常处理 在 C# 中&#xff0c;异常是在程序运行出错时引发的&#xff0c;所有异常都派生自 System.Exception 类。异常处理就是处理运行时错误的过程&#xff0c;通过异常处理可以使程序在发生错误时保持正常运行。 C# 中的异常处理基于四个关键字构建&#xff0c;分别…...

网络编程套接字( TCP协议通讯流程)

目录 1、绑定失败问题 2、TCP协议通讯流程 三次握手的过程 数据传输的过程 四次挥手的过程 TCP和UDP对比 1、绑定失败问题 当我们测试网络代码时&#xff0c;先将服务端绑定8080端口运行&#xff0c;然后运行客户端&#xff0c;并让客户端连接当前服务器&#xff1a; 当有客户…...

WPF毛笔字实现过程

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

MHA实现mysql数据库高可用

目录 MHA原理 MHA工具包 MHA实现mysql高可用实战 MHA原理 ①MHA利用 SELECT 1 As Value 指令判断master服务器的健康性,一旦master 宕机,MHA 从宕机崩溃的master保存二进制日志事件&#xff08;binlog events&#xff09; ②识别含有最新更新的slave ③应用差异的中继日志&…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...