一、概述,最后面有完整代码下载地址

老规矩先上图

Android直播sdk Android直播点赞_java

好了,基本就是这个样子,录完的视频用格式工厂转换完就这个样子了,将就看吧

二、定义我们自己的Layout

1. /**
2.  * @author 刘洋巴金
3.  * @date 2017-4-27
4.  * 
5.  * 定义我们自己的布局
6.  * */  
7. public class LoveLayout extends RelativeLayout{  
8.   
9. private Context context;  
10. private LayoutParams params;  
11. private Drawable[] icons = new Drawable[4];  
12. private Interpolator[] interpolators = new Interpolator[4];  
13. private int mWidth;  
14. private int mHeight;  
15.       
16. public LoveLayout(Context context, AttributeSet attrs) {  
17. super(context, attrs);  
18.           
19. this.context = context;  
20.         initView();  
21.     }  
22.   
23. private void initView() {  
24.           
25. // 图片资源  
26. 0] = getResources().getDrawable(R.drawable.green);  
27. 1] = getResources().getDrawable(R.drawable.purple);  
28. 2] = getResources().getDrawable(R.drawable.red);  
29. 3] = getResources().getDrawable(R.drawable.yellow);  
30.           
31. // 插值器  
32. 0] = new AccelerateDecelerateInterpolator(); // 在动画开始与结束的地方速率改变比较慢,在中间的时候加速  
33. 1] = new AccelerateInterpolator();  // 在动画开始的地方速率改变比较慢,然后开始加速  
34. 2] = new DecelerateInterpolator(); // 在动画开始的地方快然后慢  
35. 3] = new LinearInterpolator();  // 以常量速率改变  
36.           
37. int width = icons[0].getIntrinsicWidth();  
38. int height = icons[0].getIntrinsicWidth();  
39. new LayoutParams(width, height);  
40.         params.addRule(CENTER_HORIZONTAL, TRUE);  
41.         params.addRule(ALIGN_PARENT_BOTTOM, TRUE);  
42.     }

