的基础上,进行了部分优化,源码在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<StarInfo> 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;
}
}