当前位置 : 主页 > 手机开发 > android >

Android仿直播特效之点赞飘心效果

来源:互联网 收集:自由互联 发布时间:2021-08-03
本文实例为大家分享了Android实现点赞飘心效果的具体代码,供大家参考,具体内容如下 一、概述 老规矩先上图 好了,基本就是这个样子,录完的视频用格式工厂转换完就这个样子了,

本文实例为大家分享了Android实现点赞飘心效果的具体代码,供大家参考,具体内容如下

一、概述

老规矩先上图

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

二、定义我们自己的Layout

/** 
 * @author 刘洋巴金 
 * @date 2017-4-27 
 * 
 * 定义我们自己的布局 
 * */ 
public class LoveLayout extends RelativeLayout{ 
 
 private Context context; 
 private LayoutParams params; 
 private Drawable[] icons = new Drawable[4]; 
 private Interpolator[] interpolators = new Interpolator[4]; 
 private int mWidth; 
 private int mHeight; 
 
 public LoveLayout(Context context, AttributeSet attrs) { 
 super(context, attrs); 
  
 this.context = context; 
 initView(); 
 } 
 
 private void initView() { 
  
 // 图片资源 
 icons[0] = getResources().getDrawable(R.drawable.green); 
 icons[1] = getResources().getDrawable(R.drawable.purple); 
 icons[2] = getResources().getDrawable(R.drawable.red); 
 icons[3] = getResources().getDrawable(R.drawable.yellow); 
  
 // 插值器 
 interpolators[0] = new AccelerateDecelerateInterpolator(); // 在动画开始与结束的地方速率改变比较慢,在中间的时候加速 
 interpolators[1] = new AccelerateInterpolator(); // 在动画开始的地方速率改变比较慢,然后开始加速 
 interpolators[2] = new DecelerateInterpolator(); // 在动画开始的地方快然后慢 
 interpolators[3] = new LinearInterpolator(); // 以常量速率改变 
  
 int width = icons[0].getIntrinsicWidth(); 
 int height = icons[0].getIntrinsicWidth(); 
 params = new LayoutParams(width, height); 
 params.addRule(CENTER_HORIZONTAL, TRUE); 
 params.addRule(ALIGN_PARENT_BOTTOM, TRUE); 
 } 

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

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
 // TODO Auto-generated method stub 
 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
 mWidth = getMeasuredWidth(); 
 mHeight = getMeasuredHeight(); 
} 
 
public void addLoveView() { 
 // TODO Auto-generated method stub 
 final ImageView iv = new ImageView(context); 
 iv.setLayoutParams(params); 
 iv.setImageDrawable(icons[new Random().nextInt(4)]); 
 addView(iv); 
  
 // 开启动画,并且用完销毁 
 AnimatorSet set = getAnimatorSet(iv); 
 set.start(); 
 set.addListener(new AnimatorListenerAdapter() { 
 @Override 
 public void onAnimationEnd(Animator animation) { 
  // TODO Auto-generated method stub 
  super.onAnimationEnd(animation); 
  removeView(iv); 
 } 
 }); 
} 

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

/** 
 * 获取动画集合 
 * @param iv 
 * */ 
private AnimatorSet getAnimatorSet(ImageView iv) { 
  
 // 1.alpha动画 
 ObjectAnimator alpha = ObjectAnimator.ofFloat(iv, "alpha", 0.3f, 1f); 
  
 // 2.缩放动画 
 ObjectAnimator scaleX = ObjectAnimator.ofFloat(iv, "scaleX", 0.2f, 1f); 
 ObjectAnimator scaleY = ObjectAnimator.ofFloat(iv, "scaleY", 0.2f, 1f); 
  
 // 动画集合 
 AnimatorSet set = new AnimatorSet(); 
 set.playTogether(alpha, scaleX, scaleY); 
 set.setDuration(500); 
  
 // 贝塞尔曲线动画 
 ValueAnimator bzier = getBzierAnimator(iv); 
  
 AnimatorSet set2 = new AnimatorSet(); 
 set2.playSequentially(set, bzier); 
 set2.setTarget(iv); 
 return set2; 
} 

