1. 程式人生 > >Android 5.X 新特性詳解(四)——Material Design 動畫效果

Android 5.X 新特性詳解(四)——Material Design 動畫效果

Ripple效果

在Android 5.X 中,Material Design 大量使用了Ripple效果,即點選後的波紋效果。可以通過如下程式碼設定波紋的背景。

//有界波紋
android:background="?android:attr/selectableItemBackground"
//無界波紋
android:background="?android:attr/selectableItemBackgroundBorderless"

有界波紋是指波紋被限制在控制元件的邊界中,而無界波紋則是波紋不會限制在控制元件邊界中,會呈圓形發散出去。波紋效果示例XML程式碼如下:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:background="@android:color/holo_blue_bright">
<Button android:layout_width="100dp" android:layout_height
="100dp" android:textColor="@android:color/white" android:background="?android:attr/selectableItemBackground" android:text="有界波紋" />
<Button android:layout_width="100dp" android:layout_height="100dp" android:background="?android:attr/selectableItemBackgroundBorderless"
android:textColor="@android:color/white" android:text="無界波紋" />
</LinearLayout>

同樣可以在XML檔案中直接來建立一個具有Ripple效果的XML檔案,程式碼如下所示:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@android:color/holo_blue_bright">

    <item>
        <shape android:shape="oval">
            <solid android:color="?android:colorPrimary" />
        </shape>
    </item>

</ripple>

Circular Reveal

Circular Reveal動畫效果具體表現為一個View以圓形的形式展開、揭示出來。通過ViewAnimationUtils.createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius)方法建立一個RevealAnimator動畫。

createCircularReveal方法的使用非常簡單,這要是設定幾個關鍵的座標點:

  • centerX——動畫開始的中心點X
  • centerY——動畫開始的中心點Y
  • startRadius——動畫開始半徑
  • endRadius——動畫結束半徑

示例程式碼如下:

public class CircularActivity extends Activity {

    private View oval, rect;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_circular);
        oval = findViewById(R.id.oval);
        oval.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Animator animator = ViewAnimationUtils.createCircularReveal(oval, oval.getWidth() / 2,
                        oval.getHeight() / 2, oval.getWidth(), 0);
                animator.setInterpolator(new AccelerateDecelerateInterpolator());
                animator.setDuration(2000);
                animator.start();
            }
        });

        rect = findViewById(R.id.rect);
        rect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Math.hypot方法獲取直角三角形斜邊的長度
                Animator animator = ViewAnimationUtils.createCircularReveal(rect, 0,
                        0, 0, (float) Math.hypot(rect.getWidth(), rect.getHeight()));
                animator.setInterpolator(new AccelerateDecelerateInterpolator());
                animator.setDuration(2000);
                animator.start();
            }
        });
    }

}

以上程式碼中設定了兩種形式,通過設定不同的座標值,改變圓形展開的方式和效果。

View state changes Animation

在Android 5.X 中,系統提供了檢視狀態改變來設定一個檢視的狀態切換動畫。

StateListAnimator

StateListAnimator作為檢視改變時的動畫效果,通常會使用Selector來進行設定,但以前設定Selector的時候,通常是修改背景來達到反饋的效果。現在。在Android 5.X 中,可以使用動畫來作為檢視改變的效果。

在XML中定義一個StateListAnimator,並新增到Selector中,程式碼如下所示:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true">
        <set>
            <objectAnimator android:propertyName="rotationX"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="360"
                android:valueType="floatType"/>
        </set>
    </item>

    <item android:state_pressed="false">
        <set>
            <objectAnimator android:propertyName="rotationX"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="0"
                android:valueType="floatType"/>
        </set>
    </item>

</selector>

在一般的XML佈局中,使用如下程式碼來將StateListAnimator新增給一個檢視。

    <Button
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:stateListAnimator="@drawable/state_list" />

同樣,在程式碼中也可以呼叫AnimatorInflater.loadStateListAnimator()方法,並且通過View.setStateListAnimator()`方法分配動畫到檢視上。

animated-selector

animated-selector同樣是一個狀態改變的動畫效果Selector。在Android 5.X 中,很多Material Design 的控制元件設計,都是通過這種方式來實現,例如check_box的動畫效果,就是使用類似幀動畫的切換效果,模擬進行點選時的切換效果。

實現一個具有動畫效果的狀態切換按鈕,首先需要一組狀態切換圖,如下圖所示:

這裡寫圖片描述

有了這樣一組圖,就可以在XML檔案中定義animated-selector。animated-selector與selector的使用十分類似,同樣是通過item標籤來區分不同的狀態。圖ic_done_anim_000與圖ic_plus_anim_030分別代表兩種不同的狀態。同時也給這兩種狀態增加了ID來進行區分,並使用transition標籤來給這兩種狀態設定不同的過渡圖片,這點非常類似Android中的幀動畫效果。

<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/state_on"
        android:state_checked="true">
        <bitmap android:src="@drawable/ic_done_anim_000" />
    </item>

    <item android:id="@+id/state_off">
        <bitmap android:src="@drawable/ic_plus_anim_030" />
    </item>

    <transition
        android:fromId="@+id/state_on"
        android:toId="@+id/state_off">
        <animation-list>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_000" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_001" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_002" />
            </item>

                、、、

            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_028" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_029" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_030" />
            </item>
        </animation-list>
    </transition>

    <transition
        android:fromId="@+id/state_off"
        android:toId="@+id/state_on">
        <animation-list>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_000" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_001" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_002" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_003" />
            </item>

        、、、

            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_028" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_029" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_030" />
            </item>
        </animation-list>
    </transition>

</animated-selector>

有了animated-selector之後,只需要把它應用到一個ImageView上即可。同時在程式碼中設定不同的點選狀態。在Android中,通常使用系統屬性來設定切換狀態。

public class ViewStateActivity extends Activity {

    private boolean mIsCheck;
    private ImageView mImageView;
    private static final int[] STATE_CHECKED = new int[]{android.R.attr.state_checked};
    private static final int[] STATE_UNCHECKED = new int[]{};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_state);
        mImageView = (ImageView) findViewById(R.id.image);
    }

    public void anim(View view) {
        if(mIsCheck){
            mImageView.setImageState(STATE_UNCHECKED, true);
            mIsCheck = false;
        }else{
            mImageView.setImageState(STATE_CHECKED, true);
            mIsCheck = true;
        }
    }

}

程式執行效果如圖所示:

這裡寫圖片描述

程式碼地址