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 -…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...
车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...
归并排序:分治思想的高效排序
目录 基本原理 流程图解 实现方法 递归实现 非递归实现 演示过程 时间复杂度 基本原理 归并排序(Merge Sort)是一种基于分治思想的排序算法,由约翰冯诺伊曼在1945年提出。其核心思想包括: 分割(Divide):将待排序数组递归地分成两个子…...
