抖音APP双击点赞效果实现
春天来了,万物复苏,大草原又到了动物们交配的季节。。。
相信大部分的同学都有刷抖音的经历吧,那么当你疯狂给小姐姐点赞的时候,有没有想过这个蹦出来的那些疯狂跳动的心心的是怎么实现的呢?
= 。=,先看效果预览
分析:
效果特点:
1.双击屏幕任意位置,就生成一个心动图
2.心动图不断放大
3.心动图逐渐消失
开始:
1.创建一个新的项目,添加一个class并取名为HotHeartFrameLayout,继承FrameLayout,如下:
ublic class HeartFrameLayout extends FrameLayout{
public HeartFrameLayout(@NonNull Context context) {
super(context);
}
public HeartFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
//这里绘制图形
}
}
2.创建一个HeartBean,用来存放需要绘制的心形图属性:
public class HeartBean {
int alpha; // 透明度
int X; // X坐标点
int Y; // Y坐标点
float scanle; // 缩放比例
int degrees; // 旋转角度
Paint paint; //
}
3.创建一个Handler,用来处理界面刷新,表现出动画的效果:
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
Refresh();
invalidate();
if (list != null && list.size() > 0) {
sendEmptyMessageDelayed(0, refreshRate);// 延时
}
break;
default:
break;
}
}
}
4.初始化相关值:
List<HeartBean> list;//存放多个心形图
int MaxAlpha = 255;//透明度,默认为255,0为消失不可见
boolean START = true;//true为开始动画,false为结束动画
int refreshRate = 16;//动画刷新频率
int degreesMin = -30;//最小旋转角度
int degreesMax = 30;//最大旋转角度
MyHandler handler = new MyHandler();
Bitmap bitmap;//初始图片
Matrix matrix = new Matrix();//控制bitmap旋转角度和缩放的矩阵
5.不断刷新图片
/***
* 刷新
*/
private void Refresh() {
for (int i = 0; i < list.size(); i++) {
HeartBean bean = list.get(i);
if (!START && bean.alpha == 0) {
list.remove(i);
bean.paint = null;
continue;
} else if (START) {
START = false;
}
bean.scanle += refreshRate > 16 ? 0.03 : 0.1;//放大倍数 默认0.1
bean.alpha -= 10;//透明度
if (bean.alpha < 0) {
bean.alpha = 0;
}
bean.paint.setAlpha(bean.alpha);
}
}
原理是通过不断的更新图片缩放和透明度,来让图片逐渐放大并同时逐渐消失的效果。
6.双击事件时调用
/**
* 开始心动动画
*
* @param event 点击事件
*/
private void startSwipe(MotionEvent event) {
//
HeartBean bean = new HeartBean();
bean.scanle = 1; //
bean.alpha = MaxAlpha; //
bean.X = (int) event.getX(); //
bean.Y = (int) event.getY(); //
bean.paint = initPaint(bean.alpha);
bean.degrees = degrees(degreesMin, degreesMax);
if (list.size() == 0) {
START = true;
}
list.add(bean);
invalidate();
if (START) {
handler.sendEmptyMessage(0);
}
}
7.双击事件监听:
DoubleClickListener mDoubleClickListener;
int timeout = 400;//双击间格毫秒延时
long singleClickTime;//记录第一次点击的时间
@Override
public boolean onTouchEvent(final MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
long newClickTime = System.currentTimeMillis();
//双击以上事件都会调用心动动画
if (newClickTime - singleClickTime < timeout) {
//开始心动动画
startSwipe(event);
//调用双击事件
if (mDoubleClickListener != null)
mDoubleClickListener.onDoubleClick(this);
}
singleClickTime = newClickTime;
break;
}
return true;
}
/**
* 接口
*/
public interface DoubleClickListener {
void onDoubleClick(View view);
}
/**
* 双击监听接口的方法
*
* @param mDoubleClickListener 双击监听
*/
public void setOnDoubleClickListener(
final DoubleClickListener mDoubleClickListener) {
this.mDoubleClickListener = mDoubleClickListener;
}
8.绘制图片:
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
for (int i = 0; i < list.size(); i++) {
HeartBean heartBean = list.get(i);
// 重置
matrix.reset();
// 缩放原图
matrix.postScale(heartBean.scanle,
heartBean.scanle,
heartBean.X + bitmap.getWidth() / 2,
heartBean.Y + bitmap.getHeight() / 2);
// 旋转
matrix.postRotate(heartBean.degrees,
heartBean.X + bitmap.getWidth() / 2,
heartBean.Y + bitmap.getHeight() / 2);
canvas.save();
canvas.concat(matrix);
canvas.drawBitmap(bitmap,
heartBean.X - bitmap.getWidth() / 2,
heartBean.Y - bitmap.getHeight() / 2,
heartBean.paint);
canvas.restore();
}
}
简单使用
如果觉得自己写起来很不耐烦,没关系,我已经将上面的效果做了一个很好的封装,希望对你有用~
下面简单说下使用方法:
第一步: 在项目根目录的build.gradle文件中加入
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
第二步: 添加依赖项
dependencies {
implementation 'com.github.KevinYou128:HotHeart:v1.1'
}
第三步:直接在布局文件里调用
<com.yqw.hotheart.HeartFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:degrees_interval_max="20"
app:degrees_interval_min="-20"
app:swipe_image="@drawable/ic_heart"
tools:context=".MainActivity">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/douyin" />
</com.yqw.hotheart.HeartFrameLayout>
直接在你的父布局外层包裹上hotheart布局就可以了,另外,考虑到缩减布局层数,我特意添加了HeartLinearLayout、HeartConstraintLayout、HeartRelativeLayout、HeartFrameLayout等父容器,你可以直接使用它们来替换你的原生布局,以达到缩减布局层数的效果。
XML属性说明
swipe_image:点击时需要显示的图片
refresh_rate:设置动画刷新频率,默认为16,数值越大动画表现越慢,建议使用默认就好了
degrees_interval_min:图片最小旋转角度,默认-30,取值范围为-360到360(注意取值小于或等于max)
degrees_interval_max:图片最大旋转角度,默认30,取值范围为-360到360(注意取值大于或等于min)
java代码属性说明
setOnDoubleClickListener:双击事件监听
示例:
heartViewGroup.setOnDoubleClickListener(new HeartViewGroup.DoubleClickListener() {
@Override
public void onDoubleClick(View view) {
//双击事件处理
}
});
setSwipeImage(int id):设置点击时需要显示的图片
setRefreshRate(int refreshRate):设置动画刷新频率,默认为16,数值越大动画表现越慢,建议使用默认就好了
setDegreesInterval(int min,int max):设置图片旋转角度区间,默认-30到30
min取值范围为-360到360
max取值范围为-360到360
如果还有不明白的地方,可以去查看源码=。=
欢迎star~~