Android 轉場動畫

轉場動畫

轉場動畫: 是Android L 引入的動畫效果, 能夠說是api19引入的場景(Scene)動畫的擴展. 使開發者更加方便的實現佈局(界面)變化時候的過渡動畫.java

Android L 是Google於2014年升級的系統版本號, 在2015年國內廠商新機就開始推送Android L, 如今是2017年我以爲此時不用更待什麼時候.android

轉場動畫(Transition)

在android.transition包下提供關於transitionAnimation的過渡框架, Transiton框架是在api19引入, 可是轉場動畫倒是在api21引入.git

Tip: 某些動畫效果可能須要api23之上github

類關係:api

  • Transition
    • ChangeBounds 改變目標視圖的佈局邊界
    • ChangeClipBounds 裁剪目標視圖邊界
    • ChangeTransform 改變目標視圖的縮放比例和旋轉角度
    • ChangeImageTransform 改變目標圖片的大小和縮放比例
    • ChangeScroll
    • TransitionSet
      • AutoTransition 默認過渡動畫
    • Visibility 其子類都屬於界面切換動畫
      • Explode 爆炸
      • Fade 淡出
      • Slide 上下滑動

Transition是一個不須要考慮關鍵幀(keyFrame)只須要告訴系統你想要的動畫效果就能實現其過渡bash

帶有change前綴的Transition的子類只是針對特有屬性纔有效果app

而Visibility的子類是針對共享元素的座標建立動畫效果框架

簡單的效果實現演示:ide

界面A佈局

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.button) Button mButton;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
    }

    @OnClick(R.id.button) public void onClick() {
        startActivity(new Intent(this, SecondActivity.class), ActivityOptionsCompat.makeSceneTransitionAnimation(this).toBundle());
    }
}
複製代碼

界面B

public class SecondActivity extends AppCompatActivity {

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); // 必須
        setContentView(R.layout.activity_second);

        getWindow().setExitTransition(new Slide());
        getWindow().setEnterTransition(new Slide());
    }
}
複製代碼

Tip: 官方文檔說明轉場動畫要求當前Activity必須在setContentView以前寫入以下代碼, 不過api21以上並不須要如下設置.

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
複製代碼

若是要退出界面仍然有transition動畫不能執行finish, 須要執行finishAfterTransition()

動畫目標

默認轉場動畫會對全部的子View進行遍歷加載動畫, 可是若是添加目標則不會進行遍歷全部子View, 或者你也能夠排除特定View.

對於目標有三個操做

  • 添加

    默認會進行遍歷全部的視圖加載動畫, 可是若是使用了添加就不會遍歷全部, 只會讓指定的視圖進行動畫

  • 排除

    若是使用排除方法, 依舊會進行遍歷視圖對象, 不過會排除你指定的視圖

  • 刪除

    刪除目標是在動畫已經遍歷視圖完成之後還想對目標集合進行變動, 就能夠刪除指定的視圖

添加/排除和刪除目標支持如下參數類型

  1. 視圖對象(View)
  2. 過渡名(TransitionNames)
  3. 字節碼(Class)
  4. ID
Transition addTarget (View target) Transition addTarget (String targetName) Transition addTarget (Class targetType) Transition addTarget (int targetId) 複製代碼

刪除是removeTarget(), 排除是excludeTarget()

轉場動畫都支持設置監聽器

Transition addListener (Transition.TransitionListener listener) 複製代碼

TransitionListener和AnimatorListener同樣的重寫方法.

窗口(Window)

從示例能夠看出轉場動畫在代碼中是經過獲取Window對象進行設置的. 看下Window有哪些關於轉場動畫的方法.

轉場動畫有四種場景:

// 當前界面進入動畫
void setEnterTransition (Transition transition) // 當前界面退出動畫 void setExitTransition (Transition transition) // 如下介紹的是返回時的動畫, 若是不設置就會默認和進入和退出動畫相同 // 下個界面返回當前界面時, 當前界面進入動畫 void setReenterTransition (Transition transition) // 返回上個界面時當前界面退出動畫 void setReturnTransition (Transition transition) 複製代碼

默認狀況下界面A的退出動畫尚未結束時, 界面B的進入動畫就會開始執行. 如下兩個方法默認爲true. 想要進入動畫等待退出動畫結束後再播放就須要如下兩個方法設置爲false.

建議處於默認開啓的狀態, 不然可能出現背景空白期. 若是想清晰的看出幾個不一樣狀態的動畫順序能夠開啓

