android中的Transition動畫的使用

1. 簡介

Transition框架是安卓4之後引入的一個轉場框架。能夠在場景轉換時的加入轉場動畫(slide,fade等等)效果,使app更加炫酷。 這裏須要注意的是Transition的用途有兩種。php

  1. Activity和Activity之間, Fragment和Fragment之間,Activity和Fragment之間。
  2. 在一個ViewGroup內的佈局變化。

2. 名詞解釋

還須要解釋下關鍵的名詞。 Scene: 一個佈局場景 Transition: 兩個場景間的動態變化,便可以理解爲會產生動畫效果java

當一個Scene到另外一個Scene時,Transition的職責爲以下:android

  1. 獲取先後兩個Scene的狀態
  2. 建立Animator,並計算動畫效果,而後播放動畫。

3. 相關動畫類型

4. 動畫的建立方法

4.1 xml文件

在res文件夾下建立一個transition文件夾。並在裏面建立xml動畫文件。git

<?xml version="1.0" encoding="utf-8"?>
<fade xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:interpolator/accelerate_decelerate" android:duration="200" android:transitionOrdering="sequential" />
複製代碼

此時若是要在代碼中引用該文件時能夠用下面的方法。github

window.exitTransition = TransitionInflater.from(this).inflateTransition(R.transition.fade_transition)
複製代碼

4.2 利用代碼

window.exitTransition = 
    Slide().apply {
        duration = 200
        slideEdge = Gravity.END
    }
複製代碼

4.3 建立多轉場

利用xml:數據結構

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android" android:transitionOrdering="together">
    <explode android:duration="1000" android:interpolator="@android:interpolator/accelerate_decelerate" />
    <fade android:duration="1000" android:fadingMode="fade_in_out" android:interpolator="@android:interpolator/accelerate_decelerate" />
    <slide android:duration="500" android:interpolator="@android:interpolator/accelerate_decelerate" android:slideEdge="top" />
</transitionSet>
複製代碼

利用代碼:app

val transitionSet = TransitionSet()
                transitionSet.addTransition(Fade())
                transitionSet.addTransition(Slide())
                transitionSet.setOrdering(ORDERING_TOGETHER)
複製代碼

5. Activity之間的轉場動畫

5.1 各Activity的轉場

A.exitTransition(): 從A到B時A的退出動畫 B.enterTransition(): 從A到B時B的進場動畫 B.returnTransition(): 從B返回A時的退出動畫 A.reenterTransition(): 從B返回A時的進場動畫框架

5.2 進場退場的過渡動畫

  1. explore : 將View移入場景中心或從中移出。
  2. slide : 將視圖從場景的其中一個邊緣移入或移出。能夠利用slideEdge=Gravity.Start方式設置移入移出邊緣。
  3. fade : 經過更改視圖的不透明度,在場景中添加視圖或從中移除視圖。

系統支持將任何擴展 Visibility 類的過渡做爲進入或退出過渡。ide

5.3 轉場設置

須要在activity的onCreate中設置轉場動畫。佈局

window.let {
            // 設置分享元素的轉場(後面會講到)
            it.sharedElementEnterTransition
            it.sharedElementExitTransition
            it.sharedElementReenterTransition
            it.sharedElementReturnTransition
            
            // 設置是否需動畫覆蓋,轉場動畫中動畫之間會有覆蓋的狀況
            // 能夠設置false來讓動畫有序的進入退出
            it.allowEnterTransitionOverlap = false
            it.allowReturnTransitionOverlap = false
            
            // 設置activity之間的轉場動畫
// it.exitTransition = TransitionInflater.from(this).inflateTransition(R.transition.fade_transition)
            it.exitTransition = Slide().apply {
                duration = 200
                slideEdge = Gravity.END
            }
            it.enterTransition = Slide().apply {
                duration = 200
                slideEdge = Gravity.START

            }
            it.reenterTransition = Slide().apply {
                duration = 200
                slideEdge = Gravity.END
            }
            it.returnTransition = Slide().apply {
                duration = 200
                slideEdge = Gravity.START
            }
        }
複製代碼

動畫設置完了,下一步咱們是須要進行跳轉的工做。 activity之間跳轉須要用到intent, 若是須要它們之間傳遞數據是要用到Bundle。 沒有錯,咱們要設置的轉場動畫也要用到Bundle。咱們看一下下面的代碼。

btn2.setOnClickListener {
    val intent = Intent()
    intent.setClass(this, ThirdActivity::class.java)
    // 利用ActivityOptions生成TransitionActivityOptions
    val transitionActivityOptions = ActivityOptions.makeSceneTransitionAnimation(
        this@MainActivity
    )
    // 利用上面生成的TransitionActivityOptions生成Bundle
    startActivity(intent, transitionActivityOptions.toBundle())
}
複製代碼

6. Activity之間的元素共享轉場

元素共享轉場是Meterial設計中我的比較喜歡的設計之一。 activity之間的轉場總有頓挫感,可是利用元素共享轉場可讓前一個畫面中的元素能夠在下一個畫面上流暢的顯示。

6.1 轉場元素設置

