Android(安卓)星体动效实现
16lz
2021-01-26
本文在理解 http://blog.csdn.net/tianjian4592/article/details/45157787
的基础上,进行了部分优化,源码在http://download.csdn.net/detail/xiaomu123456/9685975,主要看StarActivity就行了
实际效果如下:
首先,要实现这样一幅动效图,基本上就是两个步骤: 第一,在背景上确定物体(图片中的星体,流星)的初始位置 第二,使物体进行移动,在此过程中要实时更新物体的参数信息,比如大小,亮度等
其次,对于图中的每一个实体对象,都需要以下基本信息 1.方向2.速度3.形态4.大小5.位置6.物体宽度,高度7透明度等
具体定义如下: public class StarInfo {
//方向 public final static int LEFT = 0; public final static int RIGHT = 1; public final static int TOP = 2; public final static int BOTTOM = 3; public static final int RIGHT_BOTTOM = 4;
//速度,实际上相当于在背景上移动的距离(像素) public static final int LOW_SPEED = 1; public static final int MID_SPEED = 2; public static final int HIGTH_SPEED = 3;
public Bitmap mBitmap;//形态 public int mWidth;//物体宽度 public int mHeight;//物体高度 public Rect mSrcRect;//自身所占的矩形区域
// 大小 float sizePercent; // x位置 int xLocation; // y位置 int yLocation; // 透明度 float alpha; // 漂浮方向 int direction; // 漂浮速度 int speed; }
在图中第一种对象为星体,定义如下:
public class CircleStar extends StarInfo {
public static final int STAR_TYPE_1 = 101; public static final int STAR_TYPE_2 = 102; public static final int STAR_TYPE_3 = 103;
private Context mContext;
public CircleStar(Context context,int type){ this.mContext = context; initBitmap(type); }
public void initBitmap( int type ){ switch (type){ case STAR_TYPE_1: mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.small_start1)) .getBitmap(); break; case STAR_TYPE_2: mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.small_star2)) .getBitmap(); break; case STAR_TYPE_3: mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.small_star2)) .getBitmap(); break; default: mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.small_start1)) .getBitmap(); break; } mWidth = mBitmap.getWidth(); mHeight = mBitmap.getHeight(); mSrcRect = new Rect(0,0, mWidth, mHeight); }
}
在图中第二种对象为流星,定义如下:
public class FallingStar extends StarInfo {
private Context mContext;
public FallingStar(Context context){ this.mContext = context; initBitmap(); }
public void initBitmap(){ mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.light_star_1)) .getBitmap(); mWidth = mBitmap.getWidth(); mHeight = mBitmap.getHeight(); mSrcRect = new Rect(0,0, mWidth, mHeight); } } 最后在view中展示动画效果:
public class StarView extends View {
private final static int mStarCount = 200;//背景图添加了200个实体对象 private List mStarInfos = new ArrayList(); private Bitmap mBackgoundBitmap;//背景图片 private int mBackgoundWidth; private int mBackgoundHeight; private int mTotalWidth,mTotalHeight;//实际上是背景宽度和高度 private Paint mPaint;
public StarView(Context context) { this(context,null); }
public StarView(Context context, AttributeSet attrs) { this(context, attrs,0); }
public StarView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initData(); initStarInfo(); }
private void initData() { //背景 mBackgoundBitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.bg_star)) .getBitmap(); mBackgoundWidth = mBackgoundBitmap.getWidth(); mBackgoundHeight = mBackgoundBitmap.getHeight(); mTotalWidth = mBackgoundWidth; mTotalHeight = mBackgoundHeight; this.setBackgroundResource(R.drawable.bg_star);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setFilterBitmap(true); mPaint.setDither(true); }
/** * 获取星球大小 */ private float getStarSize(float start, float end) { float nextFloat = (float) Math.random(); if (start < nextFloat && nextFloat < end) { return nextFloat; } else { // 如果不处于想要的数据段,则再随机一次,因为不断递归有风险 return (float) Math.random(); } }
/** * 初始化星球信息 */ private void initStarInfo() {
StarInfo starInfo = null; for (int i = 0; i < mStarCount; i++) {
if( i % 2 == 0 ){ starInfo = new CircleStar(getContext(),CircleStar.STAR_TYPE_1);//星体1 }else if(i % 3 == 0){ starInfo = new CircleStar(getContext(),CircleStar.STAR_TYPE_2);//星体2 }else{ starInfo = new FallingStar(getContext());//流星 }
//共有属性 starInfo.sizePercent = getStarSize(0.1f, 0.2f); getStarSpeed(starInfo); starInfo.alpha = getStarSize(0.3f, 0.5f); starInfo.xLocation = (int) (getStarSize(0f,1f) * mTotalWidth); starInfo.yLocation = (int) (getStarSize(0f,1f) * mTotalHeight);
if( starInfo instanceof FallingStar ){ starInfo.direction = StarInfo.RIGHT_BOTTOM; }else { starInfo.direction = getStarDirection(); } mStarInfos.add(starInfo); } }
/** *在画布上画出star */ private void drawStarDynamic(StarInfo starInfo, Canvas canvas, Paint paint) { int xLocation = (int) ( starInfo.xLocation / starInfo.sizePercent); int yLocation = (int) ( starInfo.yLocation / starInfo.sizePercent);
Bitmap bitmap = starInfo.mBitmap; Rect srcRect = starInfo.mSrcRect; Rect destRect = new Rect(); destRect.set(xLocation, yLocation, xLocation + starInfo.mWidth, yLocation + starInfo.mHeight);
paint.setAlpha((int) (starInfo.alpha * 255)); canvas.save(); canvas.scale(starInfo.sizePercent, starInfo.sizePercent); canvas.drawBitmap(bitmap, srcRect, destRect, paint); canvas.restore();
}
/** *改变star的参数信息(比如速度,透明度,大小等),在画布上移动star */ private void resetStarFloat(StarInfo starInfo) { switch (starInfo.direction) { case StarInfo.LEFT: starInfo.xLocation -= starInfo.speed; if( starInfo.xLocation <= 0 ){ starInfo.direction = StarInfo.RIGHT; } break; case StarInfo.RIGHT: starInfo.xLocation += starInfo.speed; if( starInfo.xLocation >= mTotalWidth ){ starInfo.direction = StarInfo.LEFT; } break; case StarInfo.TOP: starInfo.yLocation -= starInfo.speed; if( starInfo.yLocation <= 0 ){ starInfo.direction = StarInfo.BOTTOM; } break; case StarInfo.BOTTOM: starInfo.yLocation += starInfo.speed; if( starInfo.yLocation >= mTotalHeight ){ starInfo.direction = StarInfo.TOP; } break; case StarInfo.RIGHT_BOTTOM: starInfo.xLocation += starInfo.speed; starInfo.yLocation += starInfo.speed; starInfo.alpha += 0.003; starInfo.sizePercent += 0.003; if( starInfo.xLocation >= mTotalWidth ){ starInfo.xLocation = 0; starInfo.sizePercent = 0.1f; starInfo.alpha = getStarSize(0.0f,0.3f); }else if( starInfo.yLocation >= mTotalHeight ){ starInfo.yLocation = 0; starInfo.sizePercent = 0.1f; starInfo.alpha = getStarSize(0.0f,0.3f); } if( starInfo.alpha >= 1.0 ){ starInfo.alpha = 1; } if( starInfo.sizePercent >= 0.6 ){ starInfo.sizePercent = 0.6f; }
break; default: break; } }
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); }
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (int i = 0; i < mStarInfos.size(); i++) { drawStarDynamic(mStarInfos.get(i), canvas, mPaint); resetStarFloat(mStarInfos.get(i)); } postInvalidate(); }
/** * 初始化漂浮速度 */ private int getStarSpeed(StarInfo starInfo){ Random random = new Random(); int randomSpeed = random.nextInt(3); switch (randomSpeed) { case 0: starInfo.speed = StarInfo.LOW_SPEED; break; case 1: starInfo.speed = StarInfo.MID_SPEED; break; case 2: starInfo.speed = StarInfo.HIGTH_SPEED; break; default: starInfo.speed = StarInfo.MID_SPEED; break; } return starInfo.speed; }
/** * 初始化星球运行方向 */ public int getStarDirection() { Random random = new Random(); int randomInt = random.nextInt(4); int direction = 0; switch (randomInt) { case 0: direction = StarInfo.LEFT; break; case 1: direction = StarInfo.RIGHT; break; case 2: direction = StarInfo.TOP; break; case 3: direction = StarInfo.BOTTOM; break;
default: break; } return direction; }
}
的基础上,进行了部分优化,源码在http://download.csdn.net/detail/xiaomu123456/9685975,主要看StarActivity就行了
实际效果如下:
首先,要实现这样一幅动效图,基本上就是两个步骤: 第一,在背景上确定物体(图片中的星体,流星)的初始位置 第二,使物体进行移动,在此过程中要实时更新物体的参数信息,比如大小,亮度等
其次,对于图中的每一个实体对象,都需要以下基本信息 1.方向2.速度3.形态4.大小5.位置6.物体宽度,高度7透明度等
具体定义如下: public class StarInfo {
//方向 public final static int LEFT = 0; public final static int RIGHT = 1; public final static int TOP = 2; public final static int BOTTOM = 3; public static final int RIGHT_BOTTOM = 4;
//速度,实际上相当于在背景上移动的距离(像素) public static final int LOW_SPEED = 1; public static final int MID_SPEED = 2; public static final int HIGTH_SPEED = 3;
public Bitmap mBitmap;//形态 public int mWidth;//物体宽度 public int mHeight;//物体高度 public Rect mSrcRect;//自身所占的矩形区域
// 大小 float sizePercent; // x位置 int xLocation; // y位置 int yLocation; // 透明度 float alpha; // 漂浮方向 int direction; // 漂浮速度 int speed; }
在图中第一种对象为星体,定义如下:
public class CircleStar extends StarInfo {
public static final int STAR_TYPE_1 = 101; public static final int STAR_TYPE_2 = 102; public static final int STAR_TYPE_3 = 103;
private Context mContext;
public CircleStar(Context context,int type){ this.mContext = context; initBitmap(type); }
public void initBitmap( int type ){ switch (type){ case STAR_TYPE_1: mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.small_start1)) .getBitmap(); break; case STAR_TYPE_2: mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.small_star2)) .getBitmap(); break; case STAR_TYPE_3: mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.small_star2)) .getBitmap(); break; default: mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.small_start1)) .getBitmap(); break; } mWidth = mBitmap.getWidth(); mHeight = mBitmap.getHeight(); mSrcRect = new Rect(0,0, mWidth, mHeight); }
}
在图中第二种对象为流星,定义如下:
public class FallingStar extends StarInfo {
private Context mContext;
public FallingStar(Context context){ this.mContext = context; initBitmap(); }
public void initBitmap(){ mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.drawable.light_star_1)) .getBitmap(); mWidth = mBitmap.getWidth(); mHeight = mBitmap.getHeight(); mSrcRect = new Rect(0,0, mWidth, mHeight); } } 最后在view中展示动画效果:
public class StarView extends View {
private final static int mStarCount = 200;//背景图添加了200个实体对象 private List
public StarView(Context context) { this(context,null); }
public StarView(Context context, AttributeSet attrs) { this(context, attrs,0); }
public StarView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initData(); initStarInfo(); }
private void initData() { //背景 mBackgoundBitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.bg_star)) .getBitmap(); mBackgoundWidth = mBackgoundBitmap.getWidth(); mBackgoundHeight = mBackgoundBitmap.getHeight(); mTotalWidth = mBackgoundWidth; mTotalHeight = mBackgoundHeight; this.setBackgroundResource(R.drawable.bg_star);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setFilterBitmap(true); mPaint.setDither(true); }
/** * 获取星球大小 */ private float getStarSize(float start, float end) { float nextFloat = (float) Math.random(); if (start < nextFloat && nextFloat < end) { return nextFloat; } else { // 如果不处于想要的数据段,则再随机一次,因为不断递归有风险 return (float) Math.random(); } }
/** * 初始化星球信息 */ private void initStarInfo() {
StarInfo starInfo = null; for (int i = 0; i < mStarCount; i++) {
if( i % 2 == 0 ){ starInfo = new CircleStar(getContext(),CircleStar.STAR_TYPE_1);//星体1 }else if(i % 3 == 0){ starInfo = new CircleStar(getContext(),CircleStar.STAR_TYPE_2);//星体2 }else{ starInfo = new FallingStar(getContext());//流星 }
//共有属性 starInfo.sizePercent = getStarSize(0.1f, 0.2f); getStarSpeed(starInfo); starInfo.alpha = getStarSize(0.3f, 0.5f); starInfo.xLocation = (int) (getStarSize(0f,1f) * mTotalWidth); starInfo.yLocation = (int) (getStarSize(0f,1f) * mTotalHeight);
if( starInfo instanceof FallingStar ){ starInfo.direction = StarInfo.RIGHT_BOTTOM; }else { starInfo.direction = getStarDirection(); } mStarInfos.add(starInfo); } }
/** *在画布上画出star */ private void drawStarDynamic(StarInfo starInfo, Canvas canvas, Paint paint) { int xLocation = (int) ( starInfo.xLocation / starInfo.sizePercent); int yLocation = (int) ( starInfo.yLocation / starInfo.sizePercent);
Bitmap bitmap = starInfo.mBitmap; Rect srcRect = starInfo.mSrcRect; Rect destRect = new Rect(); destRect.set(xLocation, yLocation, xLocation + starInfo.mWidth, yLocation + starInfo.mHeight);
paint.setAlpha((int) (starInfo.alpha * 255)); canvas.save(); canvas.scale(starInfo.sizePercent, starInfo.sizePercent); canvas.drawBitmap(bitmap, srcRect, destRect, paint); canvas.restore();
}
/** *改变star的参数信息(比如速度,透明度,大小等),在画布上移动star */ private void resetStarFloat(StarInfo starInfo) { switch (starInfo.direction) { case StarInfo.LEFT: starInfo.xLocation -= starInfo.speed; if( starInfo.xLocation <= 0 ){ starInfo.direction = StarInfo.RIGHT; } break; case StarInfo.RIGHT: starInfo.xLocation += starInfo.speed; if( starInfo.xLocation >= mTotalWidth ){ starInfo.direction = StarInfo.LEFT; } break; case StarInfo.TOP: starInfo.yLocation -= starInfo.speed; if( starInfo.yLocation <= 0 ){ starInfo.direction = StarInfo.BOTTOM; } break; case StarInfo.BOTTOM: starInfo.yLocation += starInfo.speed; if( starInfo.yLocation >= mTotalHeight ){ starInfo.direction = StarInfo.TOP; } break; case StarInfo.RIGHT_BOTTOM: starInfo.xLocation += starInfo.speed; starInfo.yLocation += starInfo.speed; starInfo.alpha += 0.003; starInfo.sizePercent += 0.003; if( starInfo.xLocation >= mTotalWidth ){ starInfo.xLocation = 0; starInfo.sizePercent = 0.1f; starInfo.alpha = getStarSize(0.0f,0.3f); }else if( starInfo.yLocation >= mTotalHeight ){ starInfo.yLocation = 0; starInfo.sizePercent = 0.1f; starInfo.alpha = getStarSize(0.0f,0.3f); } if( starInfo.alpha >= 1.0 ){ starInfo.alpha = 1; } if( starInfo.sizePercent >= 0.6 ){ starInfo.sizePercent = 0.6f; }
break; default: break; } }
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); }
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (int i = 0; i < mStarInfos.size(); i++) { drawStarDynamic(mStarInfos.get(i), canvas, mPaint); resetStarFloat(mStarInfos.get(i)); } postInvalidate(); }
/** * 初始化漂浮速度 */ private int getStarSpeed(StarInfo starInfo){ Random random = new Random(); int randomSpeed = random.nextInt(3); switch (randomSpeed) { case 0: starInfo.speed = StarInfo.LOW_SPEED; break; case 1: starInfo.speed = StarInfo.MID_SPEED; break; case 2: starInfo.speed = StarInfo.HIGTH_SPEED; break; default: starInfo.speed = StarInfo.MID_SPEED; break; } return starInfo.speed; }
/** * 初始化星球运行方向 */ public int getStarDirection() { Random random = new Random(); int randomInt = random.nextInt(4); int direction = 0; switch (randomInt) { case 0: direction = StarInfo.LEFT; break; case 1: direction = StarInfo.RIGHT; break; case 2: direction = StarInfo.TOP; break; case 3: direction = StarInfo.BOTTOM; break;
default: break; } return direction; }
}
更多相关文章
- NDK学习笔记(十四) 使用AVILib+window创建一个AVI视频播放器
- Android(安卓)软键盘之 windowSoftInputMode 分析
- Android开发之自定义相机设定照片和预览参数问题
- android修改图片(修改图片大小,图片旋转,图片平移)
- [Android]【安卓】在代码中实时改变控件的大小
- Android动态设置控件大小
- Android文件、内存、SDCard管理常用工具类、方法
- Android(安卓)TextView自适应文字大小
- 计算Android(安卓)App占用的各种空间大小