自定義 View 實(shí)現(xiàn)小球撞擊數(shù)據(jù)加載效果

前言:剛開始是假裝堅(jiān)強(qiáng),后來就真的堅(jiān)強(qiáng)了。——楊絳。

承接上一篇自定義 View 屬性動(dòng)畫,本篇實(shí)現(xiàn)一個(gè)類似“小球”撞擊效果,可以作為數(shù)據(jù)加載頁面來使用。其實(shí)這個(gè)效果在某些 App 里面看到過,只不過忘記在哪看到的了。
好了,先看一下實(shí)現(xiàn)效果圖:

image

看到這種效果,就像是真空中的小球一直在發(fā)生碰撞一樣,這種方式該如何去做呢?其實(shí)有很多種方式去實(shí)現(xiàn),但是最簡單的方式還是使用屬性動(dòng)畫來實(shí)現(xiàn):
使用屬性動(dòng)畫實(shí)現(xiàn)應(yīng)該有最基本的四步:

  • 1)、繪制圓形小球
  • 2)、讓圓形小球動(dòng)起來
  • 3)、根據(jù)三個(gè)圓形的變化規(guī)律,改變小球顏色
  • 4)、優(yōu)化

1、繪制圓球

對于小球,也有不同的方式去繪制??梢灾苯赢嬕粋€(gè) shape 圖形,也可以自定義 View 進(jìn)行繪制,這里選用后者,因?yàn)楹笳呦鄬`活一點(diǎn)。
自定義 View 進(jìn)行繪制圓形:

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 畫了一個(gè)圓,然后提供 setColor 方法,并重繪。這樣就能實(shí)現(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);

        /**---------  開啟動(dòng)畫  ---------**/
        post(new Runnable() {
            @Override
            public void run() {
                startOutAnimation();
            }
        });
    }

    /**
     * 開啟往外移動(dòng)的動(dòng)畫
     */
    private void startOutAnimation() {
        //左邊小圓左移動(dòng)畫
        ObjectAnimator outObjectAnimator = ObjectAnimator.ofFloat();
        //右邊小圓右移動(dòng)畫

    }

    /**
     * 開啟往內(nèi)移動(dòng)的動(dòng)畫
     */
    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)建一個(gè) LoadingView 繼承自 RelativeLayout,當(dāng)然繼承自 FrameLayout 也是可以的。
在初識(shí)化的時(shí)候,創(chuàng)建了三個(gè) CircularView 設(shè)置其顏色并添加到 LoadingView 中,注意由于繼承了 RelativeLayout,所以添加順序是有講究的,中間的小圓讓它在最上面,左右小圓在下面。此時(shí)運(yùn)行程序:

image

注意上面三個(gè)小球是重疊起來的。


2、讓圓形小球動(dòng)起來

該節(jié)內(nèi)容就是使用屬性動(dòng)畫讓小圓球進(jìn)行移動(dòng)了。
還是先看代碼:

/**
 * 開啟往外移動(dòng)的動(dòng)畫
 */
private void startOutAnimation() {
    //左邊小圓左移動(dòng)畫
    ObjectAnimator outLeftObjectAnimator = ObjectAnimator.ofFloat(mLeftCircularView,"TranslationX",0f,-translationDis);
    //右邊小圓右移動(dòng)畫
    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) {
            //動(dòng)畫結(jié)束,開啟往內(nèi)移動(dòng)的動(dòng)畫
            startInnerAnimation();
        }
    });
    animatorSet.start();
}

/**
 * 開啟往內(nèi)移動(dòng)的動(dòng)畫
 */
private void startInnerAnimation() {

    //左邊小圓右移動(dòng)畫
    ObjectAnimator innerLeftObjectAnimator = ObjectAnimator.ofFloat(mLeftCircularView,"TranslationX",-translationDis,0f);
    //右邊小圓左移動(dòng)畫
    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) {
            //動(dòng)畫結(jié)束,開啟往內(nèi)移動(dòng)的動(dòng)畫
            startOutAnimation();
        }
    });
    animatorSet.start();
}

發(fā)現(xiàn)是左邊小圓往左側(cè)移動(dòng),中間小圓不變化,右邊小圓往右移動(dòng)。都是屬性動(dòng)畫最基本的用法,而且上一篇也做了很詳細(xì)的解釋,這里應(yīng)該沒問任何問題。運(yùn)行程序:


image

此時(shí)已經(jīng)完成了小球動(dòng)態(tài)改變效果,但是在回彈的時(shí)候是需要改變小球顏色的。


3、4、改變小球的顏色,最后的優(yōu)化

1、改變小球顏色

看一下文章開頭,改變規(guī)律如下:
左邊小球顏色—>中間小球顏色—>右邊小球顏色—>左邊小球顏色
按照上面這個(gè)規(guī)律代碼如下:

    animatorSet.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            //動(dòng)畫結(jié)束,開啟往外移動(dòng)的動(dòng)畫
            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,也即動(dòng)畫內(nèi)移結(jié)束的時(shí)候開始改變球的顏色。

2、一點(diǎn)點(diǎn)優(yōu)化

這里內(nèi)容跟上文是一樣的,直接把代碼貼在下面了:

image

運(yùn)行程序:

image

最后呈現(xiàn)一張動(dòng)圖送給你們


image
最後編輯於
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者

友情鏈接更多精彩內(nèi)容