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,此人很牛,動畫繪製這塊文章寫的很細,容易理解,建議去看下,自己稍作修改,調通,作為筆記,來實現工作需求;
原始碼