安卓Andriod使用入门(二十七)【点赞动画】

有过执着,放下执着。有过牵挂,了无牵挂。


MainActivity.java代码:

package siso.likeanimation;

import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.drawable.BitmapDrawable;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    private DivergeViewSecond mDivergeView;
    private Button mBtnStart;
    private ImageView mImageView;
    private ArrayList<Bitmap> mList;
    private int mIndex = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtnStart = (Button)findViewById(R.id.btnStart);
        mImageView = (ImageView)findViewById(R.id.iv_start);
        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());
        mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(),R.drawable.ic_praise_sm5,null)).getBitmap());
        mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.ic_praise_sm6, null)).getBitmap());
        mBtnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mIndex == 5){
                    mIndex = 0 ;
                }
                mDivergeView.startDiverges(mIndex);
                mIndex ++;
//                if (mDivergeView.isRunning()) {
//                    mDivergeView.stop();
//                } else {
//
//                }
            }
        });
        mDivergeView = (DivergeViewSecond) findViewById(R.id.divergeView);
        mDivergeView.post(new Runnable() {
            @Override
            public void run() {
                mDivergeView.setEndPoint(new PointF(mDivergeView.getMeasuredWidth()/2,0));
                mDivergeView.setDivergeViewProvider(new Provider());
            }
        });
