屬性動(dòng)畫 - 58同城數(shù)據(jù)加載動(dòng)畫

1.概述


其實(shí)越是形勢(shì)不好的時(shí)候越是要練習(xí)內(nèi)功,我們學(xué)會(huì)思考很重要,技術(shù)也只是技術(shù)而已。話不多說(shuō)看看今天的效果:

58同城數(shù)據(jù)加載

2.效果實(shí)現(xiàn)


2.1 布局分析

可以看到上圖可分為三部分,最上面是彈跳的幾何形狀圖形,中間是陰影指示器,最下面是文字,所以布局用LinearLayout,最上面暫且放ImageView,中間陰影放ImageView , 最下面放玩命加載文字。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/shapeLoadingView"
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="4dp" />

    <ImageView
        android:id="@+id/indication"
        android:layout_width="23dp"
        android:layout_height="3dp"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="82dp"
        android:src="@drawable/shadow" />

    <TextView
        android:id="@+id/promptTV"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/indication"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="18dp"
        android:text="玩命加載中..."
        android:textColor="#757575"
        android:textSize="14sp" />
</LinearLayout>

2.2 組合控件 LoadingView 繼承自 LinearLayout

public class LoadingView extends LinearLayout{
    private ImageView mShapeLodingView,mIndicationView;
    private Context mContext;
    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);
        this.mContext = context;
        initLayout();
    }

    private void initLayout() {
        View.inflate(mContext, R.layout.load_view,this);
        mShapeLodingView = (ShapeLoadingView) findViewById(R.id.shapeLoadingView);
        mIndicationView = (ImageView) findViewById(R.id.indication);
    }
}

2.3 動(dòng)畫分析

這里可以看做兩個(gè)部分的動(dòng)畫,一個(gè)是上面幾何圖形的下落上拋動(dòng)畫,一個(gè)是中間陰影指示器放大縮小的動(dòng)畫,如果能這樣組合就算實(shí)現(xiàn)了: 當(dāng)幾何圖形下落時(shí)配合陰影放大,當(dāng)幾何圖形上拋時(shí)配合中間陰影縮小。需要用到 ObjectAnimator 屬性動(dòng)畫

 //初始化下落動(dòng)畫
 private void initFreeFallAnimation() {
        // 下落動(dòng)畫集合
        mFreeFallAnimatiorSet  = new AnimatorSet();
        // 幾何圖形的垂直位移動(dòng)畫
        ObjectAnimator freeFallTranslationAnimator = ObjectAnimator.ofFloat(
                mShapeLodingView, "translationY", 0, mTranslationYDistance);
        // 定義動(dòng)畫的變化率。
        freeFallTranslationAnimator.setInterpolator(new AccelerateInterpolator(factor));
        // 中間陰影縮小動(dòng)畫
        ObjectAnimator scaleIndication = ObjectAnimator.ofFloat(mIndicationView,
                "scaleX", 1, 0.2f);

        mFreeFallAnimatiorSet.setDuration(ANIMATION_DURATION);
        mFreeFallAnimatiorSet.playTogether(freeFallTranslationAnimator, scaleIndication);

        mFreeFallAnimatiorSet.addListener(new AnimatorListenerAdapter() {
            //設(shè)置動(dòng)畫監(jiān)聽(tīng)器,監(jiān)聽(tīng)該動(dòng)畫的開(kāi)始、停止、取消、結(jié)束等狀態(tài),我們往往會(huì)用AnimtorListener適配器類來(lái)只實(shí)現(xiàn)我們需要的方法
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                // 下落動(dòng)畫結(jié)束,改變形狀,然后執(zhí)行上拋動(dòng)畫
                upThrow();
                mShapeLodingView.changeShape();
            }
        });
    }

上拋動(dòng)畫其實(shí)和下落動(dòng)畫差不多,只要在下落動(dòng)畫執(zhí)行完之后啟動(dòng)上拋動(dòng)畫即可,但是我們需要在下落動(dòng)畫結(jié)束完后改變形狀,最直接的方式便是改變幾何圖像 ImageView 的背景資源即可,但是個(gè)人認(rèn)為這樣不是太好,所以需要自定義幾何形狀 ShapeLoadingView,然后提供一個(gè) changeShape() 的方法,里面調(diào)用 invalidate(),在 onDraw(Canvas canvas) 中畫對(duì)應(yīng)的幾何形狀,具體請(qǐng)看這里 自定義View - 仿 QQ 運(yùn)動(dòng)步數(shù)進(jìn)度效果

