Android实现漂亮的波纹动画
Android实现漂亮的波纹动画
本文章讲述如何使用二维画布canvas和camera、矩阵实现二、三维波纹动画效果(波纹大小变化、画笔透明度变化、画笔粗细变化)
一、UI界面
界面主要分为三部分
第一部分:输入框,根据输入x轴、Y轴、Z轴倾斜角度绘制波纹动画立体效果
第二部分:点击按钮PLAY:开始绘制动画;点击按钮STOP:停止绘制动画
第三部分:绘制波纹动画的自定义view

activity_main.xml实现如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="16dp"android:gravity="center"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:layout_marginBottom="8dp"><LinearLayoutandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:orientation="vertical"android:gravity="center_horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="X轴倾斜" /><EditTextandroid:id="@+id/editText_X"android:layout_width="match_parent"android:layout_height="wrap_content"android:inputType="number"android:text="0"/></LinearLayout><LinearLayoutandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:orientation="vertical"android:gravity="center_horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Y轴倾斜" /><EditTextandroid:id="@+id/editText_Y"android:layout_width="match_parent"android:layout_height="wrap_content"android:inputType="number"android:text="0"/></LinearLayout><LinearLayoutandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:orientation="vertical"android:gravity="center_horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Z轴倾斜" /><EditTextandroid:id="@+id/editText_Z"android:layout_width="match_parent"android:layout_height="wrap_content"android:inputType="number"android:text="0"/></LinearLayout></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:gravity="center"android:paddingTop="16dp"><Buttonandroid:id="@+id/playButton"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Play"android:layout_marginEnd="8dp"/><Buttonandroid:id="@+id/stopButton"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Stop"android:layout_marginEnd="8dp"/></LinearLayout><FrameLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:layout_gravity="center"><!-- WaveView --><com.example.waveanimationbysingleview.animation.WaveViewandroid:id="@+id/wave_view"android:layout_width="match_parent"android:layout_height="606dp"android:layout_gravity="center" /></FrameLayout></LinearLayout>
二、自定义view实现
新建一个WaveView类继承自View,声明类成员变量和实现构造函数初始化
public class WaveView extends View{private RippleAnimationInfo mRippleInfo;//动画属性类,包括最大、最小半径,光圈等private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);private float centerX, centerY; //绘制画布中心点private float[] mRadiusArray; // 存储当前绘制每圈光波的半径private float[] mAlphaArray; //存储当前绘制每圈光波的透明度private float[] mStrokenArray; //存储当前绘制每圈光波的画笔宽度private final Camera mCamera = new Camera();//相机private final Matrix mMatrix = new Matrix();//矩阵private final RectF mRectF = new RectF();private Boolean mIsDrawing = false;//是否绘制标志位private Bitmap mLogoBitmap;//中心点表情😝logoprivate AnimatorSet mAnimatorSet = new AnimatorSet();//多动画组合类private List<Animator> mAnimatorList = new ArrayList<>();//存储动画列表public WaveView(Context context) {super(context);init();}public WaveView(Context context, AttributeSet attrs) {super(context, attrs);init();}public WaveView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}
构造函数初始化
添加动画
- 圆圈等比变大动画
- 透明度渐变动画
- 画笔由细变粗动画
private void initAnimation() {int rippleDelay = mRippleInfo.durationTime/mRippleInfo.rippleCount;for (int i = 0; i < mRippleInfo.rippleCount; i++) {//动画1-半径变大final int index = i;ValueAnimator radiusAnimator = ValueAnimator.ofFloat(mRippleInfo.minRadius, mRippleInfo.maxRadius);radiusAnimator.setDuration(mRippleInfo.durationTime); // 动画持续时间radiusAnimator.setStartDelay(i * rippleDelay); // 延迟启动radiusAnimator.setRepeatCount(ValueAnimator.INFINITE);radiusAnimator.setRepeatMode(ValueAnimator.RESTART);radiusAnimator.addUpdateListener(animation -> {mRadiusArray[index] = (float) animation.getAnimatedValue();invalidate(); // 重绘视图});//动画2-画笔变粗ValueAnimator strokeAnimator = ObjectAnimator.ofFloat(mRippleInfo.minStrokenWidth, mRippleInfo.maxStrokenWidth);strokeAnimator.setDuration(mRippleInfo.durationTime); // 动画持续时间strokeAnimator.setStartDelay(i * rippleDelay); // 延迟启动strokeAnimator.setRepeatCount(ValueAnimator.INFINITE);strokeAnimator.setRepeatMode(ValueAnimator.RESTART);strokeAnimator.addUpdateListener(animation -> {mStrokenArray[index] = (float) animation.getAnimatedValue();invalidate(); // 重绘视图});//动画3-颜色淡出ValueAnimator alphaAnimator = ObjectAnimator.ofFloat( 0.1f, 0.8f, 0.8f,0.4f, 0);alphaAnimator.setDuration(mRippleInfo.durationTime); // 动画持续时间alphaAnimator.setStartDelay(i * rippleDelay); // 延迟启动alphaAnimator.setRepeatCount(ValueAnimator.INFINITE);alphaAnimator.setRepeatMode(ValueAnimator.RESTART);alphaAnimator.addUpdateListener(animation -> {mAlphaArray[index] = (float) animation.getAnimatedValue();invalidate(); // 重绘视图});mAnimatorList.add(radiusAnimator);mAnimatorList.add(strokeAnimator);mAnimatorList.add(alphaAnimator);}mAnimatorSet.playTogether(mAnimatorList);}
应用矩阵变换
重写ondraw
@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (!mIsDrawing){return;}canvas.save();// 计算中心点centerX = getWidth() / 2.0f;centerY = getHeight() / 2.0f;canvas.concat(mMatrix);// 将矩阵应用到画布上//绘制多圈波纹for (int i = 0; i < mRippleInfo.rippleCount; i++) {if (mRadiusArray[i] > 0) {paint.setStrokeWidth(mStrokenArray[i]);paint.setAlpha((int)(255 * mAlphaArray[i]));canvas.drawCircle(centerX, centerY,mRadiusArray[i],paint);}}// 中心点绘制 logocanvas.drawBitmap(mLogoBitmap, (getWidth()- mRippleInfo.minRadius)/2, (getHeight()- mRippleInfo.minRadius)/2, null);canvas.restore();}
二、二维波纹动画
waveAnimation_2D
三、三维波纹动画
waveAnimation_3D
相关文章:
Android实现漂亮的波纹动画
Android实现漂亮的波纹动画 本文章讲述如何使用二维画布canvas和camera、矩阵实现二、三维波纹动画效果(波纹大小变化、画笔透明度变化、画笔粗细变化) 一、UI界面 界面主要分为三部分 第一部分:输入框,根据输入x轴、Y轴、Z轴倾…...
JAVA学习笔记038——bean的概念和常见注解标注
什么是bean? Bean 就是 被 Spring 管理的对象,就像工厂流水线上生产的“标准产品”。这些对象不是你自己 new 出来的,而是由 Spring 容器(一个超级工厂)帮你创建、组装、管理。 由 Component、Service、Controller 等注解标记的…...
自然语言处理NLP入门 -- 第十节NLP 实战项目 2: 简单的聊天机器人
一、为什么要做聊天机器人? 在互联网时代,我们日常接触到的“在线客服”“自动问答”等,大多是以聊天机器人的形式出现。它能帮我们快速回复常见问题,让用户获得及时的帮助,并在一定程度上减少人工客服的压力。 同时&…...
【网络安全 | 渗透工具】小程序反编译分析源码 | 图文教程
未经许可,禁止转载。 本文仅供学习使用,严禁用于非法渗透测试,笔者不承担任何责任。 文章目录 1、下载Proxifier2、下载反编译工具unveilr3、寻找小程序文件包4、对文件包进行反编译5、对源码进行分析6、渗透思路6.1、查找敏感信息泄露6.2、解析加解密逻辑6.3、枚举 API 接口…...
uniapp 系统学习,从入门到实战(六)—— 样式与布局
全篇大概 4700 字(含代码),建议阅读时间 30min 📚 目录 Flex 布局在 UniApp 中的应用响应式设计与适配多端使用 SCSS 提升样式开发效率实战案例演示总结 1. Flex 布局在 UniApp 中的应用 1.1 基础布局实现 通过 display: flex 快速构建弹性容器&#…...
‘ts-node‘ 不是内部或外部命令,也不是可运行的程序
新建一个test.ts文件 let message: string = Hello World; console.log(message);如果没有任何配置的前提下,会报错’ts-node’ 不是内部或外部命令,也不是可运行的程序。 此时需要安装一下ts-node。 npm install...
mysql 全方位安装教程
下载 MySQL 【官网下载地址】 注意要选择较大的哪个安装包,小的安装包是一个安装器。 我们不用登录,直接下载 直接运行下载好的安装包 MySQL如果是 安装包安装, 可以图形化界面自主配置 如果是压缩包解压, 可以配置 配置文件, 可以解压安装到指定的…...
22-接雨水
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 方法一:双指针法 思路 使用两个指针 left 和 right 分别指向数组的两端,同时记录左边的最大高度 leftMax 和右边的最大高度 rig…...
使用Spring Boot与达梦数据库(DM)进行多数据源配置及MyBatis Plus集成
使用Spring Boot与达梦数据库(DM)进行多数据源配置及MyBatis Plus集成 在现代企业级应用开发中,处理多个数据源是一个常见的需求。本文将详细介绍如何使用Spring Boot结合达梦数据库(DM),并通过MyBatis Plus来简化数据库操作&…...
leetcode28 找出字符串第一个匹配值的下标 KMP算法
KMP 算法——快速的从主串中找到模式串 当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。 KMP 算法 比较指针不回溯,仅仅是后移模式串。 每次不匹配的时候,找之前已匹配部分…...
【Bug】natten:安装报错(临近注意力机制的高效cuda内核实现)
正常安装natten报错 pip install natten 报错 可以尝试使用以下网站进行安装 https://shi-labs.com/natten/ 可以根据自己的cuda与pytorch版本进行安装 之间复制命令即可,不需要进行任何修改...
AI 实战2 - face -detect
人脸检测 环境安装源设置conda 环境安装依赖库 概述数据集wider_face转yolo环境依赖标注信息格式转换图片处理生成 train.txt 文件 数据集展示数据集加载和处理 参考文章 环境 安装源设置 conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/f…...
Spring Boot 项目开发流程全解析
目录 引言 一、开发环境准备 二、创建项目 三、项目结构 四、开发业务逻辑 1.创建实体类: 2.创建数据访问层(DAO): 3.创建服务层(Service): 4.创建控制器层(Controller&…...
从Java到MySQL8源码:深入解析PreparedStatement参数绑定与执行机制
引言 在数据库开发中,PreparedStatement(预处理语句)是防止SQL注入、提升性能的重要工具。它通过分离SQL结构与参数值,不仅增强了安全性,还能利用预编译优化执行效率。本文将从Java JDBC驱动和MySQL 8源码的双重视角&…...
mysql的主从同步
1、异步复制:这是MySQL默认的复制模式。在这种模式下,主库在执行完客户端提交的事务后会立即将结果返回给客户端,并不关心从库是否已经接收并处理。这种模式的优点是实现简单,但缺点是如果主库崩溃,已经提交的事务可能…...
工程化与框架系列(10)--微前端架构
微前端架构 🏗️ 微前端是一种将前端应用分解成更小、更易管理的独立部分的架构模式。本文将详细介绍微前端的核心概念、实现方案和最佳实践。 微前端概述 🌟 💡 小知识:微前端的核心理念是将前端应用分解成一系列独立部署、松耦…...
【3天快速入门WPF】11-附加属性
目录 1. 步骤1:定义附加属性2. 示例代码3. 步骤2:在XAML中使用附加属性3.1. 示例代码4. 步骤3:扩展使用场景4.1. 示例代码5. 总结上一篇讲到了依赖属性,本篇主要想说一下附加属性。 在WPF中,附加属性(Attached Property)是一种特殊的依赖属性,允许你在不属于某个类的控…...
MySQL并发知识(面试高频)
mysql并发事务解决 不同隔离级别下,mysql解决并发事务的方式不同。主要由锁机制和MVCC(多版本并发控制)机制来解决并发事务问题。 1. mysql中的锁有哪些? 表级锁: 场景:表级锁适用于需要对整个表进行操作的情况,例如…...
现存脑容知识库
Redis import queue import threading import asyncio 异步:在一个线程内,等待的时候可以切换到其他任务。 多线程:每个线程独立运行,同时处理多个任务。 回调函数 网络请求(JavaScript)在浏览器中&a…...
Mysql-如何理解事务?
一、事务是什么东西 有些场景中,某个操作需要多个sql配合完成: 例如: 李四这个月剩下的前不够交房租了,找张三借1000元急用: (1)给张三的账户余额 减去1000元 updata 账户表 set money money -…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
