2018年抖音、快手、火山等短視訊App比較火,最近自己做短視訊項目時有個需求,就是類似抖音的點贊特效,單擊螢幕時視訊暫停,再次點選時視訊恢複播放,輕按兩下或者連續多次點選時出現點贊特效(飄小心心特效),而且是全屏可以随意點選,都是可以響應輕按兩下及多擊事件。我們的需求是點贊效果出現的同時請求接口,是以還是遇到很多問題的,這裡記錄一下.先放上一張抖音的點贊效果截圖如下:
:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLwIjNzUDMzMjMyATMwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.gif)
分析一下效果圖:
1.當手指單擊螢幕時,視訊暫停播放,再次點選螢幕視訊恢複播放.
2.當連續點選螢幕時,響應輕按兩下事件出現小心心特效,而且點選次數為兩次或者兩次以上.
3.單擊暫停視訊時和輕按兩下點贊同時可以響應,兩個事件事件互不沖突.
4.點選整個螢幕都可以響應單擊和輕按兩下事件.
5.多次點選時間間隔要設定在短時間内不響應,要不會出現多次響應,重複點贊(我們的需求是輕按兩下或者多擊時請求點贊接口).
實作過程如下:
1.自定義點贊view
private Context mContext;
float[] num = {-30, -20, 0, 20, 30};//随機心形圖檔角度
//記錄上一次的點選時間
private long lastClickTime = 0;
//點選的時間間隔
private long INTERVAL = 200;
private MyClickListener.MyClickCallBack onClickListener;
public Like(Context context) {
super(context);
initView(context);
}
public Like(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public Like(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
private void initView(Context context) {
mContext = context;
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//擷取點選時間
long currTime = System.currentTimeMillis();
//判斷點選之間的時間差
long interval = currTime - lastClickTime;
lastClickTime = currTime;
if(interval <INTERVAL ){//小于1秒,攔截事件,并做處理
final ImageView imageView = new ImageView(mContext);
//設定展示的位置,需要在手指觸摸的位置上方,即觸摸點是心形的右下角的位置
LayoutParams params = new LayoutParams(300, 300);
params.leftMargin = (int) event.getX() - 150;
params.topMargin = (int) event.getY() - 300;
//設定圖檔資源
imageView.setImageDrawable(getResources().getDrawable(R.mipmap.sp_dianzanhou_da));
imageView.setLayoutParams(params);
//把IV添加到父布局當中
addView(imageView);
//設定控件的動畫
AnimatorSet animatorSet = new AnimatorSet();
//縮放動畫,X軸2倍縮小至0.9倍
animatorSet.play(scale(imageView, "scaleX", 2f, 0.9f, 100, 0))
//縮放動畫,Y軸2倍縮放至0.9倍
.with(scale(imageView, "scaleY", 2f, 0.9f, 100, 0))
//旋轉動畫,随機旋轉角
.with(rotation(imageView, 0, 0, num[new Random().nextInt(4)]))
//漸變透明動畫,透明度從0-1
.with(alpha(imageView, 0, 1, 100, 0))
//縮放動畫,X軸0.9倍縮小至
.with(scale(imageView, "scaleX", 0.9f, 1, 50, 150))
//縮放動畫,Y軸0.9倍縮放至
.with(scale(imageView, "scaleY", 0.9f, 1, 50, 150))
//位移動畫,Y軸從0上移至600
.with(translationY(imageView, 0, -600, 800, 400))
//透明動畫,從1-0
.with(alpha(imageView, 1, 0, 300, 400))
//縮放動畫,X軸1至3倍
.with(scale(imageView, "scaleX", 1, 3f, 700, 400))
//縮放動畫,Y軸1至3倍
.with(scale(imageView, "scaleY", 1, 3f, 700, 400));
//開始動畫
animatorSet.start();
//設定動畫結束監聽
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
//當動畫結束以後,需要把控件從父布局移除
removeViewInLayout(imageView);
}
});
}
break;
}
return super.dispatchTouchEvent(event);
}
/**
* 縮放動畫
* @param view
* @param propertyName
* @param from
* @param to
* @param time
* @param delayTime
* @return
*/
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;
}
/**
* 位移動畫
* @param view
* @param from
* @param to
* @param time
* @param delayTime
* @return
*/
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;
}
/**
* 透明度動畫
* @param view
* @param from
* @param to
* @param time
* @param delayTime
* @return
*/
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 void setOnClickListener(MyClickListener.MyClickCallBack onClickListener) {
this.onClickListener = onClickListener;
}
public MyClickListener.MyClickCallBack getOnClickListener() {
return onClickListener;
}
}
2.事件監聽類MyClickListener
public class MyClickListener implements View.OnTouchListener {
private static int timeout=400;//輕按兩下間四百毫秒延時
private int clickCount = 0;//記錄連續點選次數
private Handler handler;
private MyClickCallBack myClickCallBack;
public interface MyClickCallBack{
void oneClick();//點選一次的回調
void doubleClick();//輕按兩下及連續多次點選的回調
}
public MyClickListener(MyClickCallBack myClickCallBack) {
this.myClickCallBack = myClickCallBack;
handler = new Handler();
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
clickCount++;
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (clickCount == 1) {
myClickCallBack.oneClick();
}else if(clickCount>=2){
myClickCallBack.doubleClick();
}
handler.removeCallbacksAndMessages(null);
//清空handler延時,并防記憶體洩漏
clickCount = 0;//計數清零
}
},timeout);//延時timeout後執行run方法中的代碼
}
return false;//讓點選事件繼續傳播,友善再給View添加其他事件監聽
}
}
3.布局檔案代碼:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/banner">
<com.example.administrator.timertask.view.Like
android:id="@+id/like"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.example.administrator.timertask.view.Like>
</android.support.constraint.ConstraintLayout>
4.Activity代碼:
/**
* 作者: njb
* 時間: 2018/12/13 14:55
* 描述:
* 來源:
*/
public class LikeActivity extends AppCompatActivity {
private Like like;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_like);
initView();
}
private void initView() {
like = findViewById(R.id.like);
like.setOnClickListener(new MyClickListener.MyClickCallBack() {
@Override
public void oneClick() {
Toast.makeText(LikeActivity.this,"單擊事件",Toast.LENGTH_SHORT).show();
}
@Override
public void doubleClick() {
Toast.makeText(LikeActivity.this,"輕按兩下或多擊事件",Toast.LENGTH_SHORT).show();
}
});
}
}
5.以上就是單擊和輕按兩下及多擊事件監聽和點贊動畫自定義view實作,由于時間問題後面會加上視訊播放、單擊暫停等,慢慢完善例子,并給出源碼,寫得不好,還望大家見諒,有問題大家可以提出一起探讨解決.
點贊動畫源碼位址:https://gitee.com/jackning_admin/LoveClick