这个自定义控件难度很小,但是效果很好,相信大家都见过,也都有自己的实现方法,今天就来介绍下我的思路。
先看下效果
1. 我先定义一个小礼物对象
/**
* Created by 李静,
* 我们定义的小礼物对象
*/
public class GiftBean {
public float alpha = 1f;
public Point pointStart;
public Point pointEnd;
public Point pointFirst;
public Point pointSecond;
public float a;
public int time;
public float t;
public GiftBean(Point[] randomPoint) {
float random = (float) Math.random();
this.a = Math.min(0.1f,random);
this.a = Math.max(0.075f,a);
this.pointStart = randomPoint[0];
this.pointFirst = randomPoint[1];
this.pointSecond = randomPoint[2];
this.pointEnd = randomPoint[3];
}
}
- 对象定义出来了,咱们就来让这些小家伙动起来吧,我用了SurfaceView来实现,毕竟有优势;
/**
* Created by 李静.
*/
public class GiftView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private ArrayList mDatas;
private ArrayList newest;
private int mWidth, mHeight;
private MyThread myThread;
public GiftView(Context context) {
super(context);
}
public GiftView(Context context, AttributeSet attrs) {
super(context, attrs);
mHolder = this.getHolder();
setZOrderOnTop(true);
mHolder.setFormat(PixelFormat.TRANSPARENT);
mHolder.addCallback(this);
myThread = new MyThread();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mWidth = w;
mHeight = h;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mDatas = new ArrayList<>();
newest = new ArrayList<>();
Collections.synchronizedList(newest);
for (int i = 0; i < 10; i++) {
Point[] randomPoint = createRandomPoint();
GiftBean bean = new GiftBean(randomPoint);
mDatas.add(bean);
}
if (!myThread.isAlive()) {
myThread = new MyThread();
myThread.start();
}
}
public void addGifts() {
for (int i = 0; i < Math.random() * 5; i++) {
Point[] randomPoint = createRandomPoint();
GiftBean bean = new GiftBean(randomPoint);
newest.add(bean);
}
if (!myThread.isAlive()) {
myThread = new MyThread();
myThread.start();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.i("lijing", "surfaceChanged");
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i("lijing", "surfaceDestroyed");
}
class MyThread extends Thread {
private Bitmap mBitmap;
private Paint paint;
public MyThread() {
paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
mBitmap = getBitmapFromDrawable(R.mipmap.ic_launcher);
}
@Override
public void run() {
while (mDatas.size() > 0 || newest.size() > 0) {
Canvas canvas = mHolder.lockCanvas();
if (canvas == null) {
mDatas.clear();
newest.clear();
return;
}
List delete = new ArrayList<>();
Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
Canvas canvas_temp = new Canvas(bitmap);
mDatas.addAll(newest);
newest.clear();
for (GiftBean giftSimple : mDatas) {
giftSimple.time += 1;
float x = 0.5f * giftSimple.a * giftSimple.time * giftSimple.time;
giftSimple.t = x / mHeight;
giftSimple.alpha = 1f - giftSimple.t;
if (giftSimple.t >= 1f) {
delete.add(giftSimple);
continue;
}
Point point = evaluate(giftSimple.t, giftSimple.pointStart, giftSimple.pointFirst, giftSimple.pointSecond, giftSimple.pointEnd);
Paint paint_temp = new Paint();
paint_temp.setAlpha((int) (giftSimple.alpha * 255));
canvas_temp.drawBitmap(mBitmap, point.x, point.y, paint_temp);
}
canvas.drawBitmap(bitmap, 0, 0, paint);
SystemClock.sleep(10);
mHolder.unlockCanvasAndPost(canvas);
mDatas.removeAll(delete);
}
}
}
protected Bitmap getBitmapFromDrawable(@DrawableRes int resId) {
BitmapDrawable drawable = (BitmapDrawable) getContext().getResources().getDrawable(resId);
Bitmap bitmap = drawable.getBitmap();
return Bitmap.createScaledBitmap(bitmap, 50, 50, false);
}
public Point evaluate(float t, Point startValue, Point first, Point second, Point endValue) {
int x = (int) (startValue.x * Math.pow((1 - t), 3) + 3 * first.x * t * Math.pow((1 - t), 2) + 3 * second.x * Math.pow(t, 2) * (1 - t) + endValue.x * Math.pow(t, 3));
int y = (int) (startValue.y * Math.pow((1 - t), 3) + 3 * first.y * t * Math.pow((1 - t), 2) + 3 * second.y * Math.pow(t, 2) * (1 - t) + endValue.y * Math.pow(t, 3));
return new Point(x, y);
}
private Point[] createRandomPoint() {
Point point_start = new Point(mWidth / 2, mHeight);
Point point_end = new Point((int) (Math.random() * mWidth), 0);
Point point_first = new Point((int) (Math.random() * (mWidth / 2)), (int) (Math.random() * (mHeight / 2) + mHeight / 2));
Point point_second = new Point((int) (Math.random() * (mWidth / 2) + mWidth / 2), (int) (Math.random() * (mHeight / 2)));
double leftOrRight = Math.random()-0.5d;
if (leftOrRight>0){
point_first.x = point_first.x+mWidth/2;
point_second.x = point_second.x-mWidth/2;
}
return new Point[]{point_start, point_first, point_second, point_end};
}
}