因工作需要最近在研究了动画,先看下效果:
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,此人很牛,动画绘制这块文章写的很细,容易理解,建议去看下,自己稍作修改,调通,作为笔记,来实现工作需求;
源码