Android之自定义View:点赞动画效果

实现点赞效果动画,可以根据需求进行修改使用。

先上个Gif图:

1.自定义DivergeView


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.View;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

public class DivergeView extends View implements Runnable {
    public static final float mDuration = 0.01F;
    public static final int mDefaultHeight = 100;
    protected static final long mQueenDuration = 200L;
    protected final Random mRandom;
    protected ArrayList mDivergeInfos;
    protected List mQueen;
    protected PointF mPtStart;
    protected PointF mPtEnd;
    protected ArrayList mDeadPool;
    private Paint mPaint;
    private DivergeViewProvider mDivergeViewProvider;
    private long mLastAddTime;
    private Thread mThread;
    private boolean mRunning;
    private boolean mIsDrawing;

    public DivergeView(Context context) {
        this(context, (AttributeSet) null);
    }

    public DivergeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DivergeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mRandom = new Random();
        this.mDeadPool = new ArrayList();
        this.mLastAddTime = 0L;
        this.mRunning = true;
        this.mIsDrawing = false;
        this.init();
    }

    public void run() {
        while (this.mRunning) {
            if (this.mDivergeViewProvider != null && this.mQueen != null && !this.mIsDrawing && this.mDivergeInfos != null) {
                this.dealQueen();
                if (this.mDivergeInfos.size() != 0) {
                    this.dealDiverge();
                    this.mIsDrawing = true;
                    this.postInvalidate();
                }
            }
        }

        this.release();
    }

    private void dealDiverge() {
        for (int i = 0; i < this.mDivergeInfos.size(); ++i) {
            DivergeInfo divergeInfo = (DivergeInfo) this.mDivergeInfos.get(i);
            float timeLeft = 1.0F - divergeInfo.mDuration;
            divergeInfo.mDuration += 0.01F;
            float time1 = timeLeft * timeLeft;
            float time2 = 2.0F * timeLeft * divergeInfo.mDuration;
            float time3 = divergeInfo.mDuration * divergeInfo.mDuration;
            float x = time1 * this.mPtStart.x + time2 * divergeInfo.mBreakPoint.x + time3 * divergeInfo.mEndPoint.x;
            divergeInfo.mX = x;
            float y = time1 * this.mPtStart.y + time2 * divergeInfo.mBreakPoint.y + time3 * divergeInfo.mEndPoint.y;
            divergeInfo.mY = y;
            if (divergeInfo.mY <= divergeInfo.mEndPoint.y) {
                this.mDivergeInfos.remove(i);
                this.mDeadPool.add(divergeInfo);
                --i;
            }
        }

    }

    private void dealQueen() {
        long now = System.currentTimeMillis();
        if (this.mQueen.size() > 0 && now - this.mLastAddTime > 200L) {
            this.mLastAddTime = System.currentTimeMillis();
            DivergeInfo divergeInfo = null;
            if (this.mDeadPool.size() > 0) {
                divergeInfo = (DivergeInfo) this.mDeadPool.get(0);
                this.mDeadPool.remove(0);
            }

            if (divergeInfo == null) {
                divergeInfo = this.createDivergeNode(this.mQueen.get(0));
            }

            divergeInfo.reset();
            divergeInfo.mType = this.mQueen.get(0);
            this.mDivergeInfos.add(divergeInfo);
            this.mQueen.remove(0);
        }

    }

    private void init() {
        this.mPaint = new Paint(1);
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }

    public void setDivergeViewProvider(DivergeViewProvider divergeViewProvider) {
        this.mDivergeViewProvider = divergeViewProvider;
    }

    public PointF getStartPoint() {
        return this.mPtStart;
    }

    public boolean isRunning() {
        return this.mRunning;
    }

    public void startDiverges(Object obj) {
        if (this.mDivergeInfos == null) {
            this.mDivergeInfos = new ArrayList(30);
        }

        if (this.mQueen == null) {
            this.mQueen = Collections.synchronizedList(new ArrayList(30));
        }

        this.mQueen.add(obj);
        if (this.mThread == null) {
            this.mThread = new Thread(this);
            this.mThread.start();
        }

    }

    public void stop() {
        if (this.mDivergeInfos != null) {
            this.mDivergeInfos.clear();
        }

        if (this.mQueen != null) {
            this.mQueen.clear();
        }

        if (this.mDeadPool != null) {
            this.mDeadPool.clear();
        }

    }

    public void release() {
        this.stop();
        this.mPtEnd = null;
        this.mPtStart = null;
        this.mDivergeInfos = null;
        this.mQueen = null;
        this.mDeadPool = null;
    }

    public void setStartPoint(PointF point) {
        this.mPtStart = point;
    }

    public void setEndPoint(PointF point) {
        this.mPtEnd = point;
    }

    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        this.mRunning = false;
    }

    protected void onDraw(Canvas canvas) {
        if (this.mRunning && this.mDivergeViewProvider != null && this.mDivergeInfos != null) {
            Iterator var2 = this.mDivergeInfos.iterator();

            while (var2.hasNext()) {
                DivergeInfo divergeInfo = (DivergeInfo) var2.next();
                this.mPaint.setAlpha((int) (255.0F * divergeInfo.mY / this.mPtStart.y));
                canvas.drawBitmap(this.mDivergeViewProvider.getBitmap(divergeInfo.mType), divergeInfo.mX, divergeInfo.mY, this.mPaint);
            }
        }

        this.mIsDrawing = false;
    }

    private PointF getBreakPointF(int scale1, int scale2) {
        PointF pointF = new PointF();
        pointF.x = (float) (this.mRandom.nextInt((this.getMeasuredWidth() - this.getPaddingRight() + this.getPaddingLeft()) / scale1) + this.getMeasuredWidth() / scale2);
        pointF.y = (float) (this.mRandom.nextInt((this.getMeasuredHeight() - this.getPaddingBottom() + this.getPaddingTop()) / scale1) + this.getMeasuredHeight() / scale2);
        return pointF;
    }

    protected DivergeInfo createDivergeNode(Object type) {
        PointF endPoint = this.mPtEnd;
        if (endPoint == null) {
            endPoint = new PointF((float) this.mRandom.nextInt(this.getMeasuredWidth()), 0.0F);
        }

        if (this.mPtStart == null) {
            this.mPtStart = new PointF((float) (this.getMeasuredWidth() / 2), (float) (this.getMeasuredHeight() - 100));
        }

        return new DivergeInfo(this.mPtStart.x, this.mPtStart.y, this.getBreakPointF(2, 3), endPoint, type);
    }

    public class DivergeInfo {
        public float mDuration = 0.0F;
        public PointF mBreakPoint;
        public PointF mEndPoint;
        public float mX;
        public float mY;
        public Object mType;
        public float mStartX;
        public float mStartY;

        public DivergeInfo(float x, float y, PointF breakPoint, PointF endPoint, Object type) {
            this.mEndPoint = endPoint;
            this.mX = x;
            this.mY = y;
            this.mStartX = x;
            this.mStartY = y;
            this.mBreakPoint = breakPoint;
            this.mType = type;
        }

        public void reset() {
            this.mDuration = 0.0F;
            this.mX = this.mStartX;
            this.mY = this.mStartY;
        }
    }

    public interface DivergeViewProvider {
        Bitmap getBitmap(Object var1);
    }
}

 
  

