android高效简洁的代码实现直播礼物效果

     入职新公司,发现这边老项目里边有个礼物的特效,我就想着何种效果应该是比较常见的,并且最近又看了一些贝塞尔曲线的内容,闲着无事,索性就自己写写代码,尝试下自己能不能自己去实现这种效果。

       实现的过程真的非常简单,无非是如何在自定义view中使用贝塞尔曲线,贝塞尔曲线这里就不介绍了,网上资源太多了,首先看下效果。



实现的动画必须有几个特点,

1.弹出的图片必须自由定义。

2.弹出的位置固定,消失位置不固定。

3.弹出的路径必须是按照贝塞尔曲线去进行。

4.弹出的速度必须不一样。

5.弹出的个数必须随意。

过程就不多说了,主要看代码:

 
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

/* * * 贝塞尔曲线的理解 * */  public class MainActivity
        extends AppCompatActivity
{
    private BezierView mBezierView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mBezierView = findViewById(R.id.bezierView);
        findViewById(R.id.addImage).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mBezierView.addimage();
            }
        });
    }

}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:app="http://schemas.android.com/apk/res-auto"  xmlns:tools="http://schemas.android.com/tools"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="vertical"  tools:context="com.livestar.liaotian.MainActivity">

    <Button  android:text="添加"  android:id="@+id/addImage"  android:layout_width="match_parent"  android:layout_height="wrap_content"/>
<com.livestar.liaotian.BezierView  android:id="@+id/bezierView"  android:background="@color/colorAccent"  android:layout_width="match_parent"  android:layout_height="match_parent"/>

</LinearLayout>
核心代码:

public class BezierView extends View {


    private static final String TAG = "BezierView";
    private Context context;
    private Paint mPaint;
    private float detlaX=0;
    private float detlaY=500;
    
    private int mWidth;
    
    private PointF point1;

    private PointF mPoint;
    private Bitmap mBitmap;

    private Bitmap mBitmap2;
    private Bitmap mBitmap3;

    private Random mRandom;
    private int select;
    private List<Bitmap> mBitmaps=new ArrayList<>();
    private int select2=1;
    
    private List<PointImage> listpointImage=new ArrayList<>();
    private Bitmap mBitmap4;
    private Bitmap mBitmap5;
    private Bitmap mBitmap6;
    private Bitmap mBitmap7;
    private Bitmap mBitmap8;
    private Bitmap mBitmap9;
    private Bitmap mBitmap10;
    private Bitmap mBitmap11;

    public BezierView(Context context) {
        super(context);
        this.context=context;
    }

    public BezierView(Context context, @Nullable AttributeSet attrs)
    {
        super(context, attrs);
        this.context=context;
        init();
        initBitmap();
        initrandom();
    }

    private void initrandom() {
        mRandom = new Random();
    }