1. 首先咱們須要讓元素共享轉場有效。

其實上面講到過設置方法,以下。

window.let {
    // 設置分享元素的轉場
    it.sharedElementEnterTransition
    it.sharedElementExitTransition
    it.sharedElementReenterTransition
    it.sharedElementReturnTransition
}
複製代碼
2. 設置transitionName

要想讓元素共享,須要讓前一個畫面的元素的id和後一個元素的id相同。 還有須要設置transitionName,設置的地方是layout的xml上。 固然,transitionName也須要先後一致。 以下。

<ImageView android:id="@+id/img" android:layout_width="240dp" android:layout_height="160dp" android:scaleType="fitCenter" android:src="@mipmap/android_logo" android:transitionName="img" // 就是這個 app:layout_constraintBottom_toTopOf="@id/txt" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_chainStyle="packed" />
複製代碼

6.2 動畫設置

咱們須要爲轉場元素設置動畫。在activity的onCreatewindow上進行設置。

override fun onCreate(savedInstanceState: Bundle?) {
        // 爲轉場元素設置動畫
        window.sharedElementEnterTransition = ChangeBounds()
        window.sharedElementExitTransition = ChangeBounds()
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
 }
複製代碼

須要注意的是先後兩個畫面都須要爲共享元素設置轉場動畫。固然動畫能夠是不同的,這個部分根據本身須要進行設置就行了。

6.3 進行轉場

val intent = Intent()
val pair1 = Pair(imgView as View, imgView.transitionName)
val pair2 = Pair(textView as View, textView.transitionName)
intent.setClass(this, SecondActivity::class.java)
val transitionActivityOptions = ActivityOptions.makeSceneTransitionAnimation(
    this@MainActivity,
    pair1, pair2
)
startActivity(intent, transitionActivityOptions.toBundle())
複製代碼

跟上面同樣也是轉換成Bundle進行轉場的設置。 可是由於須要共享元素,ActivityOptions.makeSceneTransitionAnimation中加入共享元素信息。 這裏須要用到的是Pair的數據結構,Pair的左邊是共享的view,右邊是剛剛設置的transitionName。 若是共享元素只有一個的狀況能夠直接使用以下方法。

val intent = Intent()
intent.setClass(this, SecondActivity::class.java)
val transitionActivityOptions = ActivityOptions.makeSceneTransitionAnimation(
    this@MainActivity,
    imgView as View, imgView.transitioName
)
startActivity(intent, transitionActivityOptions.toBundle())
複製代碼

7. 一個畫面的Scene轉換

除了Activity之間的轉換還有一個佈局內的scene轉換。

7.1 建立Scene

爲兩個佈局建立Scene。

val scene1 = Scene.getSceneForLayout(sceneRoot, R.layout.scene1, this)
val scene2 = Scene.getSceneForLayout(sceneRoot, R.layout.scene2, this)
複製代碼

除了上面的方法,也能夠用下面方法進行建立。

scene1 = Scene.getSceneForLayout(sceneRoot,R.layout.scene_layout1,this)
scene2 = Scene.getSceneForLayout(sceneRoot,R.layout.scene_layout2,this)
複製代碼

注意的是須要建立先後兩個Scene的控件的ID相同。

7.2 切換Scene

建立Transition動畫。

val transition =  TransitionInflater.from(this).inflateTransition(R.transition.slide_transition)
複製代碼

利用TransitionManager進行Scene的切換。

TransitionManager.go(scene2, transition)
複製代碼

7.3 完整的代碼

// 建立Scene
val scene1 = Scene.getSceneForLayout(sceneRoot, R.layout.scene1, this)
val scene2 = Scene.getSceneForLayout(sceneRoot, R.layout.scene2, this)
var count = 1

btn.setOnClickListener {
    count = if (count == 1) {
    // 建立transition動畫
    val transition =
TransitionInflater.from(this).inflateTransition(R.transition.slide_transition)
    // Scene切換
    TransitionManager.go(scene2, transition)
        2
    } else {
    val transition =
 TransitionInflater.from(this).inflateTransition(R.transition.slide_transition)
    TransitionManager.go(scene1, transition)
        1
    }
}
複製代碼

8. 限制(來源:官方文檔)

  • Android 版本在 4.0(API Level 14)4.4.2(API Level 19) 使用 Android Support Library’s
  • 應用於 SurfaceView 的動畫可能沒法正確顯示。 SurfaceView 實例是從非界面線程更新的,所以這些更新與其餘視圖的動畫可能不一樣步。
  • 當應用於 TextureView 時,某些特定過渡類型可能沒法產生所需的動畫效果。
  • 擴展 AdapterView 的類(例如 ListView)會以與過渡框架不兼容的方式管理它們的子視圖。若是您嘗試爲基於 AdapterView 的視圖添加動畫效果,則設備顯示屏可能會掛起。
  • 若是您嘗試使用動畫調整 TextView 的大小,則文本會在該對象徹底調整過大小以前彈出到新位置。爲了不出現此問題,請勿爲調整包含文本的視圖的大小添加動畫效果。

github: github.com/HyejeanMOON…

相關文章
相關標籤/搜索