基本就是做了初始化,声明了4个drawable,也就是4个颜色的心,4个插值器,用于控制动画速率的改变,设置初始位置为屏幕的下边中点处。

    1. @Override  
    2. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
    3. // TODO Auto-generated method stub  
    4. super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
    5.     mWidth = getMeasuredWidth();  
    6.     mHeight = getMeasuredHeight();  
    7. }  
    8.       
    9. public void addLoveView() {  
    10. // TODO Auto-generated method stub  
    11. final ImageView iv = new ImageView(context);  
    12.     iv.setLayoutParams(params);  
    13. new Random().nextInt(4)]);  
    14.     addView(iv);  
    15.           
    16. // 开启动画,并且用完销毁  
    17.     AnimatorSet set = getAnimatorSet(iv);  
    18.     set.start();  
    19. new AnimatorListenerAdapter() {  
    20. @Override  
    21. public void onAnimationEnd(Animator animation) {  
    22. // TODO Auto-generated method stub  
    23. super.onAnimationEnd(animation);  
    24.             removeView(iv);  
    25.         }  
    26.     });  
    27. }


    用于添加心型效果。动画结束后,再移除

    1. /**
    2.  * 获取动画集合
    3.  * @param iv 
    4.  * */  
    5. private AnimatorSet getAnimatorSet(ImageView iv) {  
    6.           
    7. // 1.alpha动画  
    8. "alpha", 0.3f, 1f);  
    9.           
    10. // 2.缩放动画  
    11. "scaleX", 0.2f, 1f);  
    12. "scaleY", 0.2f, 1f);  
    13.           
    14. // 动画集合  
    15. new AnimatorSet();  
    16.     set.playTogether(alpha, scaleX, scaleY);  
    17. 500);  
    18.           
    19. // 贝塞尔曲线动画  
    20.     ValueAnimator bzier = getBzierAnimator(iv);  
    21.           
    22. new AnimatorSet();  
    23.     set2.playSequentially(set, bzier);  
    24.     set2.setTarget(iv);  
    25. return set2;  
    26. }


    playTogether:几个动画同时执行

    ObjectAnimator为属性动画,不熟悉可以百度了解下

    然后是设置贝塞尔曲线动画

    playSequentially:动画依次执行

    1. /**
    2.  * 贝塞尔动画
    3.  * */  
    4. private ValueAnimator getBzierAnimator(final ImageView iv) {  
    5. // TODO Auto-generated method stub  
    6. // 4个点的坐标  
    7. new BasEvaluator(PointFs[1], PointFs[2]);  
    8. 0], PointFs[3]);  
    9. new AnimatorUpdateListener() {  
    10.               
    11. @Override  
    12. public void onAnimationUpdate(ValueAnimator animation) {  
    13. // TODO Auto-generated method stub  
    14.             PointF p = (PointF) animation.getAnimatedValue();  
    15.             iv.setX(p.x);  
    16.             iv.setY(p.y);  
    17. 1- animation.getAnimatedFraction()); // 透明度  
    18.         }  
    19.     });  
    20.     valueAnim.setTarget(iv);  
    21. 3000);  
    22. new Random().nextInt(4)]);  
    23. return valueAnim;  
    24. }  
    25.   
    26. private PointF[] getPointFs(ImageView iv) {  
    27. // TODO Auto-generated method stub  
    28. new PointF[4];  
    29. 0] = new PointF(); // p0  
    30. 0].x = (mWidth- params.width)/ 2;  
    31. 0].y = mHeight - params.height;  
    32.       
    33. 1] = new PointF(); // p1  
    34. 1].x = new Random().nextInt(mWidth);    
    35. 1].y = new Random().nextInt(mHeight /2) + mHeight / 2 + params.height;  
    36.       
    37. 2] = new PointF(); // p2  
    38. 2].x = new Random().nextInt(mWidth);    
    39. 2].y = new Random().nextInt(mHeight /2);  
    40.           
    41. 3] = new PointF(); // p3  
    42. 3].x = new Random().nextInt(mWidth);    
    43. 3].y = 0;  
    44. return PointFs;  
    45. }

    先获得4个点的坐标

    Android直播sdk Android直播点赞_Android直播sdk_02


    p0坐标:x坐标((布局的宽-心形图片宽)除以2),y坐标(布局的高 -心形图片高),这样获得的是顶部部水平中心点的坐标。

    p1坐标:x坐标(横坐标中的随机位置),y坐标(布局一半的高度 加上 0到一半高度范围内的随机坐标+心形的高度的一半)。这样取到的横坐标是在布局宽度之内的随机坐标,纵坐标为整个路径高度中部以上的随机坐标。

    p2坐标:与p1类似,横坐标是在布局宽度之内的随机坐标,纵坐标为整个路径高度中部以下的随机坐标。

    p3坐标:控件底部中心点

    好了知道4个坐标了,那么开始计算路径

    首先为了计算贝塞尔曲线,我们先写一个估值器

    1. /**
    2.  * 
    3.  * 估值器,计算路径
    4.  * */  
    5. public class BasEvaluator implements TypeEvaluator<PointF> {  
    6.   
    7. private PointF p1;  
    8. private PointF p2;  
    9.   
    10. public BasEvaluator(PointF p1, PointF p2) {  
    11. super();  
    12. this.p1 = p1;  
    13. this.p2 = p2;  
    14.     }  
    15.   
    16. @Override  
    17. public PointF evaluate(float fraction, PointF p0, PointF p3) {  
    18. // TODO Auto-generated method stub  
    19. new PointF();  
    20.           
    21. // 贝塞尔曲线公式  p0*(1-t)^3 + 3p1*t*(1-t)^2 + 3p2*t^2*(1-t) + p3^3  
    22. 1-fraction) *(1-fraction ) * (1-fraction)  
    23. 3*p1.x * fraction *(1-fraction )*(1-fraction )  
    24. 3*p2.x *fraction  *fraction  *(1-fraction )  
    25.                    +p3.x*fraction *fraction *fraction ;   
    26. 1-fraction ) *(1-fraction ) * (1-fraction )  
    27. 3*p1.y * fraction *(1-fraction )*(1-fraction )  
    28. 3*p2.y *fraction  *fraction  *(1-fraction )  
    29.                 +p3.y*fraction *fraction *fraction ;   
    30. return pointf;  
    31.     }  
    32. }

    TypeEvaluator:估值器回调evaluate方法,用于动态的改变动画的属性值。


    evaluate三个参数:

    1.fraction,默认传入的就是(currentTime - startTime) / duration,动画执行的时间除以总的时间比值,可以理解为变化率。当duration到了的时候,正好,起始点变到终点。

    2.起始点

    3.终点

    根据三个参数,计算点的根据每毫秒的变化率,计算点的路径轨迹。

    好了贝塞尔曲线动画就讲完了,然后再把动画绑定到控件上。

    最后在MainActivity中根据点击事件,进行增加心型就好了。

      1. btn_press = (Button)findViewById(R.id.btn_press);  
      2. ll_love = (LoveLayout)findViewById(R.id.ll_love);  
      3. btn_press.setOnClickListener(new OnClickListener() {  
      4.               
      5. @Override  
      6. public void onClick(View v) {  
      7. // TODO Auto-generated method stub  
      8.         ll_love.addLoveView();  
      9.     }  
      10. });