使用路徑動畫完成一個簡潔優雅的啓動頁動畫

是不是受夠了千篇一律的透明度變化的啓動頁動畫,快來試試使用路徑動畫和屬性動畫構建一個特別的啓動頁動畫吧.

最近在網上看到一個路徑動畫的例子,感覺效果很不錯,仿照着例子寫了一個路徑動畫的庫,並且上傳到jcenter,方便AS玩家通過依賴使用.
github地址:https://github.com/sunflowerseat/PathAnim
先上效果圖,讓圖說話:
這裏寫圖片描述
接下來,我講講怎麼通過這個路徑動畫庫來完成一個簡潔優雅的啓動頁動畫
首先在module中添加依賴

compile 'com.fancy.library:pathanim:1.0.1'

首先要完成路徑動畫,我們必須要先有一個路徑.
可以使用GIMP 2這個工具來獲取一個路徑
這裏寫圖片描述

導出路徑:
這裏寫圖片描述

得到一個路徑之後,我們開始寫佈局文件
簡單寫一個logo背景,啓動頁顯示的文字和一個版本號
佈局文件參考:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:oak="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:id="@+id/big_background"
        >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/cpb_background"
        android:id="@+id/rl_background"
        android:layout_centerInParent="true"
        >
        <com.fancy.path_anim_lib.AnimatedSvgView
            android:id="@+id/animated_svg_view"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:layout_centerInParent="true"
            oak:oakSvgFillStart="500"
            oak:oakSvgFillTime="100"
            oak:oakSvgImageSizeX="200"
            oak:oakSvgImageSizeY="200"
            oak:oakSvgTraceTime="2000"
            oak:oakSvgTraceTimePerGlyph="1000" />

    </RelativeLayout>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="啓動頁動畫"
        android:textSize="30sp"
        android:layout_below="@+id/rl_background"
        android:textStyle="bold"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="40dp"
        android:textColor="@color/startpage_blue"
        android:id="@+id/name"
        />

    </RelativeLayout>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="8.1.3"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="10dp"
        android:textSize="20sp"
        android:textColor="@color/startpage_blue"
        android:id="@+id/versionCode"
        />
</RelativeLayout>

解釋一下AnimatedSvgView中一些重要參數的作用:
oakSvgFillTime路徑動畫填充時間
oakSvgImageSizeX 原圖x所佔像素
oakSvgImageSizeY 原圖y所佔像素
oakSvgTraceTimePerGlyph 路徑繪製時間

Activity完成動畫參考:

public class MainActivity extends AppCompatActivity {

    private AnimatedSvgView mAnimatedSvgView;
    private RelativeLayout rl_background;
    private RelativeLayout big_background;
    private TextView versionCode;
    private TextView name;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_svg);
        //路徑動畫的View
        mAnimatedSvgView = (AnimatedSvgView) findViewById(R.id.animated_svg_view);
        //需要整體上移的RelativeLayout
        rl_background = (RelativeLayout) findViewById(R.id.rl_background);
        //需要變換形狀的RelativeLayout
        big_background = (RelativeLayout) findViewById(R.id.big_background);
        //版本號文字
        versionCode = (TextView) findViewById(R.id.versionCode);
        versionCode.setAlpha(0);
        //logo下方文字
        name = (TextView) findViewById(R.id.name);
        name.setAlpha(0);
        preAnim(rl_background);
        mAnimatedSvgView.getLayoutParams().width = getScreenWidth(this) / 2;
        mAnimatedSvgView.getLayoutParams().height = getScreenWidth(this) / 2;


        //路徑傳入,把GIMP2工具導出的path部分作爲String傳遞給該方法.
        mAnimatedSvgView.setGlyphStrings(AnimPath.ANIM_PATH);
        //Path填充顏色
        mAnimatedSvgView.setFillPaints(255,255,255,255);
        //設置跑動光線的顏色
        mAnimatedSvgView.setTraceColors(255,255,255,255);
        //設置輪廓顏色
        mAnimatedSvgView.setTraceResidueColors(255,255,255,255);

        mAnimatedSvgView.setOnStateChangeListener(new AnimatedSvgView.OnStateChangeListener() {
            @Override
            public void onStateChange(int state) {
                if (state == AnimatedSvgView.STATE_FILL_STARTED) {

                    AnimatorSet set = new AnimatorSet();
                    Interpolator interpolator = new DecelerateInterpolator();
                    ObjectAnimator a1 = ObjectAnimator.ofFloat(mAnimatedSvgView, "translationY", 0);
                    a1.setInterpolator(interpolator);
                    set.playTogether(a1);
                    set.start();
                }
            }
        });
    }

    public void preAnim(final View v) {
        GradientDrawable drawable = (GradientDrawable) v.getBackground();
        drawable.setCornerRadius(0);
        ObjectAnimator anim = ObjectAnimator.ofFloat(v, "scaleX", new float[]{1f,1f});
        anim.setDuration(1);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                start(v,700);
            }
        });
        anim.start();
    }

    public void endAnim() {
        AnimatorSet set = new AnimatorSet();
        ObjectAnimator a2 = ObjectAnimator.ofFloat(big_background, "y", big_background.getY(),big_background.getY()/8);
        ObjectAnimator a3 = ObjectAnimator.ofFloat(versionCode, "alpha", 0f,1f);
        ObjectAnimator a4 = ObjectAnimator.ofFloat(name, "alpha", 0f,1f);
        set.playTogether(a2, a3, a4);
        set.setDuration(700);
        set.start();
        mAnimatedSvgView.start();
    }

    /**
     * 矩形變圓角動畫
     */
    public void start(final View v,long duration) {
        //需要的參數 drawable對象
        ObjectAnimator cornerAnimation = ObjectAnimator.ofFloat(v.getBackground(), "cornerRadius", new float[]{0, v.getWidth() / 2});
        cornerAnimation.setDuration(duration);
        final ObjectAnimator heightAnimation = ObjectAnimator.ofInt(v, "xxx", new int[]{v.getHeight(), v.getWidth() / 2});
        heightAnimation.setDuration(duration);
        heightAnimation.addUpdateListener(new com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(com.nineoldandroids.animation.ValueAnimator valueAnimator) {
                v.getLayoutParams().height = (int) heightAnimation.getAnimatedValue();
                v.requestLayout();
            }
        });
        ObjectAnimator animator = ObjectAnimator.ofInt(v, "xx", v.getWidth(), v.getWidth() / 2).setDuration(duration);
        animator.addUpdateListener(new ObjectAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(com.nineoldandroids.animation.ValueAnimator valueAnimator) {
                int value = (int) valueAnimator.getAnimatedValue();
                v.getLayoutParams().width = value;
                v.requestLayout();
            }
        });

        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.play(cornerAnimation).with(heightAnimation).with(animator);
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                endAnim();
            }
        });
        animatorSet.start();
    }

    public int getScreenWidth(Context context) {
        WindowManager manager = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        Display display = manager.getDefaultDisplay();
        return display.getWidth();
    }
}

好了,經過以上步驟就能完成一個簡潔大方的啓動頁動畫了.
最後有幾點補充:
關於demo中的矩形變圓的屬性動畫,需要啓動該動畫的view背景必須是drawable文件,如下形式:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="0dp" />
    <solid android:color="@color/startpage_blue"/>
</shape>

否則在使用啓動屬性動畫是會報錯,當然你也可以不使用這個屬性動畫,用自己的動畫替代.

源碼已上傳到github

快動手寫一個屬於你的獨特的啓動頁動畫吧.
有任何問題歡迎加羣討論:283272067
希望大家多聊技術,多分享代碼.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章