少年乘勇气,百战过乌孙。这篇文章主要讲述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 的漂浮动画,下雪动画】
推荐阅读
- Android UI(矢量图使用)
- Android中活动条ActionBar的详细使用
- Android Material Design 系列之 SnackBar详解
- Android程序中如何执行shell脚本
- Android 性能测试——Heap Viewer 工具
- Android中的接口回调技术
- Android开发之MVP模式的使用
- Android SDK Android NDK Android Studio 官方下载地址
- Android中通过ActionBar为标题栏添加搜索以及分享视窗