1. 程式人生 > >仿抖音視訊詳情頁點贊紅心動效

仿抖音視訊詳情頁點贊紅心動效

GitHub地址:

https://github.com/selfconzrr/LikeAnimator

可直接測試執行

核心思路:

自定義 View 繼承自 RelativeLayout ,重寫 onTouchEvent,在點選時觸發將心形的圖片 add 到整個 view 中,然後在執行動畫。主要的處理邏輯都在 onTouchEvent() 事件中。

首先,我們需要在觸控事件中做監聽,當有觸控時,建立一個展示心形圖片的 ImageView;然後設定圖片展示的位置,需要在手指觸控的位置上方,即觸控點是心形的下方角的位置;接下來設定 imageView 動畫 AnimatorSet,並記住:我們不可能無限制的增加 view,在 view 消失之後,需要手動的移除改 imageView。

package com.example.zhangruirui.likeanimator;

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.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.animation.LinearInterpolator; import android.widget.ImageView; import android.widget.RelativeLayout; import java.util.Random; /** * ZhangRuirui:2018/08/31 * 在點選時觸發將心形的圖片 add 到整個 view 中,然後在執行動畫。主要的處理邏輯都在 onTouchEvent() 事件中 */
public class LoveAnimator extends RelativeLayout { 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; } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); } @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.drawable.details_icon_like_pressed)); 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); } 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; } }