定義定製動畫

定義定製動畫

材料設計中的動畫將爲用戶提供操作反饋並在用戶與您的應用進行互動時提供視覺連續性。 材料主題將爲按鈕與操作行爲轉換提供一些默認動畫,而 Android 5.0(API 級別 21)及更高版本可讓您定製這些動畫,同時也可創建新動畫:

  • 觸摸反饋
  • 循環揭露
  • 操作行爲轉換
  • 曲線運動
  • 視圖狀態改變

定製觸摸反饋


材料設計中的觸摸反饋可在用戶與 UI 元素互動時,在接觸點上提供即時視覺確認。 適用於按鈕的默認觸摸動畫使用全新 RippleDrawable 類別,以波紋效果實現不同狀態間的轉換。

在大多數情況下,您應以下列方式指定視圖背景,在您的視圖 XML 中應用此功能:

  • ?android:attr/selectableItemBackground 指定有界的波紋。
  • ?android:attr/selectableItemBackgroundBorderless 指定越過視圖邊界的波紋。 它將由一個非空背景的視圖的最近父項所繪製和設定邊界。

注意:selectableItemBackgroundBorderless 是 API 級別 21 中推出的新屬性。

此外,您可利用 ripple 元素將 RippleDrawable 定義爲一個 XML 資源。

您可以爲 RippleDrawable 對象指定一種顏色。如果要改變默認觸摸反饋顏色,請使用主題的 android:colorControlHighlight 屬性。

如果要了解更多信息,請參閱 RippleDrawable 類別的 API 參考文檔。

使用揭露效果


當您顯示或隱藏一組 UI 元素時,揭露動畫可爲用戶提供視覺連續性。ViewAnimationUtils.createCircularReveal() 方法讓您能夠爲裁剪區域添加動畫以揭露或隱藏視圖。

如果要使用此效果揭露之前不可見的視圖:

// previously invisible view
View myView = findViewById(R.id.my_view);

// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;

// get the final radius for the clipping circle
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());

// create the animator for this view (the start radius is zero)
Animator anim =
    ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);

// make the view visible and start the animation
myView.setVisibility(View.VISIBLE);
anim.start();

如果要使用此效果隱藏之前可見的視圖:

// previously visible view
final View myView = findViewById(R.id.my_view);

// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;

// get the initial radius for the clipping circle
int initialRadius = myView.getWidth();

// create the animation (the final radius is zero)
Animator anim =
    ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);

// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        myView.setVisibility(View.INVISIBLE);
    }
});

// start the animation
anim.start();

定製操作行爲轉換


圖 1 - 擁有共享元素的轉換。

如果要重新播放影片,請點擊設備屏幕

材料設計應用中的操作行爲轉換透過通用元素之間的移動和轉換提供不同狀態之間的視覺連接。 您可爲進入、退出轉換以及操作行爲之間的共享元素轉換指定定製動畫。

  • 進入轉換將決定操作行爲中視圖如何進入場景。例如,在分解進入轉換中,視圖將從屏幕外進入場景並飛往屏幕中心。
  • 退出轉換將決定操作行爲中應用行爲的顯示視圖如何退出場景。例如,在分解退出轉換中,視圖將從屏幕中心退出場景。
  • 共享元素轉換將決定兩個操作行爲轉換之間共享的視圖如何在這些操作行爲中轉換。 例如,如果兩個操作行爲擁有相同的圖像,但其位置與大小不同,changeImageTransform 共享元素轉換將在這些操作行爲之間平滑地轉換與縮放圖像。

Android 5.0(API 級別 21)支持這些進入與退出轉換:

  • 分解 - 從場景中心移入或移出視圖。
  • 滑動 - 從場景邊緣移入或移出視圖。
  • 淡入淡出 - 通過調整透明度在場景中增添或移除視圖。

任何擴展 Visibility 類別的轉換均將獲得進入或退出轉換支持。 如果要了解更多信息,請參閱Transition 類別的 API 參考文檔。

Android 5.0(API 級別 21)也支持這些共享元素轉換:

  • changeBounds - 爲目標視圖的佈局邊界的變化添加動畫。
  • changeClipBounds - 爲目標視圖的裁剪邊界的變化添加動畫。
  • changeTransform - 爲目標視圖的縮放與旋轉變化添加動畫。
  • changeImageTransform - 爲目標圖像的大小與縮放變化添加動畫。

當您在您的應用中啓用操作行爲轉換,默認的交叉淡入淡出轉換將在進入與退出操作行爲之間激活。


  圖 2 - 擁有一個共享元素的場景轉換。

指定定製轉換

首先,在定義您從材料主題繼承的風格時,使用 android:windowContentTransitions 屬性啓用窗口內容轉換。您也可在您的風格定義中指定進入、退出以及共享元素轉換:

<style name="BaseAppTheme" parent="android:Theme.Material">
  <!-- enable window content transitions -->
  <item name="android:windowContentTransitions">true</item>

  <!-- specify enter and exit transitions -->
  <item name="android:windowEnterTransition">@transition/explode</item>
  <item name="android:windowExitTransition">@transition/explode</item>

  <!-- specify shared element transitions -->
  <item name="android:windowSharedElementEnterTransition">
    @transition/change_image_transform</item>
  <item name="android:windowSharedElementExitTransition">
    @transition/change_image_transform</item>