playTogether:几个动画同时执行
ObjectAnimator为属性动画,不熟悉可以百度了解下

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

playSequentially:动画依次执行

/** 
 * 贝塞尔动画 
 * */ 
private ValueAnimator getBzierAnimator(final ImageView iv) { 
 // TODO Auto-generated method stub 
 PointF[] PointFs = getPointFs(iv); // 4个点的坐标 
 BasEvaluator evaluator = new BasEvaluator(PointFs[1], PointFs[2]); 
 ValueAnimator valueAnim = ValueAnimator.ofObject(evaluator, PointFs[0], PointFs[3]); 
 valueAnim.addUpdateListener(new AnimatorUpdateListener() { 
  
 @Override 
 public void onAnimationUpdate(ValueAnimator animation) { 
  // TODO Auto-generated method stub 
  PointF p = (PointF) animation.getAnimatedValue(); 
  iv.setX(p.x); 
  iv.setY(p.y); 
  iv.setAlpha(1- animation.getAnimatedFraction()); // 透明度 
 } 
 }); 
 valueAnim.setTarget(iv); 
 valueAnim.setDuration(3000); 
 valueAnim.setInterpolator(interpolators[new Random().nextInt(4)]); 
 return valueAnim; 
} 
 
private PointF[] getPointFs(ImageView iv) { 
 // TODO Auto-generated method stub 
 PointF[] PointFs = new PointF[4]; 
 PointFs[0] = new PointF(); // p0 
 PointFs[0].x = (mWidth- params.width)/ 2; 
 PointFs[0].y = mHeight - params.height; 
 
 PointFs[1] = new PointF(); // p1 
 PointFs[1].x = new Random().nextInt(mWidth); 
 PointFs[1].y = new Random().nextInt(mHeight /2) + mHeight / 2 + params.height; 
 
 PointFs[2] = new PointF(); // p2 
 PointFs[2].x = new Random().nextInt(mWidth); 
 PointFs[2].y = new Random().nextInt(mHeight /2); 
  
 PointFs[3] = new PointF(); // p3 
 PointFs[3].x = new Random().nextInt(mWidth); 
 PointFs[3].y = 0; 
 return PointFs; 
} 

先获得4个点的坐标

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

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

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

p3坐标:控件底部中心点

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

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

/** 
 * @author 刘洋巴金 
 * @date 2017-4-27 
 * 
 * 估值器,计算路径 
 * */ 
public class BasEvaluator implements TypeEvaluator<PointF> { 
 
 private PointF p1; 
 private PointF p2; 
 
 public BasEvaluator(PointF p1, PointF p2) { 
 super(); 
 this.p1 = p1; 
 this.p2 = p2; 
 } 
 
 @Override 
 public PointF evaluate(float fraction, PointF p0, PointF p3) { 
 // TODO Auto-generated method stub 
 PointF pointf = new PointF(); 
  
 // 贝塞尔曲线公式 p0*(1-t)^3 + 3p1*t*(1-t)^2 + 3p2*t^2*(1-t) + p3^3 
 pointf.x = p0.x * (1-fraction) *(1-fraction ) * (1-fraction) 
   +3*p1.x * fraction *(1-fraction )*(1-fraction ) 
   +3*p2.x *fraction *fraction *(1-fraction ) 
   +p3.x*fraction *fraction *fraction ; 
 pointf.y = p0.y * (1-fraction ) *(1-fraction ) * (1-fraction ) 
  +3*p1.y * fraction *(1-fraction )*(1-fraction ) 
  +3*p2.y *fraction *fraction *(1-fraction ) 
  +p3.y*fraction *fraction *fraction ; 
 return pointf; 
 } 
} 

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

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

2.起始点

3.终点

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

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

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

btn_press = (Button)findViewById(R.id.btn_press); 
ll_love = (LoveLayout)findViewById(R.id.ll_love); 
btn_press.setOnClickListener(new OnClickListener() { 
  
 @Override 
 public void onClick(View v) { 
 // TODO Auto-generated method stub 
 ll_love.addLoveView(); 
 } 
}); 

三、Demo

Android实现点赞飘心效果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自由互联。

网友评论