void setAllowEnterTransitionOverlap (boolean allow) void setAllowReturnTransitionOverlap (boolean allow) 複製代碼

直接設置一個

void setTransitionManager (TransitionManager tm)
複製代碼

在分享元素過渡的時候是否容許重疊

void setSharedElementsUseOverlay (boolean sharedElementsUseOverlay) 複製代碼

Tip: 轉場動畫還支持主題文件裏面直接設置

界面選項(ActivityOptions)

若是想兼容api16以前的系統版本可使用ActivityOptionsCompat

該類用跳轉界面的使用做爲可選參數傳遞;

若是想讓轉場動畫生效就必須使用下面兩種方法開啓界面

// 單一共享元素, 若是沒有共享元素傳入NULL
ActivityOptions makeSceneTransitionAnimation (Activity activity, View sharedElement, String sharedElementName) // 支持多個共享元素 ActivityOptions makeSceneTransitionAnimation (Activity activity, Pair...<View, String> sharedElements) 複製代碼

自定義進入和退出動畫, 和overridePendingTransition方法同樣

ActivityOptions makeCustomAnimation (Context context, int enterResId, int exitResId) 複製代碼

下面介紹三種系統提供的默認動畫效果, 我實際使用感受效果不是很明顯, 感受用處不大.

裁剪動畫, 這是api23(Android m) 新增api.

ActivityOptions makeClipRevealAnimation (View source, int startX, int startY, int width, int height) 複製代碼

縮放動畫

ActivityOptions makeScaleUpAnimation (View source, int startX, int startY, int width, int height) 複製代碼

縮略圖

ActivityOptions makeThumbnailScaleUpAnimation (View source, Bitmap thumbnail, int startX, int startY) 複製代碼

場景(Scene)

場景能夠理解爲在一個界面(Activity)當中切換或者改變佈局內容, 場景是在api19引入

建立方式有兩種, 一種是經過如下的靜態方法直接建立

Scene getSceneForLayout (ViewGroup sceneRoot, int layoutId, Context context) 複製代碼

或者經過構造方法

Scene (ViewGroup sceneRoot,  // 當前場景
                View layout) // 須要進入的新場景
複製代碼

sceneRoot能夠稱爲根視圖. 在官方示例中是當前界面佈局的視圖對象, 能夠理解爲其場景(Scene)依附的Activity容器

若是你須要動態的設置場景的視圖內容, 能夠只指定根視圖

Scene (ViewGroup sceneRoot)
複製代碼

進入場景和退出場景, 不帶任何動畫. 通常狀況下場景的進入由TransitionManager負責

void enter ()

void exit ()
複製代碼

exit並不會對場景有任何變化

在場景進入和退出時能夠設置兩個回調方法

void setEnterAction (Runnable action)

void setExitAction (Runnable action)
複製代碼

Tip: 若是兩個場景存在相同的ID會自動進行共享元素動畫(前提是用的不是默認的AutoTransiton, 由於該類沒有使用Change)

過渡管理器(TransitionManager)

Scene默認是沒有針對場景的變化, TransitionManager提供兩種方式

  1. 這種默認的過渡動畫是 AutoTransition

    static void go (Scene scene) 複製代碼

  2. 自定義過渡動畫

    static void go (Scene scene, Transition transition) 複製代碼

開始延遲過渡, 即保存當前視圖的屬性狀態, 而後在以後其發生改變的時候自動進行過渡動畫

void beginDelayedTransition (ViewGroup sceneRoot) void beginDelayedTransition (ViewGroup sceneRoot, Transition transition) 複製代碼

後面還能夠結束自動保存屬性狀態

void endTransitions (ViewGroup sceneRoot)
複製代碼

場景切換

// 建立一個自定義Transition動畫的TransitionManager
mTransitionManagerForScene3 = TransitionInflater.from(getActivity())
.inflateTransitionManager(R.transition.scene3_transition_manager, mSceneRoot);

// 而後切換任意佈局
mTransitionManagerForScene3.transitionTo(mScene3);
複製代碼

該方法等同於提到的go()

void transitionTo (Scene scene) 複製代碼

XML定義

不一樣於普通的動畫, 轉場動畫擁有專屬的資源目錄transition

在res/transition目錄下建立XML文件

標籤一覽

引用XML

Transition explode = TransitionInflater.from(this).inflateTransition(R.transition.explode);
複製代碼

或者能夠直接在主題中設置

