Android 气泡动画(自定义View类)

  • 一、前言
  • 二、代码
    • 1. 随机移动的气泡
    • 2.热水气泡

一、前言

最近有需求制作一个水壶的气泡动画,首先在网上查找了一番,找到了一个文章。

https://blog.csdn.net/u010386612/article/details/50580080

测试了一下发现,如果把它作为子视图的话,会出现小球溢出边界的情况。所以简单的修改了一下。

二、代码

1. 随机移动的气泡

Ball类

/*** @author jiang yuhang* @date 2021-04-18 19:57*/
class Ball {// 半径@kotlin.jvm.JvmFieldvar radius = 0// 圆心@kotlin.jvm.JvmFieldvar cx = 0f// 圆心@kotlin.jvm.JvmFieldvar cy = 0f// X轴速度@kotlin.jvm.JvmFieldvar vx = 0f// Y轴速度@kotlin.jvm.JvmFieldvar vy = 0f@kotlin.jvm.JvmFieldvar paint: Paint? = null// 移动fun move() {//向角度的方向移动,偏移圆心cx += vxcy += vy}fun left(): Int {return (cx - radius).toInt()}fun right(): Int {return (cx + radius).toInt()}fun bottom(): Int {return (cy + radius).toInt()}fun top(): Int {return (cy - radius).toInt()}
}

BallView类

/*** @author jiang yuhang* @date 2021-04-18 19:53*/
public class BallView extends View {private final Random mRandom;private final int mCount = 5;   // 小球个数private final int minSpeed = 5; // 小球最小移动速度private final int maxSpeed = 20; // 小球最大移动速度public Ball[] mBalls;   // 用来保存所有小球的数组private int maxRadius;  // 小球最大半径private int minRadius; // 小球最小半径private int mWidth = 200;private int mHeight = 200;public BallView(final Context context, final AttributeSet attrs) {super(context, attrs);// 初始化所有球(设置颜色和画笔, 初始化移动的角度)this.mRandom = new Random();final RandomColor randomColor = new RandomColor(); // 随机生成好看的颜色,github开源库。this.mBalls = new Ball[this.mCount];for (int i = 0; i < this.mCount; i++) {this.mBalls[i] = new Ball();// 设置画笔final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setColor(randomColor.randomColor());paint.setStyle(Paint.Style.FILL);paint.setAlpha(180);paint.setStrokeWidth(0);// 设置速度final float speedX = (this.mRandom.nextInt(this.maxSpeed - this.minSpeed + 1) + 5) / 10f;final float speedY = (this.mRandom.nextInt(this.maxSpeed - this.minSpeed + 1) + 5) / 10f;this.mBalls[i].paint = paint;this.mBalls[i].vx = this.mRandom.nextBoolean() ? speedX : -speedX;this.mBalls[i].vy = this.mRandom.nextBoolean() ? speedY : -speedY;}}@Overrideprotected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);this.mWidth = View.resolveSize(this.mWidth, widthMeasureSpec);this.mHeight = View.resolveSize(this.mHeight, heightMeasureSpec);this.setMeasuredDimension(this.mWidth, this.mHeight);this.maxRadius = this.mWidth / 12;this.minRadius = this.maxRadius / 2;// 初始化圆的半径和圆心for (Ball mBall : this.mBalls) {mBall.radius = this.mRandom.nextInt(this.maxRadius + 1 - this.minRadius) + this.minRadius;// 初始化圆心的位置, x最小为 radius, 最大为mwidth- radiusmBall.cx = this.mRandom.nextInt(this.mWidth - mBall.radius) + mBall.radius;mBall.cy = this.mRandom.nextInt(this.mHeight - mBall.radius) + mBall.radius;}}@Overrideprotected void onDraw(final Canvas canvas) {final long startTime = System.currentTimeMillis();// 先画出所有圆for (int i = 0; i < this.mCount; i++) {final Ball ball = this.mBalls[i];canvas.drawCircle(ball.cx, ball.cy, ball.radius, ball.paint);}// 球碰撞边界for (int i = 0; i < this.mCount; i++) {final Ball ball = this.mBalls[i];this.collisionDetectingAndChangeSpeed(ball); // 碰撞边界的计算ball.move(); // 移动}final long stopTime = System.currentTimeMillis();final long runTime = stopTime - startTime;// 16毫秒执行一次this.postInvalidateDelayed(Math.abs(runTime - 16));}// 判断球是否碰撞碰撞边界public void collisionDetectingAndChangeSpeed(final Ball ball) {final int left = 0;final int top = 0;final int right = this.mWidth;final int bottom = this.mHeight;final float speedX = ball.vx;final float speedY = ball.vy;// 碰撞左右,X的速度取反。 speed的判断是防止重复检测碰撞,然后黏在墙上了=。=if (ball.left() <= left && speedX < 0) {ball.vx = -ball.vx;} else if (ball.top() <= top && speedY < 0) {ball.vy = -ball.vy;} else if (ball.right() >= right && speedX > 0) {ball.vx = -ball.vx;} else if (ball.bottom() >= bottom && speedY > 0) {ball.vy = -ball.vy;}}
}


