Android 漂浮类动效的分析与实现!

尊重原创,欢迎转载,转载请注明: FROM GA_studio

注:因部分原因,本篇主要讲解动效分析的思路,不提供源码下载,请见谅 … …

上一篇只讲了Canvas中的drawBitmap方法,并且还说的这个方法好像很腻害、能做出很多牛逼效果的样子,接下来这篇文章只是为了作为上一篇文章的一个小栗子,进一步拓展大家利用drawBitmap 完成动效的思路!

好了,先上失真的不能再失真的效果图:

咱们先一起来分析下上面的效果:

假定这是你刚从UE 或动效射鸡湿手里拿到上面的动效设计图,映入眼帘的是苍茫的星空,漂浮的星球营造出的深邃、浩瀚的宇宙,好了,不多BB了,针对上图你会想到什么样的实现方案?

1. 有些同学可能会想到创建对应数量个ImageView,然后针对每一个ImageView使用 Animation或Animator 去做对应的移动效果;

2.采用自己绘制的方式进行实现,不就是漂浮的星球吗,咱都给画出来;

不用说,上面第二种方案肯定更可取,第一种方案有以下几个缺陷:

1. 创建的view 个数过多,性能太差;

2. 灵活性太差,比如UE或产品要增加或减少星球数量,都会是个麻烦事儿;

3. 对每一个view做移动动画,开销太大还不太可控或修改;

针对于此,咱们坚定不移的走自己绘制完成漂浮动效的路线;

既然要绘制,那首先得拿到星球的位图,根据星球的种类拿到所有的位图:

/*** init bitmap info*/private void initBitmapInfo() {mBackBitmap = ((BitmapDrawable) mResources.getDrawable(R.drawable.back)).getBitmap();mBackWidth = mBackBitmap.getWidth();mBackHeight = mBackBitmap.getHeight();mStarOne = ((BitmapDrawable) mResources.getDrawable(R.drawable.star2)).getBitmap();mStarOneWidth = mStarOne.getWidth();mStarOneHeight = mStarOne.getHeight();mStarTwo = ((BitmapDrawable) mResources.getDrawable(R.drawable.star1)).getBitmap();mStarTwoWidth = mStarTwo.getWidth();mStarTwoHeight = mStarTwo.getHeight();mStarThree = ((BitmapDrawable) mResources.getDrawable(R.drawable.star3)).getBitmap();mStarThreeWidth = mStarThree.getWidth();mStarThreeHeight = mStarThree.getHeight();}上面拿到了背景和三种类型星球的位图,根据上面的效果,我们来分析下,有哪些特征性数据:

1. 同一种星球有大有小;

2. 彼此之间有透明度的差别;

3. 漂浮的方向不一样;

4. 漂浮的速度不一样;

5. 每个星球都得有自己的位置;

我们暂且只分析这么多,基于此,我们抽象出星球对象:

/*** 星球* @author AJian*/private class StarInfo {// 缩放比例float sizePercent;// x位置int xLocation;// y位置int yLocation;// 透明度float alpha;// 漂浮方向int direction;// 漂浮速度int speed;}

为了得到上面的部分数据,我们先写一些数据或方法:

1. 为了初始化星球的位置,我们用数组先定义一批星球的位置(基于view宽高的比例),当然大家也可以随机,只是随机可能出现扎堆情况:

private static final float[][] STAR_LOCATION = new float[][] {{0.5f, 0.2f}, {0.68f, 0.35f}, {0.5f, 0.05f},{0.15f, 0.15f}, {0.5f, 0.5f}, {0.15f, 0.8f},{0.2f, 0.3f}, {0.77f, 0.4f}, {0.75f, 0.5f},{0.8f, 0.55f}, {0.9f, 0.6f}, {0.1f, 0.7f},{0.1f, 0.1f}, {0.7f, 0.8f}, {0.5f, 0.6f}};

2. 获取星球大小的方法(基于原始Bitmap缩放比例):

/*** 获取星球大小*/private float getStarSize(float start, float end) {float nextFloat = (float) Math.random();if (start < nextFloat && nextFloat < end) {return nextFloat;} else {// 如果不处于想要的数据段,则再随机一次,因为不断递归有风险return (float) Math.random();}}

3. 定义三种不同快慢的漂浮速度:

mFloatTransLowSpeed = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0.5f,mResources.getDisplayMetrics());mFloatTransMidSpeed = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0.75f,mResources.getDisplayMetrics());mFloatTransFastSpeed = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1f,mResources.getDisplayMetrics());4. 获取星球漂浮方向的方法: /*** 初始化星球运行方向*/private int getStarDirection() {Random random = new Random();int randomInt = random.nextInt(4);int direction = 0;switch (randomInt) {case 0:direction = LEFT;break;case 1:direction = RIGHT;break;case 2:direction = TOP;break;case 3:direction = BOTTOM;break;default:break;}return direction;}

