分享一个类似星星眨眼的动画效果实现方式。这里涉及到两个类,看官可直接拿来用。
StarView.java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.VectorDrawable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import java.util.ArrayList;
import java.util.Random;
public class StarView extends View {
private Paint mPaint;
private Bitmap mStarOn;
private Bitmap mStarOff;
private int mStarsNumber=10;
private ArrayList<StarModel> mStarModelList = null;
private int mCenterX, mCenterY;
private boolean mAnimatorStatus=true;
private Random mRandom;
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);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mStarOn = getBitmapFromDrawable(getContext(),android.R.drawable.star_on);
mStarOff = getBitmapFromDrawable(getContext(), android.R.drawable.star_off);
}
private Bitmap getBitmapFromDrawable(Context context, int drawableId) {
Drawable drawable = ContextCompat.getDrawable(context, drawableId);
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
} else if (drawable instanceof VectorDrawable) {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
return null;
}
/**
* 设置星星图片
* @param starOn
* @param starOff
*/
public void setStar(int starOn,int starOff){
mStarOn=getBitmapFromDrawable(getContext(),starOn);
mStarOff=getBitmapFromDrawable(getContext(),starOff);
}
/**
* 设置星星数量
* @param number 参数值范围(1-100)
* @return 0:设置成功 -1:设置失败
*/
public int setStarsNumber(int number){
if(number<=0||number>100){
return -1;
}
mStarsNumber=number;
return 0;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mCenterX = getMeasuredWidth() / 2 - mStarOn.getWidth() / 2; // 90
mCenterY = getMeasuredHeight() / 2 - mStarOn.getHeight() / 2; // 90
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i("StarView", "onDraw");
if (mStarModelList == null) {
return;
}
calculate(canvas);
}
//在这个方法里会随机地去改变星星的位置和图片类型,以达到眨眼效果
protected void calculate(Canvas canvas){
if(mRandom==null){
mRandom= new Random();
}
float angle = 0;
int i=0;
float startX=0,startY=0;
for (StarModel starModel : mStarModelList) {
i++;
if (i == 0) {
angle = (float) ((10 + 270) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * mRandom.nextInt(3) * 0.1f;
startY = (float) Math.sin(angle) * mCenterY * mRandom.nextInt(3) * 0.1f;
} else if (i == 1) {
angle = (float) ((30 + 270) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * mRandom.nextInt(2) * 0.1f;
startY = (float) Math.sin(angle) * mCenterY * mRandom.nextInt(3) * 0.1f;
} else if (i == 2) {
angle = (float) ((40 + 270) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.25f;
startY = (float) Math.sin(angle) * mCenterY * 0.4f;
} else if (i == 3) {
angle = (float) ((60 + 270) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.13f;
startY = (float) Math.sin(angle) * mCenterY * 0.33f;
} else if (i == 4) {
angle = (float) ((50) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.16f;
startY = (float) Math.sin(angle) * mCenterY * 0.17f;
} else if (i == 5) {
angle = (float) ((80) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.05f;
startY = (float) Math.sin(angle) * mCenterY * 0.3f;
} else if (i == 6) {
angle = (float) ((145) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.15f;
startY = (float) Math.sin(angle) * mCenterY * 0.28f;
} else if (i == 7) {
angle = (float) ((205) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.15f;
startY = (float) Math.sin(angle) * mCenterY * 0.15f;
} else if (i == 8) {
angle = (float) ((215) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * mRandom.nextInt(3) * 0.1f;
startY = (float) Math.sin(angle) * mCenterY * mRandom.nextInt(3) * 0.1f;
} else if (i == 9) {
angle = (float) ((225) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * 0.14f;
startY = (float) Math.sin(angle) * mCenterY * 0.15f;
}else {
angle = (float) ((215) * Math.PI / 180);
startX = (float) Math.cos(angle) * mCenterX * mRandom.nextInt(3) * 0.1f;
startY = (float) Math.sin(angle) * mCenterY * mRandom.nextInt(3) * 0.1f;
}
starModel.setmStartX(startX);
starModel.setmStartY(startY);
if (mRandom.nextInt(12) % 2 == 0) {
starModel.setmIcon(mStarOn);
} else {
starModel.setmIcon(mStarOff);
}
starModel.draw(canvas, mPaint, mCenterX, mCenterY);
}
}
/**
* 开始动画
* @return
*/
public void startAnimation() {
mAnimatorStatus=true;
initStarModel();
//这里开启一个线程,不断地去刷新view(调用invalidate方法后调用onDraw)
new Thread(){
@Override
public void run() {
super.run();
while (mAnimatorStatus){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
invalidate();
}
}
}.start();
}
/**
* 停止动画
*/
public void stopAnimation() {
mAnimatorStatus=false;
}
private void initStarModel() {
Log.i("StarView","initStarModel");
if(mStarModelList==null){
mStarModelList = new ArrayList<>(mStarsNumber);
}else {
mStarModelList.clear();
}
Bitmap bitmap = mStarOn;
for (int i = 0; i < mStarsNumber; i++) {
Matrix matrix = new Matrix();
StarModel model = new StarModel(bitmap, 0, 0, matrix);
mStarModelList.add(model);
}
}
}
StarModel.java
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.Log;
public class StarModel {
private Bitmap mIcon;// 图片
private float mStartX;// 起始位置
private float mStartY;// 起始位置
private Matrix mMatrix;// 矩阵
public StarModel(Bitmap mIcon, float mStartX, float mStartY, Matrix matrix) {
this.mIcon = mIcon;
this.mStartX = mStartX;
this.mStartY = mStartY;
this.mMatrix = matrix;
}
public void draw(Canvas canvas, Paint paint, int centerX, int centerY) {
float left = centerX + mStartX;
float top = centerY + mStartY;
Log.i("StarModel","centerY: "+centerY+" mStartY: "+mStartY);
Log.i("StarModel","left: "+left+" top: "+top);
mMatrix.setTranslate(left, top);
canvas.drawBitmap(mIcon, mMatrix, paint);
}
public Bitmap getmIcon() {
return mIcon;
}
public void setmIcon(Bitmap mIcon) {
this.mIcon = mIcon;
}
public float getmStartX() {
return mStartX;
}
public void setmStartX(float mStartX) {
this.mStartX = mStartX;
}
public float getmStartY() {
return mStartY;
}
public void setmStartY(float mStartY) {
this.mStartY = mStartY;
}
public Matrix getmMatrix() {
return mMatrix;
}
public void setmMatrix(Matrix mMatrix) {
this.mMatrix = mMatrix;
}
}
使用方法:
1,在布局文件里面加入StarView
<com.xxx.xxx.xxx.StarView
android:id="@+id/star"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
2,在Activity里调用
final StarView starView = findViewById(R.id.star);
starView.setStar(R.drawable.star,R.drawable.star2);
.....
start_annmotion.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
starView.startAnimation();
}
});
findViewById(R.id.stop_annmotion).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
starView.stopAnimation();
}
});
|