因為新的項目中要實現(xiàn)海底上升氣泡的效果當(dāng)做手機(jī)下半面的背景跳芳,需要氣泡隨機(jī)大小隨機(jī)位置移動。說是隨機(jī)移動弊琴,但是終點要控制所有的氣泡都要回歸到終點位置X軸的中點棋弥。所以我選擇了用二階的貝塞爾曲線和屬性動畫來實現(xiàn)。先看下效果帚豪。
因為背景圖選擇的是深色圖碳竟,所以效果有些不明顯。大家將就著看狸臣。
在實現(xiàn)這個效果之前莹桅,公司的動效設(shè)計師說氣泡是三種氣泡,分別有不同的顏色以及陰影邊緣烛亦,所以他給我們提供氣泡的素材诈泼。這也就省去了畫氣泡的時間。
首先我們在自定義view中添加了十一個不同的氣泡圖片煤禽,并且我又實例了一個集合用來存放LayoutParams铐达,用來實現(xiàn)氣泡的不同大小。
private ValueAnimator getBezierValueAnimator(final View target) {
?// 初始化貝塞爾估值器 //隨機(jī)產(chǎn)生兩個點檬果,以確定一條3階貝塞爾
曲線?BezierEvaluator evaluator = new BezierEvaluator(getPointF(), getPointF());
ValueAnimator animator= ValueAnimator.ofObject(evaluator, new PointF(random.nextInt(1000), 1000), new PointF(random.nextInt(500)+300, 0)); animator.setTarget(target); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override public void onAnimationUpdate(ValueAnimator valueAnimator) {
?// 這里獲取到貝塞爾曲線計算出來的的x y值 賦值給view 這樣就能讓氣泡隨著曲線走啦
PointF pointF = (PointF) valueAnimator.getAnimatedValue(); target.setX(pointF.x); target.setY(pointF.y); }
});
animator.setDuration(6000); return animator;}
上面的方法是貝塞爾曲線的靈魂瓮孙,我們向這個方法中添加view,然后確定控制點的位置汁汗。
二階貝塞爾曲線還是很簡單的衷畦,只需要確定三個點的位置。也就是起點知牌,終點和兩個點中間的控制點,然后根據(jù)貝塞爾估值器轉(zhuǎn)化為貝塞爾的路徑斤程。那么就可以了角寸。
從上面的方法,可以看到我們用到了屬性動畫忿墅,我們監(jiān)聽了動畫的變化扁藕,然后根據(jù)每次變化將貝塞爾曲線得到的點的位置賦值給view,那么就能夠讓view按照貝塞爾曲線移動了疚脐。具體的移動時間可以自己控制亿柑。
private PointF getPointF() { PointF pointF = new PointF();
pointF.x = random.nextInt(ScreenUtils.getScreenWidth(mContext));
pointF.y = random.nextInt(300)+100; return pointF;}
這個方法是我們用來控制中間的控制點的。X軸上的點是在屏幕的寬度之間隨機(jī)選取的棍弄。這樣會實現(xiàn)曲線分布的很均勻望薄。然后Y軸上的坐標(biāo)疟游,為了能夠讓曲線在中間位置讓用戶看的很隨機(jī)。我特別選取了Y軸在自定義view的中間位置痕支。這樣曲線在用戶的視線內(nèi)會有很均勻的變化颁虐。這個點也就是二階貝塞爾曲線的中間點位置。
public void startBallAnim() {
final ImageView imageView = new ImageView(mContext);
imageView.setBackgroundResource(mList.get(random.nextInt(mList.size())));
imageView.setLayoutParams(lp.get(random.nextInt(lp.size())));
addView(imageView);
AnimatorSet finalSet = new AnimatorSet();
ValueAnimator bezierValueAnimator = getBezierValueAnimator(imageView);
//貝塞爾曲線路徑動畫
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView,"alpha",random.nextFloat(),0f);
objectAnimator.setDuration(6000);
finalSet.playSequentially(bezierValueAnimator);
finalSet.setInterpolator(new LinearInterpolator());
finalSet.setTarget(imageView);
finalSet.addListener(new AnimatorListenerAdapter() {
@Override public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation); removeView((imageView));//刪除氣泡 }
});
finalSet.start();
objectAnimator.start();}
這個方法是在自定義view剛開始實例化就開始調(diào)用的卧须。這樣在用戶進(jìn)入界面的時候另绩,就會觸發(fā)氣泡開始向上升起。這里還是用到了屬性動畫花嘶,漸變的屬性動畫笋籽。初衷是讓氣泡越往上面移動越透明,最后淡出椭员。然后在動畫結(jié)束的時候车海,將這個view remove掉,不然這個動畫會讓氣泡一直一直的出來拆撼,會對內(nèi)存有很大的損耗容劳。
然后在自定義view實例化的時候調(diào)用這個開始方法。就會有源源不斷的氣泡從底部升上來闸度。
有什么問題可以私聊我或者公聊 哈哈哈哈