</style>

此示例中的 change_image_transform 轉換定義如下:

<!-- res/transition/change_image_transform.xml -->
<!-- (see also Shared Transitions below) -->
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
  <changeImageTransform/>
</transitionSet>

changeImageTransform 元素與 ChangeImageTransform 類別相對應。如果要了解更多信息,請參閱 Transition 的 API 參考。

如果要在您的代碼中啓用窗口內容轉換,請調用 Window.requestFeature() 方法:

// inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

// set an exit transition
getWindow().setExitTransition(new Explode());

如果要在您的代碼中指定轉換,請以 Transition 對象調用這些方法:

setExitTransition() 和 setSharedElementExitTransition() 方法定義正在調用的操作行爲的退出轉換。 setEnterTransition() 與setSharedElementEnterTransition() 方法定義被調用的操作行爲的進入轉換。

如果要取得轉換的完整效果,您必須在正在調用以及被調用的操作行爲上啓用窗口內容轉換。 否則,正在調用的操作行爲將開始退出轉換,但是您將會看到窗口轉換(例如縮放或淡入淡出)。

如果要儘快開始進入轉換,請針對被調用的操作行爲使用 Window.setAllowEnterTransitionOverlap() 方法。這可以讓您實現更生動的進入轉換。

使用轉換啓動一個操作行爲

如果您啓用轉換並且爲一個操作行爲設置退出轉換,那麼在您啓動另一個操作行爲時,轉換將以下列方式激活:

startActivity(intent,
              ActivityOptions.makeSceneTransitionAnimation(this).toBundle());

如果您已爲第二個操作行爲設置進入轉換,則轉換也將會在操作行爲啓動時激活。 如果要在您啓動另一個操作行爲時禁用轉換,請提供 null 選項包。

以共享元素啓動一個操作行爲

如果要在兩個擁有共享元素的操作行爲之間安排屏幕轉換動畫:

  1. 請在您的主題中啓用窗口內容轉換。
  2. 在您的風格中指定一個共享元素轉換。
  3. 將您的轉換定義爲 XML 資源。
  4. 利用 android:transitionName 屬性對兩個佈局中的共享元素指定一個通用名稱。
  5. 使用 ActivityOptions.makeSceneTransitionAnimation() 方法。
// get the element that receives the click event
final View imgContainerView = findViewById(R.id.img_container);

// get the common element for the transition in this activity
final View androidRobotView = findViewById(R.id.image_small);

// define a click listener
imgContainerView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(this, Activity2.class);
        // create the transition animation - the images in the layouts
        // of both activities are defined with android:transitionName="robot"
        ActivityOptions options = ActivityOptions
            .makeSceneTransitionAnimation(this, androidRobotView, "robot");
        // start the new activity
        startActivity(intent, options.toBundle());
    }
});

對於在您的代碼中生成的共享動態視圖,請使用 View.setTransitionName() 方法在兩個操作行爲中指定一個通用元素名稱。

如果要在完成第二項操作行爲時反轉場景轉換動畫,請調用 Activity.finishAfterTransition() 方法而非 Activity.finish()

以多個共享元素啓動一個操作行爲

如果要在兩個擁有多個共享元素的操作行爲之間安排場景轉換動畫,請以 android:transitionName 屬性(或在兩個操作行爲中使用View.setTransitionName() 方法)定義共享元素,並以下列方式創建一個 ActivityOptions 對象:

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
        Pair.create(view1, "agreedName1"),
        Pair.create(view2, "agreedName2"));

使用曲線運動


材料設計中的動畫利用曲線實現時間內插與空間移動模式。 利用 Android 5.0(API 級別 21)及更高版本,您可爲動畫定義定製時間曲線以及曲線運動模式。

PathInterpolator 類別是一個基於貝塞爾曲線或 Path 對象的全新插入器。 此插入器在一個 1x1 的正方形內指定一個運動曲線,定位點位於 (0,0) 以及 (1,1),而控制點則使用構造函數參數指定。 您也可以將路徑插入器定義爲一個 XML 資源:

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:controlX1="0.4"
    android:controlY1="0"
    android:controlX2="1"
    android:controlY2="1"/>

系統將爲材料設計規範中的三種基本曲線提供 XML 資源:

  • @interpolator/fast_out_linear_in.xml
  • @interpolator/fast_out_slow_in.xml
  • @interpolator/linear_out_slow_in.xml

您可以將一個 PathInterpolator 對象傳遞給 Animator.setInterpolator() 方法。

ObjectAnimator 類別擁有新的構造函數,可讓您一次使用兩個或更多屬性在路徑上爲座標添加動畫。 例如,下列動畫使用 Path 對象爲視圖的 X 和 Y 屬性添加動畫:

ObjectAnimator mAnimator;
mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
...
mAnimator.start();

爲視圖狀態改變添加動畫


