前言:剛開始是假裝堅強帆赢,后來就真的堅強了∨樽螅——楊絳匿醒。
承接上一篇自定義 View 屬性動畫,本篇實現(xiàn)一個類似“小球”撞擊效果缠导,可以作為數(shù)據(jù)加載頁面來使用廉羔。其實這個效果在某些 App 里面看到過,只不過忘記在哪看到的了僻造。
好了憋他,先看一下實現(xiàn)效果圖:
看到這種效果,就像是真空中的小球一直在發(fā)生碰撞一樣髓削,這種方式該如何去做呢竹挡?其實有很多種方式去實現(xiàn),但是最簡單的方式還是使用屬性動畫來實現(xiàn):
使用屬性動畫實現(xiàn)應(yīng)該有最基本的四步:
- 1)立膛、繪制圓形小球
- 2)揪罕、讓圓形小球動起來
- 3)、根據(jù)三個圓形的變化規(guī)律宝泵,改變小球顏色
- 4)好啰、優(yōu)化
1、繪制圓球
對于小球儿奶,也有不同的方式去繪制框往。可以直接畫一個 shape 圖形闯捎,也可以自定義 View 進行繪制椰弊,這里選用后者,因為后者相對靈活一點瓤鼻。
自定義 View 進行繪制圓形:
public class CircularView extends View {
private int Color;
private Paint mPaint;
public void setColor(int color) {
this.Color = color;
mPaint.setColor(Color);
invalidate();
}
public int getColor() {
return Color;
}
public CircularView(Context context) {
this(context,null);
}
public CircularView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public CircularView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float cx = getWidth()/2;
canvas.drawCircle(cx,cx,cx,mPaint);
}
}
在 OnDraw 中秉版,直接使用 canvas 畫了一個圓,然后提供 setColor 方法娱仔,并重繪沐飘。這樣就能實現(xiàn)創(chuàng)建任意顏色的小圓了。
public class LoadingView extends RelativeLayout {
private CircularView mLeftCircularView;
private CircularView mCenterCircularView;
private CircularView mRightCircularView;
public LoadingView(Context context) {
this(context,null);
}
public LoadingView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
mLeftCircularView = createCircularView(context);
mLeftCircularView.setColor(Color.RED);
mRightCircularView = createCircularView(context);
mRightCircularView.setColor(Color.BLUE);
mCenterCircularView = createCircularView(context);
mCenterCircularView.setColor(Color.GREEN);
addView(mLeftCircularView);
addView(mRightCircularView);
//后添加在上面,表示中間的小圓
addView(mCenterCircularView);
/**--------- 開啟動畫 ---------**/
post(new Runnable() {
@Override
public void run() {
startOutAnimation();
}
});
}
/**
* 開啟往外移動的動畫
*/
private void startOutAnimation() {
//左邊小圓左移動畫
ObjectAnimator outObjectAnimator = ObjectAnimator.ofFloat();
//右邊小圓右移動畫
}
/**
* 開啟往內(nèi)移動的動畫
*/
private void startInnerAnimation() {
}
/**
* 統(tǒng)一創(chuàng)建小圓
* @param context
* @return
*/
private CircularView createCircularView(Context context) {
CircularView circularView = new CircularView(context);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(dip2px(10),dip2px(10));
params.addRule(CENTER_IN_PARENT);
circularView.setLayoutParams(params);
return circularView;
}
private int dip2px(int dip) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dip,getResources().getDisplayMetrics());
}
}
這里創(chuàng)建一個 LoadingView 繼承自 RelativeLayout耐朴,當(dāng)然繼承自 FrameLayout 也是可以的借卧。
在初識化的時候,創(chuàng)建了三個 CircularView 設(shè)置其顏色并添加到 LoadingView 中筛峭,注意由于繼承了 RelativeLayout铐刘,所以添加順序是有講究的,中間的小圓讓它在最上面影晓,左右小圓在下面镰吵。此時運行程序:
注意上面三個小球是重疊起來的。
2挂签、讓圓形小球動起來
該節(jié)內(nèi)容就是使用屬性動畫讓小圓球進行移動了疤祭。
還是先看代碼:
/**
* 開啟往外移動的動畫
*/
private void startOutAnimation() {
//左邊小圓左移動畫
ObjectAnimator outLeftObjectAnimator = ObjectAnimator.ofFloat(mLeftCircularView,"TranslationX",0f,-translationDis);
//右邊小圓右移動畫
ObjectAnimator outRightObjectAnimator = ObjectAnimator.ofFloat(mRightCircularView,"TranslationX",0f,translationDis);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(DURATION);
animatorSet.setInterpolator(new DecelerateInterpolator(2f));
animatorSet.playTogether(outLeftObjectAnimator,outRightObjectAnimator);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
//動畫結(jié)束,開啟往內(nèi)移動的動畫
startInnerAnimation();
}
});
animatorSet.start();
}
/**
* 開啟往內(nèi)移動的動畫
*/
private void startInnerAnimation() {
//左邊小圓右移動畫
ObjectAnimator innerLeftObjectAnimator = ObjectAnimator.ofFloat(mLeftCircularView,"TranslationX",-translationDis,0f);
//右邊小圓左移動畫
ObjectAnimator innerRightObjectAnimator = ObjectAnimator.ofFloat(mRightCircularView,"TranslationX",translationDis,0f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(DURATION);
animatorSet.setInterpolator(new AccelerateInterpolator());
animatorSet.playTogether(innerLeftObjectAnimator,innerRightObjectAnimator);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
//動畫結(jié)束饵婆,開啟往內(nèi)移動的動畫
startOutAnimation();
}
});
animatorSet.start();
}
發(fā)現(xiàn)是左邊小圓往左側(cè)移動勺馆,中間小圓不變化,右邊小圓往右移動侨核。都是屬性動畫最基本的用法草穆,而且上一篇也做了很詳細的解釋,這里應(yīng)該沒問任何問題搓译。運行程序:
此時已經(jīng)完成了小球動態(tài)改變效果悲柱,但是在回彈的時候是需要改變小球顏色的。
3些己、4豌鸡、改變小球的顏色,最后的優(yōu)化
1段标、改變小球顏色
看一下文章開頭直颅,改變規(guī)律如下:
左邊小球顏色—>中間小球顏色—>右邊小球顏色—>左邊小球顏色
按照上面這個規(guī)律代碼如下:
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
//動畫結(jié)束,開啟往外移動的動畫
startOutAnimation();
//改變小球顏色
//左邊小球顏色—>中間小球顏色—>右邊小球顏色—>左邊小球顏色
int mLeftCircularViewColor = mLeftCircularView.getColor();
int mCenterCircularViewColor = mCenterCircularView.getColor();
int mRightCircularViewColor = mRightCircularView.getColor();
mCenterCircularView.setColor(mLeftCircularViewColor);
mRightCircularView.setColor(mCenterCircularViewColor);
mLeftCircularView.setColor(mRightCircularViewColor);
}
});
監(jiān)聽在 startInnerAnimation怀樟,也即動畫內(nèi)移結(jié)束的時候開始改變球的顏色。
2盆佣、一點點優(yōu)化
這里內(nèi)容跟上文是一樣的往堡,直接把代碼貼在下面了:
運行程序:
最后呈現(xiàn)一張動圖送給你們