Android實(shí)現(xiàn)點(diǎn)贊動(dòng)畫(huà)(27)
本文實(shí)例為大家分享了Android使用入門(mén)第二十七篇點(diǎn)贊動(dòng)畫(huà)的具體代碼,供大家參考,具體內(nèi)容如下
MainActivity.java代碼:
package siso.likeanimation;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.drawable.BitmapDrawable;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private DivergeViewSecond mDivergeView;
private Button mBtnStart;
private ImageView mImageView;
private ArrayList<Bitmap> mList;
private int mIndex = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtnStart = (Button)findViewById(R.id.btnStart);
mImageView = (ImageView)findViewById(R.id.iv_start);
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());
mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(),R.drawable.ic_praise_sm5,null)).getBitmap());
mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.ic_praise_sm6, null)).getBitmap());
mBtnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mIndex == 5){
mIndex = 0 ;
}
mDivergeView.startDiverges(mIndex);
mIndex ++;
// if (mDivergeView.isRunning()) {
// mDivergeView.stop();
// } else {
//
// }
}
});
mDivergeView = (DivergeViewSecond) findViewById(R.id.divergeView);
mDivergeView.post(new Runnable() {
@Override
public void run() {
mDivergeView.setEndPoint(new PointF(mDivergeView.getMeasuredWidth()/2,0));
mDivergeView.setDivergeViewProvider(new Provider());
}
});
// mDivergeView.start();
}
@Override
protected void onDestroy() {
super.onDestroy();
if(mList != null){
mList.clear();
mList = null;
}
}
class Provider implements DivergeViewSecond.DivergeViewProvider{
@Override
public Bitmap getBitmap(Object obj) {
return mList == null ? null : mList.get((int)obj);
}
}
}
DivergeViewSecond.java代碼:
package siso.likeanimation;
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.util.Log;
import android.view.View;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
public class DivergeViewSecond extends View implements Runnable{
public static final float mDuration = 0.010F;
public static final int mDefaultHeight = 100;
protected static final long mQueenDuration = 200;
protected final Random mRandom = new Random();
protected ArrayList<DivergeInfo> mDivergeInfos;
protected List<Object> mQueen;
protected PointF mPtStart;
protected PointF mPtEnd;
protected ArrayList<DivergeInfo> mDeadPool = new ArrayList<>();
private Paint mPaint;
// private static final int mDefaultWidth = 100;
// private static final int mAlphaOffset = 50;
private DivergeViewProvider mDivergeViewProvider;
private long mLastAddTime = 0;
private Thread mThread;
private boolean mRunning = true;
private boolean mIsDrawing = false;
public DivergeViewSecond(Context context) {
this(context, null);
}
public DivergeViewSecond(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DivergeViewSecond(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
/**
* Loop
*/
@Override
public void run() {
while(mRunning){
if(mDivergeViewProvider == null){
continue;
}
if(mQueen == null){
continue;
}
if(mIsDrawing){
//如果正在繪制,不要處理數(shù)據(jù)
continue;
}
if(mDivergeInfos == null){
continue;
}
dealQueen();
if(mDivergeInfos.size() == 0){
continue;
}
dealDiverge();
mIsDrawing = true;
postInvalidate();
}
//停止
release();
}
private void dealDiverge(){
for (int i = 0; i < mDivergeInfos.size(); i++) {
DivergeInfo divergeInfo = mDivergeInfos.get(i);
float timeLeft = 1.0F - divergeInfo.mDuration;
divergeInfo.mDuration += mDuration;
float x, y;
//二次貝塞爾
float time1 = timeLeft * timeLeft;
float time2 = 2 * timeLeft * divergeInfo.mDuration;
float time3 = divergeInfo.mDuration * divergeInfo.mDuration;
x = time1 * (mPtStart.x)
+ time2 * (divergeInfo.mBreakPoint.x)
+ time3 * (divergeInfo.mEndPoint.x);
divergeInfo.mX = x;
y = time1 * (mPtStart.y)
+ time2 * (divergeInfo.mBreakPoint.y)
+ time3 * (divergeInfo.mEndPoint.y);
divergeInfo.mY = y;
if (divergeInfo.mY <= divergeInfo.mEndPoint.y) {
mDivergeInfos.remove(i);
mDeadPool.add(divergeInfo);
i--;
continue;
}
}
}
private void dealQueen(){
long now = System.currentTimeMillis();
if(mQueen.size() > 0 && now - mLastAddTime > mQueenDuration){
mLastAddTime = System.currentTimeMillis();
DivergeInfo divergeInfo = null;
if(mDeadPool.size() > 0){
//死池里面有空閑的divergeNode
divergeInfo = mDeadPool.get(0);
mDeadPool.remove(0);
}
if(divergeInfo == null){
divergeInfo = createDivergeNode(mQueen.get(0));
}
divergeInfo.reset();
divergeInfo.mType = mQueen.get(0);
mDivergeInfos.add(divergeInfo);
mQueen.remove(0);
}
}
public interface DivergeViewProvider{
public Bitmap getBitmap(Object obj);
}
private void init(){
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//不需要支持wrap_content
}
@Override
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){
mDivergeViewProvider = divergeViewProvider;
}
public PointF getStartPoint(){
return mPtStart;
}
public boolean isRunning(){
return mRunning;
}
public void startDiverges(Object obj){
if(mDivergeInfos == null){
mDivergeInfos = new ArrayList<>(30);
}
if(mQueen == null){
mQueen = Collections.synchronizedList(new ArrayList<>(30));
}
mQueen.add(obj);
// for(Object obj : objs) {
// mQueen.add(obj);
// }
if(mThread == null) {
mThread = new Thread(this);
mThread.start();
}
}
public void stop(){
if(mDivergeInfos != null){
mDivergeInfos.clear();
}
if(mQueen != null){
mQueen.clear();
}
if(mDeadPool != null){
mDeadPool.clear();
}
}
public void release(){
stop();
mPtEnd = null;
mPtStart = null;
mDivergeInfos = null;
mQueen = null;
mDeadPool = null;
}
public void setStartPoint(PointF point){
mPtStart = point;
}
public void setEndPoint(PointF point){
mPtEnd = point;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mRunning = false;
}
@Override
protected void onDraw(Canvas canvas) {
if(mRunning && mDivergeViewProvider != null && mDivergeInfos != null){
for(DivergeInfo divergeInfo : mDivergeInfos){
mPaint.setAlpha((int)(255 * divergeInfo.mY / mPtStart.y));
canvas.drawBitmap(mDivergeViewProvider.getBitmap(divergeInfo.mType),
divergeInfo.mX,
divergeInfo.mY,
mPaint);
}
}
mIsDrawing = false;
}
private PointF getBreakPointF(int scale1, int scale2) {
PointF pointF = new PointF();
pointF.x = mRandom.nextInt((getMeasuredWidth() - getPaddingRight() + getPaddingLeft()) / scale1) + getMeasuredWidth() / scale2;
pointF.y = mRandom.nextInt((getMeasuredHeight() - getPaddingBottom() + getPaddingTop()) / scale1) + getMeasuredHeight() / scale2;
return pointF;
}
protected DivergeInfo createDivergeNode(Object type){
PointF endPoint = mPtEnd;
if(endPoint == null){
endPoint = new PointF(mRandom.nextInt(getMeasuredWidth()),0);
}
// int height = mDivergeViewProvider == null ? mDefaultHeight : mDivergeViewProvider.getBitmap(type).getHeight();
if(mPtStart == null) {
mPtStart = new PointF(getMeasuredWidth() / 2, getMeasuredHeight() - mDefaultHeight);//默認(rèn)起始高度
}
return new DivergeInfo(
mPtStart.x,
mPtStart.y,
getBreakPointF(2, 3),
endPoint,
type);
}
public class DivergeInfo {
public float mDuration;
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){
mDuration = 0.0f;
mEndPoint = endPoint;
mX = x;
mY = y;
mStartX = x;
mStartY = y;
mBreakPoint = breakPoint;
mType = type;
}
public void reset(){
mDuration = 0.0f;
mX = mStartX;
mY = mStartY;
}
}
}
activity_main.xml內(nèi)容:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="siso.likeanimation.MainActivity"> <Button android:id="@+id/btnStart" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="開(kāi)始"/> <siso.likeanimation.DivergeViewSecond android:id="@+id/divergeView" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_width="130dp" android:layout_height="300dp"/> <ImageView android:id="@+id/iv_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:background="@drawable/ic_praise_sm6"/> </RelativeLayout>
運(yùn)行結(jié)果如圖:

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android高級(jí)UI特效仿直播點(diǎn)贊動(dòng)畫(huà)效果
- android實(shí)現(xiàn)直播點(diǎn)贊飄心動(dòng)畫(huà)效果
- Android控件實(shí)現(xiàn)直播App點(diǎn)贊飄心動(dòng)畫(huà)
- Android控件FlowLikeView實(shí)現(xiàn)點(diǎn)贊動(dòng)畫(huà)
- Android實(shí)現(xiàn)簡(jiǎn)單點(diǎn)贊動(dòng)畫(huà)
- Android實(shí)現(xiàn)仿今日頭條點(diǎn)贊動(dòng)畫(huà)效果實(shí)例
- 利用Android實(shí)現(xiàn)一種點(diǎn)贊動(dòng)畫(huà)效果的全過(guò)程
相關(guān)文章
Kotlin面向?qū)ο笾R(shí)點(diǎn)講解
面向?qū)ο缶幊掏ㄟ^(guò)對(duì)事物的抽象,大大的簡(jiǎn)化了程序的開(kāi)發(fā)難度。我們常用的編程語(yǔ)言:Java、C++、Python都屬于面向?qū)ο缶幊獭otlin與java類似,也是一種面向?qū)ο缶幊陶Z(yǔ)言。本文從面向?qū)ο笕齻€(gè)基本特征:封裝、繼承、多態(tài),來(lái)闡述一下Kotlin中的面向?qū)ο缶幊?/div> 2022-12-12
如何在Android Studio下進(jìn)行NDK開(kāi)發(fā)
這篇文章主要介紹了如何在Android Studio下進(jìn)行NDK開(kāi)發(fā),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
Android實(shí)現(xiàn)仿今日頭條點(diǎn)贊動(dòng)畫(huà)效果實(shí)例
我想看到今日頭條的點(diǎn)贊效果,應(yīng)該都覺(jué)得很絢麗吧,下面這篇文章主要給大家介紹了關(guān)于Android實(shí)現(xiàn)仿今日頭條點(diǎn)贊動(dòng)畫(huà)效果的相關(guān)資料,文中通過(guò)示例代價(jià)介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02
Android利用MediaRecorder實(shí)現(xiàn)錄音功能
這篇文章主要為大家詳細(xì)介紹了Android利用MediaRecorder實(shí)現(xiàn)錄音功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Android Vitamio和ExoPlayer兩種播放器優(yōu)劣分析
Vitamio和ExoPlayer都是用于安卓平臺(tái)的視頻播放器庫(kù),它們各有優(yōu)缺點(diǎn),具體使用哪一個(gè),需要根據(jù)你的實(shí)際需求、開(kāi)發(fā)經(jīng)驗(yàn)、項(xiàng)目規(guī)模等多個(gè)因素綜合考慮2023-04-04
Android使用Intent的Action和Data屬性實(shí)現(xiàn)點(diǎn)擊按鈕跳轉(zhuǎn)到撥打電話和發(fā)送短信界面
這篇文章主要介紹了Android中使用Intent的Action和Data屬性實(shí)現(xiàn)點(diǎn)擊按鈕跳轉(zhuǎn)到撥打電話和發(fā)送短信,需要的朋友可以參考下2020-01-01
flutter自定義InheritedProvider實(shí)現(xiàn)狀態(tài)管理詳解
這篇文章主要為大家介紹了flutter自定義InheritedProvider實(shí)現(xiàn)狀態(tài)管理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Android實(shí)現(xiàn)調(diào)用系統(tǒng)圖庫(kù)與相機(jī)設(shè)置頭像并保存在本地及服務(wù)器
這篇文章主要介紹了Android實(shí)現(xiàn)調(diào)用系統(tǒng)圖庫(kù)與相機(jī)設(shè)置頭像并保存在本地及服務(wù)器 ,需要的朋友可以參考下2017-03-03最新評(píng)論