有了上面的数据和方法,我们首先初始化一定数量的星球数据:

/*** 初始化星球信息*/private void initStarInfo() {StarInfo starInfo = null;Random random = new Random();for (int i = 0; i < mStarCount; i++) {// 获取星球大小比例float starSize = getStarSize(0.4f, 0.9f);// 初始化星球大小float[] starLocation = STAR_LOCATION[i];starInfo = new StarInfo();starInfo.sizePercent = starSize;// 初始化漂浮速度int randomSpeed = random.nextInt(3);switch (randomSpeed) {case 0:starInfo.speed = mFloatTransLowSpeed;break;case 1:starInfo.speed = mFloatTransMidSpeed;break;case 2:starInfo.speed = mFloatTransFastSpeed;break;default:starInfo.speed = mFloatTransMidSpeed;break;}// 初始化星球透明度starInfo.alpha = getStarSize(0.3f, 0.8f);// 初始化星球位置starInfo.xLocation = (int) (starLocation[0] * mTotalWidth);starInfo.yLocation = (int) (starLocation[1] * mTotalHeight);log("xLocation = " + starInfo.xLocation + "–yLocation = "+ starInfo.yLocation);log("stoneSize = " + starSize + "—stoneAlpha = "+ starInfo.alpha);// 初始化星球位置starInfo.direction = getStarDirection();mStarInfos.add(starInfo);}}有了这些数据,我们已经可以将星球绘制在屏幕上: private void drawStarDynamic(int count, StarInfo starInfo,Canvas canvas, Paint paint) {float starAlpha = starInfo.alpha;int xLocation = starInfo.xLocation;int yLocation = starInfo.yLocation;float sizePercent = starInfo.sizePercent;xLocation = (int) (xLocation / sizePercent);yLocation = (int) (yLocation / sizePercent);Bitmap bitmap = null;Rect srcRect = null;Rect destRect = new Rect();if (count % 3 == 0) {bitmap = mStarOne;srcRect = mStarOneSrcRect;destRect.set(xLocation, yLocation,xLocation + mStarOneWidth, yLocation+ mStarOneHeight);} else if (count % 2 == 0) {bitmap = mStarThree;srcRect = mStarThreeSrcRect;destRect.set(xLocation, yLocation, xLocation+ mStarThreeWidth, yLocation + mStarThreeHeight);} else {bitmap = mStarTwo;srcRect = mStarTwoSrcRect;destRect.set(xLocation, yLocation, xLocation+ mStarTwoWidth, yLocation + mStarTwoHeight);}paint.setAlpha((int) (starAlpha * 255));canvas.save();canvas.scale(sizePercent, sizePercent);canvas.drawBitmap(bitmap, srcRect, destRect, paint);canvas.restore();}接下来要考虑的只是如何让星球动起来,有了以上数据和思路,相信大家让星球动起来就不是难事了,只需要根据星球运动的方向,每次重绘的时候将星球的x、y增加或减小对应大小即可:private void resetStarFloat(StarInfo starInfo) {switch (starInfo.direction) {case LEFT:starInfo.xLocation -= starInfo.speed;break;case RIGHT:starInfo.xLocation += starInfo.speed;break;case TOP:starInfo.yLocation -= starInfo.speed;break;case BOTTOM:starInfo.yLocation += starInfo.speed;break;default:break;}}这时候有部分同学可能会说了,尼玛, 星球直接移出屏幕了怎么办,这个问题相信大家都能解决,只是一个值的判断和重新修复,不再多言;

最后针对这一类动效小谈一下,其实很大一部分效果和上面的动效是类似的,不信?我举几个栗子:

1. 雪花飘落的效果

尼玛,扯淡呢!雪花和这类似?雪花从上往下飞,并且还旋转;

找一个让心里安静和干净的地方,自己变得跟水晶一般透明,

Android 漂浮类动效的分析与实现!

相关文章:

你感兴趣的文章:

标签云: