高仿抖音播放(三)——细节的优化
这是第「31篇」原创分享
朝阳杨少爷(ID:CY_YANG_DA_YE),专注于Android领域的开发者。
上
一篇文章,我们着重实现了 上下滑动播放详情页, 播放之后自动播放
接下来,我们要实现的就是 双击点赞效果,并且点赞, 单击暂停,再单击播放这两个功能。
欢迎star!
首先,实现以下双击点击的动画效果。
这个动画,可以看到要实现的效果。
可以看到,主要有以下几个功能点。
1. 缩放的动画
2. 位移的动画
3. 透明度的动画
4. 还有一个点击的动作的监听
梳理完功能点之后,就比较好实现对应的效果了。
三个动画效果,我们可以直接用ObjectAnimator这个类来实现。
点击效果,自然就涉及到了 dispatchTouchEvent
梳理完要实现的效果和方法之后,详细就看代码。
我们自定义了一个点赞的动画。
package com.yang.dyvideo.widget;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.content.Context;
import android.graphics.Canvas;
import android.support.annotation.Nullable;
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.yang.dyvideo.R;
import com.yang.dyvideo.presenter.MyClickListener;
import java.util.Random;
/**
* @author yangzc
* @data 2019/5/31 13:13
* @desc
*/
public class VideoLikeView extends RelativeLayout {
private Context mContext;
float[] num = {-30, -20, 0, 20, 30};//随机心形图片角度
//记录上一次的点击时间
private long lastClickTime = 0;
//点击的时间间隔
private long INTERVAL = 200;
private MyClickListener.MyClickCallBack onClickListener;
public VideoLikeView(Context context) {
super(context);
initView(context);
}
public VideoLikeView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public VideoLikeView(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 ){
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.ic_heart));
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;
}
}
接下来,我们就要实现单击暂停、播放的功能
因为这个功能也涉及到了的点击,所以,我们就需要区分一下在屏幕上是双击,还是单击。
双击就是点赞的动画,单击就是播放、暂停的功能。
在这里,采用的Handler的postDelayed方法,来区分两次点击之间的延时点击时间timeout,同时设计一个连续点击的计数器clickCount来记录在timeout的时间里的点击次数。clickCount为1则是播放、暂停的方法,如果 clickCount为2 则为点赞的效果。
理清了思路,接下来我们看一下实现的代码。
mAdapter!!.setOnItemClickListener(object : VideoPlayAdapter.OnItemClickListener {
var timeout = 500//双击间百毫秒延时
var clickCount = 0//记录连续点击次数
var handler = Handler()
override fun onItemClick(view: View, position: Int) {
clickCount++
val mini_surface_view = view.findViewById<FullWindowVideoView>(R.id.surface_view)
view.setOnTouchListener { v, event ->
if (event.action == MotionEvent.ACTION_DOWN) {
handler.postDelayed({
if (clickCount == 1) {
if (mini_surface_view.isPlaying()) {
mini_surface_view.pause()
iv_video_play.setVisibility(View.VISIBLE)
} else {
iv_video_play.setVisibility(View.GONE)
val mediaPlayer = arrayOfNulls<MediaPlayer>(1)
mini_surface_view.setOnPreparedListener(MediaPlayer.OnPreparedListener { })
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
mini_surface_view.setOnInfoListener(MediaPlayer.OnInfoListener { mp, what, extra ->
mediaPlayer[0] = mp
mp.isLooping = true
mp.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT)
false
})
}
mini_surface_view.start()
}
} else if (clickCount >= 2) {
if (!videolist?.get(position)!!.like) {
praiseMethod(position)
}
}
handler.removeCallbacksAndMessages(null)
//清空handler延时,并防内存泄漏
clickCount = 0//计数清零
}, timeout.toLong())//延时timeout后执行run方法中的代码
}
false
}
}
})
至此,我们要实现的整个功能都完成了。
欢迎**“点赞”、“关注”**。
如果要有任何问题、BUG欢迎给我留言。
点击查看更多内容
1人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