仿抖音视频详情页的红心点赞动效

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.yibai.svideo.R;

import java.util.Random;

/**
 * zzw:2020/07/03
 * 在点击时将心形的图片 add 到整个 view 中,然后在执行动画
 */

public class LoveAnimator extends RelativeLayout {

  int timeout = 400;//双击间格毫秒延时
  long singleClickTime;//记录第一次点击的时间
  DoubleClickListener mDoubleClickListener;
  SimpleClickListener mSimpleClickListener;

  private Context mContext;
  final float[] num = {-30, -20, 0, 20, 30}; // 随机心形图片的角度

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

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

  public LoveAnimator(Context context, AttributeSet attrs, int defStyleAttr) {
    this(context, attrs, defStyleAttr, 0);
  }

  @SuppressLint("NewApi")
  public LoveAnimator(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    initView(context);
  }

  private void initView(Context context) {
    mContext = context;
    singleClickTime = System.currentTimeMillis();
    clickHandler = new Handler();
  }

  @Override
  protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(canvas);
    clickCount = 0;//切换新界面时,重置点击次数
  }

  //手指按下的点为(x1, y1)手指离开屏幕的点为(x2, y2)
  float x1 = 0;
  float x2 = 0;
  float y1 = 0;
  float y2 = 0;
  boolean isMove = false;
  private Handler clickHandler;
  private int clickCount = 0;//记录连续点击次数
  @SuppressLint("ClickableViewAccessibility")
  @Override
  public boolean onTouchEvent(final MotionEvent event) {
    super.onTouchEvent(event);

    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        clickCount++;
        //当手指按下的时候
        isMove = false;
        x1 = event.getX();
        y1 = event.getY();

        long newClickTime = System.currentTimeMillis();
        //双击以上事件都会调用心动动画
        if (newClickTime - singleClickTime < timeout) {
          //开始心动动画
          startSwipe(event);
          //调用双击事件
          if (mDoubleClickListener != null)
            mDoubleClickListener.onDoubleClick(this);
          //在双击事件中清除点击次数,防止有时多次点击触发单击事件
          clickCount = 0;
        } else {


        }
        singleClickTime = newClickTime;
        break;
      case MotionEvent.ACTION_MOVE:
        //当手指移动的时候
        x2 = event.getX();
        y2 = event.getY();
        if(Math.abs(x1-x2) > 50 || Math.abs(y1-y2) > 50){
          isMove = true;
        }
        break;
      case MotionEvent.ACTION_UP:
        clickHandler.postDelayed(new Runnable() {
          @Override
          public void run() {
            if (clickCount == 1) {
              if (mSimpleClickListener != null && !isMove)
                mSimpleClickListener.onSimpleClick(LoveAnimator.this);
            }else if(clickCount==2){
            }
            clickHandler.removeCallbacksAndMessages(null);
            //清空handler延时,并防内存泄漏
            clickCount = 0;//计数清零
          }
        },timeout);
        break;
    }
    return true;
  }

  /*@SuppressLint("ClickableViewAccessibility")
  @Override
  public boolean onTouchEvent(MotionEvent event) {

    // 首先,我们需要在触摸事件中做监听,当有触摸时,创建一个展示心形图片的 ImageView
    final ImageView imageView = new ImageView(mContext);

    // 设置图片展示的位置,需要在手指触摸的位置上方,即触摸点是心形的下方角的位置。所以我们需要将 ImageView 设置到手指的位置
    LayoutParams params = new LayoutParams(300, 300);
    params.leftMargin = (int) event.getX() - 150;
    params.topMargin = (int) event.getY() - 300;

    imageView.setImageDrawable(getResources().getDrawable(R.mipmap.ic_heart));
    imageView.setLayoutParams(params);
    addView(imageView);

    // 设置 imageView 动画
    AnimatorSet animatorSet = new AnimatorSet();
    animatorSet.play(scale(imageView, "scaleX", 2f, 0.9f, 100, 0)) // 缩放动画,X轴2倍缩小至0.9倍
        .with(scale(imageView, "scaleY", 2f, 0.9f, 100, 0)) // 缩放动画,Y轴2倍缩小至0.9倍
        .with(rotation(imageView, 0, 0, num[new Random().nextInt(4)])) // 旋转动画,随机旋转角度num={-30.-20,0,20,30}
        .with(alpha(imageView, 0, 1, 100, 0)) // 渐变透明度动画,透明度从0-1.
        .with(scale(imageView, "scaleX", 0.9f, 1, 50, 150)) // 缩放动画,X轴0.9倍缩小至1倍
        .with(scale(imageView, "scaleY", 0.9f, 1, 50, 150)) // 缩放动画,Y轴0.9倍缩小至1倍
        .with(translationY(imageView, 0, -600, 800, 400)) // 平移动画,Y轴从0向上移动600单位
        .with(alpha(imageView, 1, 0, 300, 400)) // 透明度动画,从1-0
        .with(scale(imageView, "scaleX", 1, 3f, 700, 400)) // 缩放动画,X轴1倍放大至3倍
        .with(scale(imageView, "scaleY", 1, 3f, 700, 400)); // 缩放动画,Y轴1倍放大至3倍
    animatorSet.start();

    // 我们不可能无限制的增加 view,在 view 消失之后,需要手动的移除改 imageView
    animatorSet.addListener(new AnimatorListenerAdapter() {
      @Override
      public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        removeViewInLayout(imageView);
      }
    });
    return super.onTouchEvent(event);
  }*/

  private void startSwipe(MotionEvent event){
    // 首先,我们需要在触摸事件中做监听,当有触摸时,创建一个展示心形图片的 ImageView
    final ImageView imageView = new ImageView(mContext);

    // 设置图片展示的位置,需要在手指触摸的位置上方,即触摸点是心形的下方角的位置。所以我们需要将 ImageView 设置到手指的位置
    LayoutParams params = new LayoutParams(300, 300);
    params.leftMargin = (int) event.getX() - 150;
    params.topMargin = (int) event.getY() - 300;

    imageView.setImageDrawable(getResources().getDrawable(R.mipmap.ic_heart));
    imageView.setLayoutParams(params);
    addView(imageView);

    // 设置 imageView 动画
    AnimatorSet animatorSet = new AnimatorSet();
    animatorSet.play(scale(imageView, "scaleX", 2f, 0.9f, 100, 0)) // 缩放动画,X轴2倍缩小至0.9倍
            .with(scale(imageView, "scaleY", 2f, 0.9f, 100, 0)) // 缩放动画,Y轴2倍缩小至0.9倍
            .with(rotation(imageView, 0, 0, num[new Random().nextInt(4)])) // 旋转动画,随机旋转角度num={-30.-20,0,20,30}
            .with(alpha(imageView, 0, 1, 100, 0)) // 渐变透明度动画,透明度从0-1.
            .with(scale(imageView, "scaleX", 0.9f, 1, 50, 150)) // 缩放动画,X轴0.9倍缩小至1倍
            .with(scale(imageView, "scaleY", 0.9f, 1, 50, 150)) // 缩放动画,Y轴0.9倍缩小至1倍
            .with(translationY(imageView, 0, -600, 800, 400)) // 平移动画,Y轴从0向上移动600单位
            .with(alpha(imageView, 1, 0, 300, 400)) // 透明度动画,从1-0
            .with(scale(imageView, "scaleX", 1, 3f, 700, 400)) // 缩放动画,X轴1倍放大至3倍
            .with(scale(imageView, "scaleY", 1, 3f, 700, 400)); // 缩放动画,Y轴1倍放大至3倍
    animatorSet.start();

    // 我们不可能无限制的增加 view,在 view 消失之后,需要手动的移除改 imageView
    animatorSet.addListener(new AnimatorListenerAdapter() {
      @Override
      public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        removeViewInLayout(imageView);
      }
    });
  }

  public static ObjectAnimator scale(View view, String propertyName, float from, float to, long time, long delayTime) {
    ObjectAnimator translation = ObjectAnimator.ofFloat(view
        , propertyName
        , from, to);
    translation.setInterpolator(new LinearInterpolator());
    translation.setStartDelay(delayTime);
    translation.setDuration(time);
    return translation;
  }

  public static ObjectAnimator translationX(View view, float from, float to, long time, long delayTime) {
    ObjectAnimator translation = ObjectAnimator.ofFloat(view
        , "translationX"
        , from, to);
    translation.setInterpolator(new LinearInterpolator());
    translation.setStartDelay(delayTime);
    translation.setDuration(time);
    return translation;
  }

  public static ObjectAnimator translationY(View view, float from, float to, long time, long delayTime) {
    ObjectAnimator translation = ObjectAnimator.ofFloat(view
        , "translationY"
        , from, to);
    translation.setInterpolator(new LinearInterpolator());
    translation.setStartDelay(delayTime);
    translation.setDuration(time);
    return translation;
  }

  public static ObjectAnimator alpha(View view, float from, float to, long time, long delayTime) {
    ObjectAnimator translation = ObjectAnimator.ofFloat(view
        , "alpha"
        , from, to);
    translation.setInterpolator(new LinearInterpolator());
    translation.setStartDelay(delayTime);
    translation.setDuration(time);
    return translation;
  }

  public static ObjectAnimator rotation(View view, long time, long delayTime, float... values) {
    ObjectAnimator rotation = ObjectAnimator.ofFloat(view, "rotation", values);
    rotation.setDuration(time);
    rotation.setStartDelay(delayTime);
    rotation.setInterpolator(new TimeInterpolator() {
      @Override
      public float getInterpolation(float input) {
        return input;
      }
    });
    return rotation;
  }

  /**
   * 接口
   */
  public interface DoubleClickListener {
    void onDoubleClick(View view);
  }

  /**
   * 单击接口
   */
  public interface SimpleClickListener {
    void onSimpleClick(View view);
  }

  /**
   * 单击接口监听的方法
   *
   * @param mSimpleClickListener 单击监听
   */
  public void setOnSimpleClickListener(
          final SimpleClickListener mSimpleClickListener) {
    this.mSimpleClickListener = mSimpleClickListener;
  }

  /**
   * 双击接口监听的方法
   *
   * @param mDoubleClickListener 双击监听
   */
  public void setOnDoubleClickListener(
          final DoubleClickListener mDoubleClickListener) {
    this.mDoubleClickListener = mDoubleClickListener;
  }
}

你可能感兴趣的:(android)