2.热水气泡

/*** @author jiang yuhang* @date 2021-04-18 19:57*/
class Ball {// 半径@kotlin.jvm.JvmFieldvar radius = 0// 圆心@kotlin.jvm.JvmFieldvar cx = 0f// 圆心@kotlin.jvm.JvmFieldvar cy = 0f// X轴速度@kotlin.jvm.JvmFieldvar vx = 0f// Y轴速度@kotlin.jvm.JvmFieldvar vy = 0f@kotlin.jvm.JvmFieldvar paint: Paint? = null// 移动fun move() {//向角度的方向移动,偏移圆心cx += vxcy += vy}fun left(): Int {return (cx - radius).toInt()}fun right(): Int {return (cx + radius).toInt()}fun bottom(): Int {return (cy + radius).toInt()}fun top(): Int {return (cy - radius).toInt()}
}
/*** @author jiang yuhang* @date 2021-04-18 19:53*/
public class BallView extends View {final RandomColor randomColor = new RandomColor(); // 随机生成好看的颜色,github开源库。private final Random mRandom = new Random();private final int mCount = 5;   // 小球个数private final int minSpeed = 5; // 小球最小移动速度private final int maxSpeed = 15; // 小球最大移动速度public Ball[] mBalls = new Ball[this.mCount];   // 用来保存所有小球的数组private int maxRadius;  // 小球最大半径private int minRadius; // 小球最小半径private int mWidth = 200;private int mHeight = 200;public BallView(final Context context, final AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);this.mWidth = View.resolveSize(this.mWidth, widthMeasureSpec);this.mHeight = View.resolveSize(this.mHeight, heightMeasureSpec);this.setMeasuredDimension(this.mWidth, this.mHeight);this.maxRadius = this.mWidth / 12;this.minRadius = this.maxRadius / 2;// 初始化所有球(设置颜色和画笔, 初始化移动的角度)for (int i = 0; i < mBalls.length; i++) {this.mBalls[i] = getRandomBall();}}private Ball getRandomBall() {Ball mBall = new Ball();// 设置画笔setRandomBall(mBall);return mBall;}private void setRandomBall(Ball ball) {// 设置画笔final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setColor(randomColor.randomColor());paint.setStyle(Paint.Style.FILL);paint.setAlpha(180);paint.setStrokeWidth(0);ball.paint = paint;// 设置速度final float speedX = (this.mRandom.nextInt(this.maxSpeed - this.minSpeed + 1) + 5) / 10f;final float speedY = (this.mRandom.nextInt(this.maxSpeed - this.minSpeed + 1) + 5) / 10f;ball.vx = this.mRandom.nextBoolean() ? speedX : -speedX;ball.vy = -speedY;ball.radius = mRandom.nextInt(maxRadius + 1 - minRadius) + minRadius;ball.cx = mRandom.nextInt(mWidth - ball.radius) + ball.radius;ball.cy = mHeight - ball.radius;}@Overrideprotected void onDraw(final Canvas canvas) {final long startTime = System.currentTimeMillis();// 先画出所有圆for (int i = 0; i < this.mCount; i++) {final Ball ball = this.mBalls[i];canvas.drawCircle(ball.cx, ball.cy, ball.radius, ball.paint);}// 球碰撞边界for (int i = 0; i < this.mCount; i++) {collisionDetectingAndChangeSpeed(mBalls[i]); // 碰撞边界的计算mBalls[i].move(); // 移动}final long stopTime = System.currentTimeMillis();final long runTime = stopTime - startTime;// 16毫秒执行一次this.postInvalidateDelayed(Math.abs(runTime - 16));}// 判断球是否碰撞碰撞边界public void collisionDetectingAndChangeSpeed(Ball ball) {final int left = 0;final int top = 0;final int right = this.mWidth;final int bottom = this.mHeight;final float speedX = ball.vx;final float speedY = ball.vy;// 碰撞左右,X的速度取反。 speed的判断是防止重复检测碰撞,然后黏在墙上了=。=if (ball.left() <= left && speedX < 0) {ball.vx = -ball.vx;} else if (ball.top() <= top && speedY < 0) {setRandomBall(ball);} else if (ball.right() >= right && speedX > 0) {ball.vx = -ball.vx;}}
}


Android 气泡动画(自定义View类)相关推荐

  1. Android 粒子动画自定义View

    github仓库 其中用到了较多的random随机值 ParticleItem.java public class ParticleItem {private int x;//坐标点private i ...

  2. Android模仿淘宝语音输入条形动画,录音动画自定义View

    Android模仿淘宝语音输入条形动画自定义View,类似柱状音频,折线音频,音乐跳动,音频跳动,录音动画,语音输入效果 地址: https://github.com/xfans/VoiceWaveV ...

  3. Android中的自定义View以及绘图工具

    1.1自定义view的简介 为什么要使用自定义view 在Android开发中有很多业务场景,原生的控件是无法满足应用,并且经常也会遇到一个UI在多处 重复使用情况,那么就需要通过自定义View的方式 ...

  4. Android 完整的自定义View

    一.自定义View的分类 自定义View一共分为两大类,具体如下图: 二.具体介绍 & 使用场景 对于自定义View的类型介绍及使用场景如下图: 三.使用注意点 在使用自定义View时有很多注 ...

  5. android 点赞动画 自定义UI实现

    android 点赞动画 自定义UI实现 先看效果 FlowLikeView自定义UI /*** 点赞自定义控件*/ public class FlowLikeView extends Relativ ...

  6. android标尺自定义view,android尺子的自定义view——RulerView详解

    项目中用到自定义尺子的样式: 原效果为 因为跟自己要使用的view稍有不同 所以做了一些修改,修改的注释都放在代码中了,特此记录一下. 首先是一个自定义View: public class RuleV ...

  7. Android进阶之自定义View实战(二)九宫格手势解锁实现

    一.引言 在上篇博客Android进阶之自定义View实战(一)仿iOS UISwitch控件实现中我们主要介绍了自定义View的最基本的实现方法.作为自定义View的入门篇,仅仅介绍了Canvas的 ...

  8. Android开发之自定义view进行旋转动画

    老套路先上图: 整个view非常简单,我自定义view里面都有详细的注释说明 先看自定义view部分代码: package cn.xiayiye5.customizestudy.view;import ...

  9. android伸缩动画自定义,Android干货:自定义带动画的View

    对于一个自定义View来说,onMeasure只是用来计算View尺寸,onDraw()才是真正执行View的绘制,所以一般我们都需要重写onDraw()函数来绘制我们期望的UI界面,下面我以一个具体 ...

最新文章

  1. vs2010下使用ADO.NET Entity Data Model
  2. 太阳能工程联箱知识_暖通设计|太阳能热水系统设计参考手册(供参考)
  3. IDEA之过滤那些不重要的文件
  4. MySQL Server has gone away报错原因汇总
  5. S3C2440 IIS操作 uda134x录放音
  6. 计算机毕设-文献摘要,毕设摘要翻译,要人工翻译,不要电脑网站翻译的。
  7. 写给准备学习Linux的人
  8. xml 和android脚本之家,Android开发之XML文件解析的使用
  9. Redis 性能问题排查:slowlog 和排队延时
  10. 【廖雪峰官方网站/Java教程】设计模式(一)
  11. 用mapreduce 处理气象数据集
  12. 使用 SnakeYAML 解析 YAML
  13. 俄罗斯方块(C/C++)
  14. 第14期《学海无涯乐作舟》12月刊
  15. python-文件读写-OS-窗口控制
  16. 计算机专业群名有内涵,有内涵高大上的群名
  17. 免实名域名是什么意思?
  18. -2147483648 < 2147483647,为什么有的编译器运行结果为false?
  19. 计算机WPS二级备考攻略来啦~
  20. Python datetime.datetime.isoweekday和date.weekday()

热门文章

  1. SpringCloud 注册中心:Nacos 简介、安装和配置
  2. 代发工资直接理财 微信已经可以代替银行 而且更方便
  3. java static
  4. 如何使用python编程画图_建议收藏-超级详细的python画图教程
  5. 我是一个流氓软件线程
  6. 和硅谷AI专家一起走进美团,探索美团外卖背后的AI大脑
  7. 学会这10款AI绘画工具,你也可以成为插画师
  8. Matlab-图像处理及数字水印生成
  9. jQuery Validation Engine 表单验证
  10. 《论文阅读》EMOTIONFLOW: CAPTURE THE DIALOGUE LEVEL EMOTION TRANSITIONS