2.XML布局文件:




    

    

3.在Activity中的代码:

public class MainActivity extends Activity {

    private DivergeView mDivergeView;
    private ImageView mImageView;
    private ArrayList mList;
    private int mIndex = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initView();
    }

    //初始化布局
    private void initView() {
        mImageView = findViewById(R.id.iv_start);
        mDivergeView = findViewById(R.id.divergeView);

        mList = new ArrayList<>();
        // 添加点赞图标
        mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.ic_praise_sm1, null)).getBitmap());
        mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.ic_praise_sm2, null)).getBitmap());
        mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.ic_praise_sm3, null)).getBitmap());
        mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.ic_praise_sm4, null)).getBitmap());

        mImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mIndex == mList.size()) {
                    mIndex = 0;
                }
                mDivergeView.startDiverges(mIndex);
                mIndex++;
            }
        });
       

        mDivergeView.post(new Runnable() {
            @Override
            public void run() {
                mDivergeView.setEndPoint(new PointF(mDivergeView.getMeasuredWidth() / 2, 0));
                mDivergeView.setDivergeViewProvider(new Provider());
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mList != null) {
            mList.clear();
            mList = null;
        }
    }

    class Provider implements DivergeView.DivergeViewProvider {

        @Override
        public Bitmap getBitmap(Object obj) {
            return mList == null ? null : mList.get((int) obj);
        }
    }

}

 

你可能感兴趣的:(Android之自定义View)