<item name="android:windowExitTransition">@transition/explode</item>
<item name="android:windowEnterAnimation">@transition/explode</item>
<item name="android:windowReenterTransition">@transition/explode</item>
複製代碼

TransitionInflat除上面提到的方法外還能夠填充trantionManager對象

TransitionManager inflateTransitionManager (int resource, ViewGroup sceneRoot) 複製代碼

共享元素(ShareElement)

共享元素

通常是在關聯的界面以前存在相同的(或者說相似的, 並不強制必定要相同)控件元素就會使用, 例以下圖的按鈕:

A界面跳轉要指定共享元素

startActivity(new Intent(this, SecondActivity.class),
                ActivityOptionsCompat.makeSceneTransitionAnimation(this, mButton, "button")
                        .toBundle());
複製代碼

B界面的佈局文件中指定共享元素android:transitionName="button"

<Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="第二個界面" android:transitionName="button" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" android:layout_marginTop="99dp" />
複製代碼

能夠看到所謂的共享元素即在兩個界面的兩個控件(或多個控件)之間的過渡變化效果

能夠看到轉場動畫的操做都是針對Window對象, 擁有以下方法(同時都擁有對應的getter方法)

共享元素

void setSharedElementEnterTransition (Transition transition) void setSharedElementExitTransition (Transition transition) void setSharedElementReenterTransition (Transition transition) void setSharedElementReturnTransition (Transition transition) 複製代碼

自定義Transiton

主要重寫三個方法

  1. 開始值
  2. 結束值
  3. 建立動畫

官方示例

Tip: 針對不一樣的View採用不一樣的動畫效果能夠重寫Transition

擴散(Propagation)

Propagation能夠指定Transition中的視圖過渡延遲, 控制進入當前場景的視圖進入的前後順序. 例如要求Explode動畫中特定的View速度快於其餘的視圖.

擴散中心

首先須要Transition確認擴散中心

void setEpicenterCallback (Transition.EpicenterCallback epicenterCallback) 複製代碼

在Transiton.EpicenterCallback回調中須要重寫如下方法

Rect onGetEpicenter (Transition transition) 複製代碼

在回調方法內返回一個矩形, 其矩形的中心即擴散中心.

關係:

  • TransitionPropagation
    • VisibilityPropagation
      • SidePropagation
      • CircularPropagation

經過transition的方法指定

void setPropagation (TransitionPropagation transitionPropagation) // 設置擴散 void setPropagationSpeed (float propagationSpeed) // 設置速度 複製代碼

查看源碼能夠看到Explode默認使用的CircularPropagation

Slide使用的天然是SlidePropagation

TransitionPropagation 屬於抽象類提供三個重寫方法

void captureValues (TransitionValues transitionValues) String[] getPropagationProperties () long getStartDelay (ViewGroup sceneRoot, Transition transition, TransitionValues startValues, TransitionValues endValues) 複製代碼

分別控制:

  1. 捕捉

示例

slide.setPropagation(new VisibilityPropagation() {
  @Override public long getStartDelay(ViewGroup sceneRoot, Transition transition, TransitionValues startValues, TransitionValues endValues) {
    return 0;
  }
});
複製代碼

路徑動做

PathMotion是在api21引入的過渡動畫的一種新的實現方式. 能夠經過指定路徑來限制動畫運動軌跡

經過Transition設置路徑動畫

void setPathMotion (PathMotion pathMotion) 複製代碼

PathMotion

  • ArcMotion (弧形動做)
  • PatternPathMotion

弧形軌跡

共享元素都是在不一樣的界面間的位置變化是以直線運動的, 經過指定如下路徑動做能夠變成弧形軌跡

參考 GooglePlay 的實現效果

<changeBounds>
   <arcMotion android:minimumHorizontalAngle="15" android:minimumVerticalAngle="0" android:maximumAngle="90"/>
 </changeBounds>
複製代碼

參數:

  • android:maximumAngle

    ​ 開始和結束的最大弧形角度

  • android:minimumHorizontalAngle

    ​ 二者接近水平的時候最小角度

  • android:minimumVerticalAngle

    ​ 垂直同上

路徑動做

能夠徹底自定義路徑來控制共享元素的運動軌跡

<changeBounds>
     <patternPathMotion android:patternPathData="M0 0 L0 100 L100 100"/>
 </changeBounds>
複製代碼

Tip: patternPathData 的參數值相似矢量動畫

自定義路徑動做

<changeBounds>
     <pathMotion class="my.app.transition.MyPathMotion"/>
 </changeBounds>
複製代碼
相關文章
相關標籤/搜索