最近在做直播相關(guān)的東西懂拾,這個動畫是IOS先擼出來的煤禽,后來android這邊要模仿,大部分直播應(yīng)用都有很炫酷的點贊動畫岖赋,所以也沒什么好稀奇的檬果。如果有現(xiàn)成的輪子了,就沒必要自己再造了,后來參照了程序亦非猿的實現(xiàn)选脊,做了些修改杭抠,最終效果還不錯。
剛開始自己造輪子的時候也走了些彎路恳啥,最初是給這些圖標一些隨機的初始速度和偏移量然后慢慢上升偏灿,效果總是不大好,差了點意思钝的。后來仔細研究發(fā)現(xiàn)這些圖標上升的路線并不是直線翁垂,而是一個三階貝塞爾曲線。
一階貝塞爾曲線硝桩,實際上就是一條連接兩點的直線段沿猜。
二階貝塞爾曲線,就是兩點間的一條拋物線碗脊,利用一個控制點來控制拋物線的形狀啼肩。
三階貝塞爾曲線,則需要一個起點衙伶,一個終點疟游,兩個控制點來控制曲線的形狀。
三節(jié)貝塞爾曲線的公式
公式中:P0痕支,是我們的起點,P3是終點蛮原,P1卧须,P2是途徑的兩個點,而t則是一個因子,取值范圍是0-1儒陨。
整個曲線的生成過程
實現(xiàn)代碼如下花嘶,調(diào)用的時候只需要在構(gòu)造方法中傳入兩個隨機點即可。
public class BesselEvaluator implements TypeEvaluator<float[]> {
private float point1[] = new float[2], point2[] = new float[2];
public BesselEvaluator(float[] point1, float[] point2) {
this.point1 = point1;
this.point2 = point2;
}
@Override
public float[] evaluate(float fraction, float[] point0, float[] point3) {
float[] currentPosition = new float[2];
currentPosition[0] = point0[0] * (1 - fraction) * (1 - fraction) * (1 - fraction)
+ point1[0] * 3 * fraction * (1 - fraction) * (1 - fraction)
+ point2[0] * 3 * (1 - fraction) * fraction * fraction
+ point3[0] * fraction * fraction * fraction;
currentPosition[1] = point0[1] * (1 - fraction) * (1 - fraction) * (1 - fraction)
+ point1[1] * 3 * fraction * (1 - fraction) * (1 - fraction)
+ point2[1] * 3 * (1 - fraction) * fraction * fraction
+ point3[1] * fraction * fraction * fraction;
return currentPosition;
}
}
詳細的動畫實現(xiàn)可以參考一步一步教你實現(xiàn)Periscope點贊效果蹦漠,但很顯然我這里完成點贊動畫椭员,任務(wù)還沒有完成。有幾個問題需要解決:允許連續(xù)點贊笛园,而且是計數(shù)的隘击,什么時候把點贊的數(shù)量拋給服務(wù)器;我怎么看到其他用戶點贊研铆,或者其他用戶怎么看的到我點贊埋同。
先看第一個問題吧,什么時候把點贊數(shù)量拋給服務(wù)器棵红?由于產(chǎn)品經(jīng)理帶著小姨子跑路了凶赁,Ios和android兩個端的策略還不太一樣,但我們達成的基本共識就是:不能點一次拋一次,拋的次數(shù)越少越好虱肄。Ios是本地維護一個count致板,沒隔一段時間檢測count有增加,就拋一次咏窿。android這里是連續(xù)點擊的時間間隔大于一個約定值斟或,就認為本輪點贊結(jié)束,然后拋一次翰灾。以前有研究過單擊雙擊缕粹,這次連續(xù)點擊也來了,該來的總要來的纸淮。
public class MainActivity extends AppCompatActivity {
long mLastTime = 0;
long mCurTime = 0;
private final int DELAY = 500;//連續(xù)點擊的臨界點
BubbleView bubbleView;
private int mClickCount = 0;
private int currLikeCount;
private TextView likeCount;
private Timer delayTimer;
private TimerTask timeTask;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
praiseRequest(mClickCount);
delayTimer.cancel();
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
bubbleView=(BubbleView)findViewById(R.id.praise_anim);
bubbleView.setDefaultDrawableList();
likeCount = (TextView) findViewById(R.id.like_count);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mCurTime = System.currentTimeMillis();
if (mCurTime - mLastTime < DELAY) {
mClickCount++;
} else {
mClickCount = 1;
}
currLikeCount++;
likeCount.setText(String.valueOf(currLikeCount));
delay();
mLastTime = mCurTime;
bubbleView.startAnimation(bubbleView.getWidth(), bubbleView.getHeight());
}
});
}
private void delay() {
if (timeTask != null)
timeTask.cancel();
timeTask = new TimerTask() {
@Override
public void run() {
Message message = new Message();
mHandler.sendMessage(message);
}
};
delayTimer = new Timer();
delayTimer.schedule(timeTask, DELAY);
}
/**
* 點贊請求網(wǎng)絡(luò)
*/
private void praiseRequest(int count) {
}
}
第二個問題由于暫時沒條件做推送平斩,所以只能客戶端每隔一段時間輪一次接口了,如果相比較上次數(shù)量有增加咽块,動畫上就彈出相應(yīng)數(shù)量的愛心數(shù)绘面,這里就需要給屏幕上允許出現(xiàn)的愛心數(shù)量設(shè)置一個最大值,要不然一瞬間彈出幾百個甚至上千個肯定要悲劇了侈沪。
最后還是貼上代碼揭璃,需要的自取:GitHub