StateListAnimator 類別讓您能夠定義視圖狀態改變時運行的動畫。 下列示例顯示如何將 StateListAnimator 定義爲一個 XML 資源:

<!-- animate the translationZ property of a view when pressed -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_pressed="true">
    <set>
      <objectAnimator android:propertyName="translationZ"
        android:duration="@android:integer/config_shortAnimTime"
        android:valueTo="2dp"
        android:valueType="floatType"/>
        <!-- you could have other objectAnimator elements
             here for "x" and "y", or other properties -->
    </set>
  </item>
  <item android:state_enabled="true"
    android:state_pressed="false"
    android:state_focused="true">
    <set>
      <objectAnimator android:propertyName="translationZ"
        android:duration="100"
        android:valueTo="0"
        android:valueType="floatType"/>
    </set>
  </item>
</selector>

如果要將定製視圖狀態動畫附加至一個視圖,請依照此示例使用 XML 資源文件中的 selector 元素定義一個動畫,並使用 android:stateListAnimator屬性將此動畫分配給您的視圖。 如果要將一個狀態列表動畫分配給您的代碼內的一個視圖,請使用 AnimationInflater.loadStateListAnimator() 方法,並以 View.setStateListAnimator() 方法將動畫分配給您的視圖。

當您的主題擴展材料主題時,在默認情況下按鈕將擁有一個 Z 動畫。如果要避免您的按鈕出現這類行爲,請將 android:stateListAnimator 屬性設置爲@null

AnimatedStateListDrawable 類別讓您能夠創建圖片,顯示相關視圖之間的狀態變化。 Android 5.0 中的某些系統小組件在默認情況下使用這些動畫。 下列示例顯示如何將 AnimatedStateListDrawable 定義爲一個 XML 資源:

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

    <!-- provide a different drawable for each state-->
    <item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
        android:state_pressed="true"/>
    <item android:id="@+id/focused" android:drawable="@drawable/drawableF"
        android:state_focused="true"/>
    <item android:id="@id/default"
        android:drawable="@drawable/drawableD"/>

    <!-- specify a transition -->
    <transition android:fromId="@+id/default" android:toId="@+id/pressed">
        <animation-list>
            <item android:duration="15" android:drawable="@drawable/dt1"/>
            <item android:duration="15" android:drawable="@drawable/dt2"/>
            ...
        </animation-list>
    </transition>
    ...
</animated-selector>

爲矢量圖片添加動畫


矢量圖片可在不丟失定義的情況下縮放。 AnimatedVectorDrawable 類別可讓您爲矢量圖片的屬性添加動畫。

您通常可以在 3 個 XML 文件中定義添加動畫的矢量圖片:

  • 在 res/drawable/ 中擁有 <vector> 元素的矢量圖片
  • 在 res/drawable/ 中擁有 <animated-vector> 元素且已添加動畫的矢量圖片
  • 在 res/anim/ 中擁有 <objectAnimator> 元素的一個或多個對象動畫

添加動畫的矢量圖片可爲 <group> 以及 <path> 元素的屬性添加動畫。<group> 元素定義路徑集或子組,而 <path> 元素則定義將繪製的路徑。

當您定義一個您想要添加動畫的矢量圖片時,請使用 android:name 屬性給這些羣組和路徑指定一個唯一名稱,以便讓您能夠從您的動畫定義中引用這些羣組或路徑。 例如:

<!-- res/drawable/vectordrawable.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="64dp"
    android:width="64dp"
    android:viewportHeight="600"
    android:viewportWidth="600">
    <group
        android:name="rotationGroup"
        android:pivotX="300.0"
        android:pivotY="300.0"
        android:rotation="45.0" >
        <path
            android:name="v"
            android:fillColor="#000000"
            android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
    </group>
</vector>

已添加動畫的矢量圖片定義按名稱引用矢量圖片內的羣組和路徑:

<!-- res/drawable/animvectordrawable.xml -->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
  android:drawable="@drawable/vectordrawable" >
    <target
        android:name="rotationGroup"
        android:animation="@anim/rotation" />
    <target
        android:name="v"
        android:animation="@anim/path_morph" />
</animated-vector>

動畫定義代表着 ObjectAnimator 或 AnimatorSet 對象。此示例中的第一個動畫將目標羣組旋轉 360 度:

<!-- res/anim/rotation.xml -->
<objectAnimator
    android:duration="6000"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="360" />

此示例中的第二個動畫對矢量圖片的路徑進行變形。 兩個路徑均需可兼容變形操作:兩個路徑均需擁有相同數量的指令,而且每個指令均需擁有相同數量的參數。

<!-- res/anim/path_morph.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="3000"
        android:propertyName="pathData"
        android:valueFrom="M300,70 l 0,-70 70,70 0,0   -70,70z"
        android:valueTo="M300,70 l 0,-70 70,0  0,140 -70,0 z"
        android:valueType="pathType" />
</set>

如果要了解更多信息,請參閱 AnimatedVectorDrawable 的 API 參考文檔。


原文:https://developer.android.com/training/material/animations.html#Touch

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