最后就剩兩個(gè)旋轉(zhuǎn)的動(dòng)畫了,我們旋轉(zhuǎn)的動(dòng)畫以及角度問(wèn)題我們直接從自定義 ShapeLoadingView 中獲取,提供一個(gè) getUpThrowRoteAnimation() 方法

/**
* 在ShapeLoadingView的構(gòu)造方法中初始化旋轉(zhuǎn)動(dòng)畫即可
*/
private void initRoteAnimation() {
    mRectRoteAnimation = ObjectAnimator.ofFloat(this,
        "rotation", 0, -120);
    mDefaultRoteAnimation = ObjectAnimator.ofFloat(this,
        "rotation", 0, 180);
}

/**
* 得到當(dāng)前正在上拋時(shí)應(yīng)該旋轉(zhuǎn)的動(dòng)畫
*/
public ObjectAnimator getUpThrowRoteAnimation() {
    switch (mCureentShape){
        case SHAPE_RECT:
            return  mRectRoteAnimation;
        default:
            return mDefaultRoteAnimation;
    }
}

給上拋動(dòng)畫設(shè)置動(dòng)畫監(jiān)聽(tīng),在其 onAnimationStart() 中執(zhí)行旋轉(zhuǎn)動(dòng)畫


mUpThrowAnimatiorSet.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        //動(dòng)畫結(jié)束,下落
        freeFall();
    }

    @Override
    public void onAnimationStart(Animator animation) {
        super.onAnimationStart(animation);
        // 動(dòng)畫開(kāi)始,和旋轉(zhuǎn)動(dòng)畫一起執(zhí)行
        startShapeRoteAnimator();
    }

    /**
    * 執(zhí)行旋轉(zhuǎn)動(dòng)畫
    */
    private void startShapeRoteAnimator() {
        ObjectAnimator roteAnimation  = mShapeLodingView.getUpThrowRoteAnimation();
        roteAnimation.setDuration(ANIMATION_DURATION);
        roteAnimation.setInterpolator(new DecelerateInterpolator(factor));
        roteAnimation.start();
    }
});

2.3 優(yōu)化性能

網(wǎng)上有太多太多的 Demo 感覺(jué)都還很不錯(cuò),但是后期檢測(cè)性能的時(shí)候其實(shí)面臨很多問(wèn)題,如果某些效果不是你寫的但是性能比較差的話其實(shí)很難改,要么你特別熟悉別人的代碼要么你需要自己重新寫要么得過(guò)且過(guò)。

    /**
     * 采用代碼的方式添加
     *
     * @param parent
     * @return
     */
    public static LoadingView attach(ViewGroup parent) {
        LoadingView loadingView = new LoadingView(parent.getContext());
        loadingView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        parent.addView(loadingView);
        return loadingView;
    }

    /**
     * 優(yōu)化性能
     * @param visibility
     */
    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(View.INVISIBLE);
        ViewGroup parent = (ViewGroup) this.getParent();
        if(parent != null){
            parent.removeView(this);
            mShapeView.clearAnimation();
            mShadowView.clearAnimation();
            this.removeAllViews();
            mStopAnimator = true;
        }
    }

所有分享大綱:Android進(jìn)階之旅 - 自定義View篇

視頻講解地址:http://pan.baidu.com/s/1slFJDOp

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過(guò)程并不復(fù)雜,今天將帶大家一窺ios動(dòng)畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,686評(píng)論 6 30
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過(guò)程并不復(fù)雜,今天將帶大家一窺iOS動(dòng)畫全貌。在這里你可以看...
    F麥子閱讀 5,258評(píng)論 5 13
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,716評(píng)論 25 709
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,022評(píng)論 4 61
  • 文/楓丹白露 電視劇《我的前半生》中的唐晶是職場(chǎng)白骨精的代表,人們看到了她的干練、堅(jiān)強(qiáng)。然而,在這個(gè)堅(jiān)強(qiáng)的人設(shè)背后...
    楓丹白露_閱讀 2,217評(píng)論 11 15

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