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); } }很简单,就不太多的解释了,大家复制进项目里边就能直接用了