    private void initBitmap() {
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_heart_yellow);
        mBitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_heart_red);
        mBitmap3 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_heart_blue);
        mBitmap4 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_heart_blue);
        mBitmap5 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_moon_blue);
        mBitmap6 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_moon_yellow);
        mBitmap7 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_qiqiu_blue);
        mBitmap8 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_qiqiu_red);
        mBitmap9 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_qiqiu_yellow);
        mBitmap10 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_star_gray);
        mBitmap11 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_start_yellow);
        mBitmaps.add(mBitmap);
        mBitmaps.add(mBitmap2);
        mBitmaps.add(mBitmap3);
        mBitmaps.add(mBitmap4);
        mBitmaps.add(mBitmap5);
        mBitmaps.add(mBitmap6);
        mBitmaps.add(mBitmap7);
        mBitmaps.add(mBitmap8);
        mBitmaps.add(mBitmap9);
        mBitmaps.add(mBitmap10);
        mBitmaps.add(mBitmap11);
       
    }
    

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth=this.getMeasuredWidth();
    }

    
    /**  * 初始化画笔 路径  */  private void init() {
        //画笔  mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.WHITE);
        mPaint.setStrokeWidth(10f);
        mPaint.setTextSize(20f);
        mPaint.setStyle(Paint.Style.STROKE);
    }
    

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
            for (int i=0;i<listpointImage.size();i++){
                PointImage pointImage=    listpointImage.get(i);
                Log.d(TAG, pointImage.getAnimation().progress+"---"+i);
                float xAix=getYvalue(pointImage.getAnimation().progress,pointImage.getPointF().point1,pointImage.getPointF().pointC,pointImage.getPointF().point2).x;
                float yAix=getYvalue(pointImage.getAnimation().progress,pointImage.getPointF().point1,pointImage.getPointF().pointC,pointImage.getPointF().point2).y;
                canvas.drawBitmap(mBitmaps.get(pointImage.getSelctimage()),xAix,yAix,mPaint);
                if (pointImage.getAnimation().progress>=1){
                    listpointImage.remove(pointImage);
                    pointImage=null;
                    continue;
                }else {
                    invalidate();
                }
            }


    }





    public PointF  getYvalue(float t, PointF point1,PointF point2, PointF point3){

        mPoint.x =(1-t)*(1-t)*point1.x+2*t*(1-t)*point2.x+t*t*point3.x;

        mPoint.y = (1-t)*(1-t)*point1.y+2*t*(1-t)*point2.y+t*t*point3.y;
        // 套用上面的公式把点返回  return mPoint;

    }

    public void addimage() {

        PointImage pointImage=new PointImage();
        AnimationBean animation=AnimationFactor.getAnimation(context);
        //必须要随机的一个动画  pointImage.setAnimation(animation);

        //随机的一个路径  PointPath pointPath =new PointPath();
        pointPath.creatPointPath(this.getMeasuredWidth(),this.getMeasuredHeight(),mBitmap.getHeight());
        pointImage.setPointF(pointPath);

        //随机的图片  pointImage.setSelctimage(mRandom.nextInt(3));
        listpointImage.add(pointImage);
        
        pointImage.getAnimation().mObjectAnimator.start();
        invalidate();

    }
}
代码很简单的,大家拿去改吧改吧就能直接用了。

import android.animation.ObjectAnimator;

public class AnimationBean {

    public ObjectAnimator mObjectAnimator;
    public float progress;
}
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.PointF;
import android.util.Log;
import android.view.animation.Animation;

import java.security.PublicKey;
import java.util.Random;

public class AnimationFactor {


    private static String TAG="AnimationFactor";
    public static Random mRandom=new Random();
    private float progresscount3;

    public static AnimationBean  getAnimation(Context context){
      final AnimationBean  animationBean=new AnimationBean();

        ObjectAnimator animator = ObjectAnimator.ofFloat(context, "z", 0, 1 );
        animator.setDuration(mRandom.nextInt(6000)+1000);
        animator.setRepeatCount(0);

        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {

                animationBean.progress=(float)animation.getAnimatedValue();
                Log.d(TAG,animationBean.progress+"");
            }
        });
        animationBean.mObjectAnimator=animator;

        return animationBean;
    }


}
public class PointImage {

    public AnimationBean mAnimation;
    public PointPath mPointF;
    public int selctimage;

    public int getSelctimage() {
        return selctimage;
    }

    public void setSelctimage(int selctimage) {
        this.selctimage = selctimage;
    }

    public AnimationBean getAnimation() {
        return mAnimation;
    }

    public void setAnimation(AnimationBean animation) {
        mAnimation = animation;
    }

    public PointPath getPointF() {
        return mPointF;
    }

    public void setPointF(PointPath pointF) {
        mPointF = pointF;
    }
    
}
import android.graphics.PointF;

import java.util.Random;

public class PointPath {
    public PointF point1;
    public PointF point2;
    public PointF pointC;
    public Random mRandom =new Random();
/* * point1 =new PointF(this.getMeasuredWidth()/2,this.getMeasuredHeight()-10);  point2 =new PointF(this.getMeasuredWidth()/2,-80);  pointC1 =new PointF(this.getMeasuredWidth()/2-200,this.getMeasuredHeight()/2);  * * * */  public void creatPointPath(int viewwidth,int viewHeight,int bitmapwidth) {

        point1 =new PointF(viewwidth/2,viewHeight-10);
        point2 =new PointF(mRandom.nextInt(viewwidth),-bitmapwidth);
        pointC =new PointF(viewwidth-200,viewHeight/2);


    }
}
很简单,就不太多的解释了,大家复制进项目里边就能直接用了

demo地址