//        mDivergeView.start();
    }

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

    }

    class Provider implements DivergeViewSecond.DivergeViewProvider{

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

DivergeViewSecond.java代码:

package siso.likeanimation;

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.util.Log;
import android.view.View;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;


public class DivergeViewSecond extends View implements Runnable{

    public static final float mDuration = 0.010F;
    public static final int mDefaultHeight = 100;
    protected  static final long mQueenDuration = 200;

    protected final Random mRandom = new Random();

    protected ArrayList<DivergeInfo> mDivergeInfos;

    protected List<Object> mQueen;

    protected PointF mPtStart;
    protected PointF mPtEnd;

    protected ArrayList<DivergeInfo> mDeadPool = new ArrayList<>();

    private Paint mPaint;

//    private static final int mDefaultWidth = 100;
//    private static final int mAlphaOffset = 50;

    private DivergeViewProvider mDivergeViewProvider;

    private long mLastAddTime = 0;

    private Thread mThread;

    private boolean mRunning = true;

    private boolean mIsDrawing = false;

    public DivergeViewSecond(Context context) {
        this(context, null);
    }

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

    public DivergeViewSecond(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }


    /**
     * Loop
     */
    @Override
    public void run() {

        while(mRunning){

            if(mDivergeViewProvider == null){
                continue;
            }

            if(mQueen == null){
                continue;
            }

            if(mIsDrawing){
                //如果正在绘制,不要处理数据
                continue;
            }

            if(mDivergeInfos == null){
                continue;
            }

            dealQueen();

            if(mDivergeInfos.size() == 0){
                continue;
            }

            dealDiverge();

            mIsDrawing = true;

            postInvalidate();

        }

        //停止
        release();
    }

    private void dealDiverge(){
        for (int i = 0; i < mDivergeInfos.size(); i++) {
            DivergeInfo divergeInfo = mDivergeInfos.get(i);

            float timeLeft = 1.0F - divergeInfo.mDuration;

            divergeInfo.mDuration += mDuration;

            float x, y;

            //二次贝塞尔
            float time1 = timeLeft * timeLeft;
            float time2 = 2 * timeLeft * divergeInfo.mDuration;
            float time3 = divergeInfo.mDuration * divergeInfo.mDuration;
            x = time1 * (mPtStart.x)
                    + time2 * (divergeInfo.mBreakPoint.x)
                    + time3 * (divergeInfo.mEndPoint.x);

            divergeInfo.mX = x;

            y = time1 * (mPtStart.y)
                    + time2 * (divergeInfo.mBreakPoint.y)
                    + time3 * (divergeInfo.mEndPoint.y);

            divergeInfo.mY = y;

            if (divergeInfo.mY <= divergeInfo.mEndPoint.y) {
                mDivergeInfos.remove(i);
                mDeadPool.add(divergeInfo);
                i--;
                continue;
            }
        }
    }

    private void dealQueen(){
        long now = System.currentTimeMillis();
        if(mQueen.size() > 0 && now - mLastAddTime > mQueenDuration){
            mLastAddTime = System.currentTimeMillis();
            DivergeInfo divergeInfo = null;
            if(mDeadPool.size() > 0){
                //死池里面有空闲的divergeNode
                divergeInfo = mDeadPool.get(0);
                mDeadPool.remove(0);
            }
            if(divergeInfo == null){
                divergeInfo = createDivergeNode(mQueen.get(0));
            }
            divergeInfo.reset();
            divergeInfo.mType = mQueen.get(0);
            mDivergeInfos.add(divergeInfo);
            mQueen.remove(0);
        }
    }

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


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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //不需要支持wrap_content

    }

    @Override
    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){
        mDivergeViewProvider = divergeViewProvider;
    }

    public PointF getStartPoint(){
        return mPtStart;
    }

    public boolean isRunning(){
        return mRunning;
    }

    public void startDiverges(Object obj){

        if(mDivergeInfos == null){
            mDivergeInfos = new ArrayList<>(30);
        }

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

        mQueen.add(obj);
//        for(Object obj : objs) {
//            mQueen.add(obj);
//        }

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

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

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

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

    }

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

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

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

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

    @Override
    protected void onDraw(Canvas canvas) {

        if(mRunning && mDivergeViewProvider != null && mDivergeInfos != null){
            for(DivergeInfo divergeInfo : mDivergeInfos){
                mPaint.setAlpha((int)(255 * divergeInfo.mY / mPtStart.y));
                canvas.drawBitmap(mDivergeViewProvider.getBitmap(divergeInfo.mType),
                        divergeInfo.mX,
                        divergeInfo.mY,
                        mPaint);
            }
        }
        mIsDrawing = false;
    }


    private PointF getBreakPointF(int scale1, int scale2) {

        PointF pointF = new PointF();
        pointF.x = mRandom.nextInt((getMeasuredWidth() - getPaddingRight() + getPaddingLeft()) / scale1) + getMeasuredWidth() / scale2;
        pointF.y = mRandom.nextInt((getMeasuredHeight() - getPaddingBottom() + getPaddingTop()) / scale1) + getMeasuredHeight() / scale2;
        return pointF;
    }

    protected DivergeInfo createDivergeNode(Object type){
        PointF endPoint = mPtEnd;
        if(endPoint == null){
            endPoint = new PointF(mRandom.nextInt(getMeasuredWidth()),0);
        }
//        int height = mDivergeViewProvider == null ? mDefaultHeight : mDivergeViewProvider.getBitmap(type).getHeight();
        if(mPtStart == null) {
            mPtStart = new PointF(getMeasuredWidth() / 2, getMeasuredHeight() - mDefaultHeight);//默认起始高度
        }
        return new DivergeInfo(
                mPtStart.x,
                mPtStart.y,
                getBreakPointF(2, 3),
                endPoint,
                type);
    }

    public class DivergeInfo {
        public float mDuration;
        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){
            mDuration = 0.0f;
            mEndPoint = endPoint;
            mX = x;
            mY = y;
            mStartX = x;
            mStartY = y;
            mBreakPoint = breakPoint;
            mType = type;
        }

        public void reset(){
            mDuration = 0.0f;
            mX = mStartX;
            mY = mStartY;
        }
    }
}

activity_main.xml内容:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="siso.likeanimation.MainActivity">

    <Button
        android:id="@+id/btnStart"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始"/>

    <siso.likeanimation.DivergeViewSecond
        android:id="@+id/divergeView"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_width="130dp"
        android:layout_height="300dp"/>
    <ImageView
        android:id="@+id/iv_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="10dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:background="@drawable/ic_praise_sm6"/>
</RelativeLayout>

运行结果如图:

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值