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

    技术2023-05-25  95

    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; } }
    Processed: 0.018, SQL: 12