Android 的漂浮动画,下雪动画

少年乘勇气,百战过乌孙。这篇文章主要讲述Android 的漂浮动画,下雪动画相关的知识,希望能为你提供帮助。
因工作需要最近在研究了动画, 先看下效果:


Android 的漂浮动画,下雪动画

文章图片
Android 的漂浮动画,下雪动画

文章图片


Android 的漂浮动画,下雪动画

文章图片
Android 的漂浮动画,下雪动画

文章图片


1.先得了解下canvas.drawBitmap(mBitmap, mSrcRect, mDestRect, mBitPaint);
在绘制图片时, 使用, 参数分别, 图片bitmap,绘制bitmap自己的区域, 绘制bitmap在手机上显示位置区域, 画笔;
mSrcRect, mDestRect都是Rect(int left, int top, int right, int bottom) 的对象;
2.思路
a.漂浮的图片, 可能是小球, 星星, 雪花之类的, 根据需求, 选若干个不同小图片, 先称之他们漂浮的星星;
b.根据效果, 漂浮图片设置其实有关数据, 像坐标, 大小, 透明度, 移动速度进水, 移动方向等;
c.然后初始化以上数据, 生成批量小球, 进行绘制;
d.开设个线程或handle造成定时器, 来不断刷新, 同时修改漂浮星星属性,
3.代码
a.定义一个继承View的类, 初始化画笔, 所需若干星星, 设置不同速度

private void initPaint() { paint = new Paint(Paint.ANTI_ALIAS_FLAG); // 防抖动 paint.setDither(true); // 开启图像过滤 paint.setFilterBitmap(true); }

/** * 设置动画目标,三张大小不同, 样式不一, 为了美观 * init bitmap info */ private void initBitmapInfo() { 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(); }

//定义三种不同快慢的漂浮速度 private void initData(Context context) { mResources = getResources(); DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics(); mTotalWidth = dm.widthPixels; mTotalHeight = dm.heightPixels; Log.i(TAG, " mTotalWidth= " + mTotalWidth + " --1--mTotalHeight= " + mTotalHeight); //设置三个不同大小的速度值 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()); }

b.初始化星星, 因为在构造方法里把一些基本数据初始化结束后, 接着会进行测量, 我把初始化星星方法放在
onMeasure方法了

/** * 初始化星星信息 */ private void initStarInfo() {StarInfo starInfo = null; Random random = new Random(); for (int i = 0; i < mFloatCount; i+ + ) { // 获取星星大小比例 float starSize = getStarSize(0.4f, 0.8f); //小球的坐标 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.i(TAG, " xLocation = " + starInfo.xLocation + " --yLocation = " + starInfo.yLocation); Log.i(TAG, " stoneSize = " + starSize + " ---stoneAlpha = " + starInfo.alpha); // 初始化星星位置 starInfo.direction = getStarDirection(); mStarInfos.add(starInfo); } }

STAR_LOCATION[]数组的人为的确定星星占手机屏幕大小比例的位置, 自己试过随机生成一些数据, 但是有时就扎堆了, 应该找个手机屏幕上随机不重复生成点坐标的算法, 正在思考, 有会的, 给我说下, 学习下
c.设置星星的移动方向, 这里只是常态化的左右上下, 对角线的方向, 自己可以添加其他轨迹方向

/** * 不同移动轨迹, 除过左右上下, 也可以定义其他方向, 如对角线, 曲线之类的 * 初始化星星运行方向 */ private int getStarDirection() { int randomInt; Random random = new Random(); if(floatTyep= = 100){ randomInt = random.nextInt(3); }else { randomInt= floatTyep; } 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; case 4: direction = FREE_POINT; break; default: break; } return direction; }

d.重复绘制时, 修改小球的运动轨迹方向, 添加case类型, 比如一些正余弦轨迹, 在手机上菱形运行, 折线轨迹等;

private void resetStarFloat(StarInfo starInfo) { switch (starInfo.direction) { case LEFT: if (starInfo.xLocation < -20) { starInfo.xLocation = mTotalWidth; } else { starInfo.xLocation -= starInfo.speed; }break; case RIGHT: if (starInfo.xLocation > mTotalWidth+ 20) { starInfo.xLocation = 0; } else { starInfo.xLocation + = starInfo.speed; }break; case TOP: if (starInfo.yLocation < -20) { starInfo.yLocation = mTotalHeight; } else { starInfo.yLocation -= starInfo.speed; }break; case BOTTOM: if (starInfo.yLocation > mTotalHeight+ 30) { starInfo.yLocation = 0; } else { starInfo.yLocation + = starInfo.speed; } break; case FREE_POINT:if (starInfo.yLocation > mTotalHeight+ 30) { starInfo.yLocation = 0; } else { starInfo.yLocation + = starInfo.speed; }if (starInfo.xLocation < -20) { starInfo.xLocation = mTotalWidth; } else { starInfo.xLocation -= starInfo.speed; } break; default: break; } }


上面的20,30是随便加的, 是为了让星星跑到手机屏幕之外, 再重新进入界面, 否则直接运动到屏幕边界, 重新开始, 会闪的一下, 效果不好;
e.进行绘制
@ Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (int i = 0; i < mStarInfos.size(); i+ + ) { StarInfo starInfo = mStarInfos.get(i); drawStarDynamic(i, starInfo, canvas, paint); } }private void drawStarDynamic(int count, StarInfo starInfo, Canvas canvas, Paint paint) { resetStarFloat(starInfo); 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(); mStarOneSrcRect = new Rect(0, 0, mStarOneWidth, mStarOneHeight); 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(); }

f.定时重会, 实现动的效果
Handler handler= new Handler(){ @ Override public void handleMessage(Message msg) { super.handleMessage(msg); if(isRuning){ postInvalidate(); handler.sendMessageDelayed(Message.obtain(),50); } } };

public void startAnimationFloat(){ isRuning= true; handler.sendMessage(Message.obtain()); }public void stopAnimationFloat(){ isRuning= false; } public void restartAnimationFloat(){ startAnimationFloat(); }

基本就这些, 然后在activity布局里使用FloatView, 设置不同运动方向轨迹即可;

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_float); int typeKey = getIntent().getIntExtra(" type_key" , 0); FloatView startBtn = (FloatView) findViewById(R.id.float_btn); startBtn.setFloatType(FloatView.FREE_POINT); if(typeKey= = 1){ startBtn.setFloatType(FloatView.DEFAULT_TYPE); }else if(typeKey= = 2){ startBtn.setFloatType(FloatView.FREE_POINT); }else if(typeKey= = 3){ startBtn.setFloatType(FloatView.TOP); }else if(typeKey= = 4){ startBtn.setFloatType(FloatView.BOTTOM); }else if(typeKey= = 5){ startBtn.setFloatType(FloatView.LEFT); }else if(typeKey= = 6){ startBtn.setFloatType(FloatView.RIGHT); } startBtn.startAnimationFloat(); }

以上的部分关键代码和思路学习于http://blog.csdn.net/tianjian4592/article/details/45157787, 此人很牛, 动画绘制这块文章写的很细, 容易理解, 建议去看下, 自己稍作修改, 调通, 作为笔记, 来实现工作需求;
源码

【Android 的漂浮动画,下雪动画】

    推荐阅读