Android自定义View实现多片叶子旋转滑动(五)

上一篇《Android 自定义View(四) 叶子飘动+旋转效果》实现了单片叶子的滑动及旋转,下面实现多片叶子的滑动旋转功能

实现思路比较简单,就是添加一个叶子Leaf类,储存每片叶子的信息,

然后随机产生叶子的坐标及旋转角度,最后实时获取每片叶子信息,添加到画布中

1、Leaf.java 叶子类

private class Leaf { // 叶子的坐标 float x, y; // 旋转角度 int rotateAngle; // 起始时间(ms) long startTime; }

2、初始化每片叶子的信息,然后保存到list中

//使叶子初始时间有间隔 int addTime; private Leaf getLeaf() { Random random = new Random(); Leaf leaf = new Leaf(); //随机初始化叶子初始角度 leaf.rotateAngle = random.nextInt(360); //随机初始化叶子启动时间 addTime += random.nextInt((int) (cycleTime)); leaf.startTime = System.currentTimeMillis() + cycleTime + addTime; return leaf; } private List<Leaf> getLeafs(int leafSize) { List<Leaf> list = new LinkedList<Leaf>(); for (int i=0; i<leafSize; i++) { list.add(getLeaf()); } return list; }

3、接下去就是改写getLocation()及getRotate()方法,使其返回每片叶子的坐标及旋转角度

//获取每片叶子在XY轴上的滑动值 private void getLocation(Leaf leaf) { float betweenTime = leaf.startTime - System.currentTimeMillis(); //周期结束再加一个cycleTime if(betweenTime < 0) { leaf.startTime = System.currentTimeMillis() + cycleTime + new Random().nextInt((int) (cycleTime)); betweenTime = cycleTime; } //通过时间差计算出叶子的坐标 float fraction = (float) betweenTime / cycleTime; float x = (int)(width * fraction); leaf.x = x; float w = (float) ((float) 2 * Math.PI / width); int y = (int) (18 * Math.sin(w * x)) + (height-mLeafHeight)/2; leaf.y = y; } //获取每片叶子的旋转角度 private void getRotate(Leaf leaf) { float scale = ((leaf.startTime - System.currentTimeMillis())%cycleTime)/ (float)cycleTime; int rotate = (int)(scale * 360); leaf.rotateAngle = rotate; }

4、在onDraw()方法中,画出每片叶子

@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //画叶子 int size = leafList.size(); for (int i=0; i<size; i++) { Leaf leaf = leafList.get(i); //获取叶子坐标 getLocation(leaf); //获取叶子旋转角度 getRotate(leaf); canvas.save(); Matrix matrix = new Matrix(); //设置滑动 matrix.postTranslate(leaf.x, leaf.y); //设置旋转 matrix.postRotate(leaf.rotateAngle, leaf.x + mLeafWidth / 2, leaf.y + mLeafHeight / 2); //添加叶子到画布 canvas.drawBitmap(mLeafBitmap, matrix, new Paint()); canvas.restore(); } //调用onDraw()重复滑动 postInvalidate(); }

完整代码:

public class LeafView extends View { private String TAG = "--------LeafView"; private Resources mResources; //背景图、叶子 private Bitmap mLeafBitmap, bgBitmap; //整个控件的宽度和高度 private int width, height; private Paint bgPaint; private RectF bgRect; private Rect bgDestRect; //存放叶子lsit private List<Leaf> leafList; //叶子的宽和高 private int mLeafWidth, mLeafHeight; //叶子滑动一周的时间5秒 private final static long cycleTime = 5000; //叶子数量 private final static int leafNumber = 5; public LeafView(Context context, AttributeSet attrs) { super(context, attrs); mResources = getResources(); mLeafBitmap = ((BitmapDrawable) mResources.getDrawable(R.drawable.leaf, null)).getBitmap(); mLeafWidth = mLeafBitmap.getWidth(); mLeafHeight = mLeafBitmap.getHeight() bgBitmap = ((BitmapDrawable) mResources.getDrawable(R.drawable.leaf_kuang, null)).getBitmap(); bgPaint = new Paint(); bgPaint.setColor(mResources.getColor(R.color.bg_color)); //获取所有叶子的信息,放入list leafList = getLeafs(leafNumber); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); width = w; height = h; bgDestRect = new Rect(0, 0 , width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); bgRect = new RectF(0, 0 , width, height); //画背景颜色到画布 canvas.drawRect(bgRect, bgPaint); //画背景图片到画布 canvas.drawBitmap(bgBitmap, null, bgDestRect, null); //画叶子 int size = leafList.size(); for (int i=0; i<size; i++) { Leaf leaf = leafList.get(i); //获取叶子坐标 getLocation(leaf); //获取叶子旋转角度 getRotate(leaf); canvas.save(); Matrix matrix = new Matrix(); //设置滑动 matrix.postTranslate(leaf.x, leaf.y); //设置旋转 matrix.postRotate(leaf.rotateAngle, leaf.x + mLeafWidth / 2, leaf.y + mLeafHeight / 2); //添加叶子到画布 canvas.drawBitmap(mLeafBitmap, matrix, new Paint()); canvas.restore(); } //调用onDraw()重复滑动 postInvalidate(); } //获取每片叶子在XY轴上的滑动值 private void getLocation(Leaf leaf) { float betweenTime = leaf.startTime - System.currentTimeMillis(); //周期结束再加一个cycleTime if(betweenTime < 0) { leaf.startTime = System.currentTimeMillis() + cycleTime + new Random().nextInt((int) (cycleTime)); betweenTime = cycleTime; } //通过时间差计算出叶子的坐标 float fraction = (float) betweenTime / cycleTime; float x = (int)(width * fraction); leaf.x = x; float w = (float) ((float) 2 * Math.PI / width); int y = (int) (18 * Math.sin(w * x)) + (height-mLeafHeight)/2; leaf.y = y; } //获取每片叶子的旋转角度 private void getRotate(Leaf leaf) { float scale = ((leaf.startTime - System.currentTimeMillis())%cycleTime)/ (float)cycleTime; int rotate = (int)(scale * 360); leaf.rotateAngle = rotate; } private class Leaf { // 叶子的坐标 float x, y; // 旋转角度 int rotateAngle; // 起始时间(ms) long startTime; } private List<Leaf> getLeafs(int leafSize) { List<Leaf> list = new LinkedList<Leaf>(); for (int i=0; i<leafSize; i++) { list.add(getLeaf()); } return list; } //使叶子初始时间有间隔 int addTime; private Leaf getLeaf() { Random random = new Random(); Leaf leaf = new Leaf(); leaf.rotateAngle = random.nextInt(360); addTime += random.nextInt((int) (cycleTime)); leaf.startTime = System.currentTimeMillis() + cycleTime + addTime; return leaf; } }

这里还有很多瑕疵,比如叶子的滑动范围覆盖了边框等等

需要图片等信息的可以从下面的Github地址下载,不过原文比较复杂

参考 https://github.com/Ajian-studio/GALeafLoading

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

时间: 2024-10-10 15:40:04

Android自定义View实现多片叶子旋转滑动(五)的相关文章

Android自定义View实现飘动的叶子效果(三)

上一篇对自定义View及一些方法有所了解,下面做一个简单的叶子飘动的例子 主要技术点 1.添加背景图片canvas.drawBitmap() 2.Matrix动画类 3.Matrix添加到画布上 步骤 1.添加黄色背景颜色 public LeafView(Context context, AttributeSet attrs) { super(context, attrs); bgPaint = new Paint(); bgPaint.setColor(mResources.getColor(

Android自定义View之圆形进度条总结

最近撸了一个圆形进度条的开源项目,算是第一次完完整整的使用自定义 View .在此对项目开发思路做个小结,欢迎大家 Star 和 Fork. 该项目总共实现了三种圆形进度条效果 CircleProgress:圆形进度条,可以实现仿 QQ 健康计步器的效果,支持配置进度条背景色.宽度.起始角度,支持进度条渐变 DialProgress:类似 CircleProgress,但是支持刻度 WaveProgress:实现了水波纹效果的圆形进度条,不支持渐变和起始角度配置,如需此功能可参考 CircleP

Android自定义view实现阻尼效果的加载动画_Android

效果: 需要知识: 1. 二次贝塞尔曲线 2. 动画知识 3. 基础自定义view知识 先来解释下什么叫阻尼运动 阻尼振动是指,由于振动系统受到摩擦和介质阻力或其他能耗而使振幅随时间逐渐衰减的振动,又称减幅振动.衰减振动.[1] 不论是弹簧振子还是单摆由于外界的摩擦和介质阻力总是存在,在振动过程中要不断克服外界阻力做功,消耗能量,振幅就会逐渐减小,经过一段时间,振动就会完全停下来.这种振幅随时间减小的振动称为阻尼振动.因为振幅与振动的能量有关,阻尼振动也就是能量不断减少的振动.阻尼振动是非简谐运

Android自定义VIew实现卫星菜单效果浅析_Android

 一 概述: 最近一直致力于Android自定义VIew的学习,主要在看<android群英传>,还有CSDN博客鸿洋大神和wing大神的一些文章,写的很详细,自己心血来潮,学着写了个实现了类似卫星效果的一个自定义的View,分享到博客上,望各位指点一二.写的比较粗糙,见谅.(因为是在Linux系统下写的,效果图我直接用手机拍的,难看,大家讲究下就看个效果,勿喷). 先来看个效果图,有点不忍直视: 自定义VIew准备: (1)创建继承自View的类; (2)重写构造函数; (3)定义属性. (

Android自定义View之酷炫圆环(二)_Android

先看下最终的效果 静态: 动态: 一.开始实现 新建一个DoughnutProgress继承View public class DoughnutProgress extends View { } 先给出一些常量.变量以及公共方法的代码,方便理解后面的代码     private static final int DEFAULT_MIN_WIDTH = 400; //View默认最小宽度 private static final int RED = 230, GREEN = 85, BLUE =

Android自定义View过程解析_Android

Android自定义的view,主要是继承view,然后实现ondraw这个方法,来进行绘制. 1. 编写自己的自定义view 2. 加入逻辑线程 3. 提取和封装自定义view 4. 利用xml中定义样式来影响显示效果 一.编写自定义的view1.在xml中使用自己的view <!-- 可以使用view的公共属性,例如背景 --> <com.niuli.view.MyView android:layout_width="match_parent" android:l

Android自定义view制作绚丽的验证码_Android

废话不多说了,先给大家展示下自定义view效果图,如果大家觉得还不错的话,请继续往下阅读. 怎么样,这种验证码是不是很常见呢,下面我们就自己动手实现这种效果,自己动手,丰衣足食,哈哈~ 一. 自定义view的步骤 自定义view一直被认为android进阶通向高手的必经之路,其实自定义view好简单,自定义view真正难的是如何绘制出高难度的图形,这需要有好的数学功底(后悔没有好好学数学了~),因为绘制图形经常要计算坐标点及类似的几何变换等等.自定义view通常只需要以下几个步骤: 写一个类继承

Android自定义View 实现闹钟唤起播放闹钟铃声功能_Android

先上图看一下闹钟唤期页面的效果 实现的功能: 1:转动的图片根据天气情况更换 2:转动时间可以设置,转动结束,闹铃声音就结束 3:光圈颜色渐变效果 直接上代码啦: package com.yuekong.sirius.extension.customview; import android.animation.Animator; import android.animation.ValueAnimator; import android.content.Context; import andro

Android自定义view制作绚丽的验证码

废话不多说了,先给大家展示下自定义view效果图,如果大家觉得还不错的话,请继续往下阅读. 怎么样,这种验证码是不是很常见呢,下面我们就自己动手实现这种效果,自己动手,丰衣足食,哈哈~ 一. 自定义view的步骤 自定义view一直被认为android进阶通向高手的必经之路,其实自定义view好简单,自定义view真正难的是如何绘制出高难度的图形,这需要有好的数学功底(后悔没有好好学数学了~),因为绘制图形经常要计算坐标点及类似的几何变换等等.自定义view通常只需要以下几个步骤: 写一个类继承