实现点赞效果动画,可以根据需求进行修改使用。
先上个Gif图:
1. 自定义DivergeView :
import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.PointF;import android.util.AttributeSet;import android.view.View;import java.util.ArrayList;import java.util.Collections;import java.util.Iterator;import java.util.List;import java.util.Random;public class DivergeView extends View implements Runnable { public static final float mDuration = 0.01F; public static final int mDefaultHeight = 100; protected static final long mQueenDuration = 200L; protected final Random mRandom; protected ArrayList mDivergeInfos; protected List mQueen; protected PointF mPtStart; protected PointF mPtEnd; protected ArrayList mDeadPool; private Paint mPaint; private DivergeViewProvider mDivergeViewProvider; private long mLastAddTime; private Thread mThread; private boolean mRunning; private boolean mIsDrawing; public DivergeView(Context context) { this(context, (AttributeSet) null); } public DivergeView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public DivergeView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.mRandom = new Random(); this.mDeadPool = new ArrayList(); this.mLastAddTime = 0L; this.mRunning = true; this.mIsDrawing = false; this.init(); } public void run() { while (this.mRunning) { if (this.mDivergeViewProvider != null && this.mQueen != null && !this.mIsDrawing && this.mDivergeInfos != null) { this.dealQueen(); if (this.mDivergeInfos.size() != 0) { this.dealDiverge(); this.mIsDrawing = true; this.postInvalidate(); } } } this.release(); } private void dealDiverge() { for (int i = 0; i < this.mDivergeInfos.size(); ++i) { DivergeInfo divergeInfo = (DivergeInfo) this.mDivergeInfos.get(i); float timeLeft = 1.0F - divergeInfo.mDuration; divergeInfo.mDuration += 0.01F; float time1 = timeLeft * timeLeft; float time2 = 2.0F * timeLeft * divergeInfo.mDuration; float time3 = divergeInfo.mDuration * divergeInfo.mDuration; float x = time1 * this.mPtStart.x + time2 * divergeInfo.mBreakPoint.x + time3 * divergeInfo.mEndPoint.x; divergeInfo.mX = x; float y = time1 * this.mPtStart.y + time2 * divergeInfo.mBreakPoint.y + time3 * divergeInfo.mEndPoint.y; divergeInfo.mY = y; if (divergeInfo.mY <= divergeInfo.mEndPoint.y) { this.mDivergeInfos.remove(i); this.mDeadPool.add(divergeInfo); --i; } } } private void dealQueen() { long now = System.currentTimeMillis(); if (this.mQueen.size() > 0 && now - this.mLastAddTime > 200L) { this.mLastAddTime = System.currentTimeMillis(); DivergeInfo divergeInfo = null; if (this.mDeadPool.size() > 0) { divergeInfo = (DivergeInfo) this.mDeadPool.get(0); this.mDeadPool.remove(0); } if (divergeInfo == null) { divergeInfo = this.createDivergeNode(this.mQueen.get(0)); } divergeInfo.reset(); divergeInfo.mType = this.mQueen.get(0); this.mDivergeInfos.add(divergeInfo); this.mQueen.remove(0); } } private void init() { this.mPaint = new Paint(1); } protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); } public void setDivergeViewProvider(DivergeViewProvider divergeViewProvider) { this.mDivergeViewProvider = divergeViewProvider; } public PointF getStartPoint() { return this.mPtStart; } public boolean isRunning() { return this.mRunning; } public void startDiverges(Object obj) { if (this.mDivergeInfos == null) { this.mDivergeInfos = new ArrayList(30); } if (this.mQueen == null) { this.mQueen = Collections.synchronizedList(new ArrayList(30)); } this.mQueen.add(obj); if (this.mThread == null) { this.mThread = new Thread(this); this.mThread.start(); } } public void stop() { if (this.mDivergeInfos != null) { this.mDivergeInfos.clear(); } if (this.mQueen != null) { this.mQueen.clear(); } if (this.mDeadPool != null) { this.mDeadPool.clear(); } } public void release() { this.stop(); this.mPtEnd = null; this.mPtStart = null; this.mDivergeInfos = null; this.mQueen = null; this.mDeadPool = null; } public void setStartPoint(PointF point) { this.mPtStart = point; } public void setEndPoint(PointF point) { this.mPtEnd = point; } protected void onDetachedFromWindow() { super.onDetachedFromWindow(); this.mRunning = false; } protected void onDraw(Canvas canvas) { if (this.mRunning && this.mDivergeViewProvider != null && this.mDivergeInfos != null) { Iterator var2 = this.mDivergeInfos.iterator(); while (var2.hasNext()) { DivergeInfo divergeInfo = (DivergeInfo) var2.next(); this.mPaint.setAlpha((int) (255.0F * divergeInfo.mY / this.mPtStart.y)); canvas.drawBitmap(this.mDivergeViewProvider.getBitmap(divergeInfo.mType), divergeInfo.mX, divergeInfo.mY, this.mPaint); } } this.mIsDrawing = false; } private PointF getBreakPointF(int scale1, int scale2) { PointF pointF = new PointF(); pointF.x = (float) (this.mRandom.nextInt((this.getMeasuredWidth() - this.getPaddingRight() + this.getPaddingLeft()) / scale1) + this.getMeasuredWidth() / scale2); pointF.y = (float) (this.mRandom.nextInt((this.getMeasuredHeight() - this.getPaddingBottom() + this.getPaddingTop()) / scale1) + this.getMeasuredHeight() / scale2); return pointF; } protected DivergeInfo createDivergeNode(Object type) { PointF endPoint = this.mPtEnd; if (endPoint == null) { endPoint = new PointF((float) this.mRandom.nextInt(this.getMeasuredWidth()), 0.0F); } if (this.mPtStart == null) { this.mPtStart = new PointF((float) (this.getMeasuredWidth() / 2), (float) (this.getMeasuredHeight() - 100)); } return new DivergeInfo(this.mPtStart.x, this.mPtStart.y, this.getBreakPointF(2, 3), endPoint, type); } public class DivergeInfo { public float mDuration = 0.0F; public PointF mBreakPoint; public PointF mEndPoint; public float mX; public float mY; public Object mType; public float mStartX; public float mStartY; public DivergeInfo(float x, float y, PointF breakPoint, PointF endPoint, Object type) { this.mEndPoint = endPoint; this.mX = x; this.mY = y; this.mStartX = x; this.mStartY = y; this.mBreakPoint = breakPoint; this.mType = type; } public void reset() { this.mDuration = 0.0F; this.mX = this.mStartX; this.mY = this.mStartY; } } public interface DivergeViewProvider { Bitmap getBitmap(Object var1); }}
2.XML布局文件:
<?xml version="1.0" encoding="utf-8"?>
3.在Activity中的代码:
public class MainActivity extends Activity { private DivergeView mDivergeView; private ImageView mImageView; private ArrayList mList; private int mIndex = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initView(); } //初始化布局 private void initView() { mImageView = findViewById(R.id.iv_start); mDivergeView = findViewById(R.id.divergeView); mList = new ArrayList<>(); // 添加点赞图标 mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.ic_praise_sm1, null)).getBitmap()); mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.ic_praise_sm2, null)).getBitmap()); mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.ic_praise_sm3, null)).getBitmap()); mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.ic_praise_sm4, null)).getBitmap()); mImageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mIndex == mList.size()) { mIndex = 0; } mDivergeView.startDiverges(mIndex); mIndex++; } }); mDivergeView.post(new Runnable() { @Override public void run() { mDivergeView.setEndPoint(new PointF(mDivergeView.getMeasuredWidth() / 2, 0)); mDivergeView.setDivergeViewProvider(new Provider()); } }); } @Override protected void onDestroy() { super.onDestroy(); if (mList != null) { mList.clear(); mList = null; } } class Provider implements DivergeView.DivergeViewProvider { @Override public Bitmap getBitmap(Object obj) { return mList == null ? null : mList.get((int) obj); } }}
修改Android中Layout布局文件字体的大小 【Android】常用控件及布局 Android 布局讲解 Android 仿抖音上下滑动布局 Android UI布局经验总结 Android网格布局实现--GridView Android的xml布局文件代码讲解(TextView控件)
随机推荐
Android底部菜单(Fragment控制切换多个页
Kotlin 会被谷歌弃坑?看官方怎么说
如何Android数据库缓存进行管理
Android笔记(十九)制作一个简易的指南针
Android单元测试(一):JUnit框架的使用
Android(安卓)Studio实现网络版音乐播放
iOS和Android设计理念的演变
androidRSA加密,java解密出现错误或者乱码
Android设备的界面适配设计
Android(安卓)高质量开发之崩溃优化