Transition框架是安卓4之後引入的一個轉場框架。能夠在場景轉換時的加入轉場動畫(slide
,fade
等等)效果,使app更加炫酷。 這裏須要注意的是Transition的用途有兩種。php
還須要解釋下關鍵的名詞。 Scene
: 一個佈局場景 Transition
: 兩個場景間的動態變化,便可以理解爲會產生動畫效果java
當一個Scene
到另外一個Scene
時,Transition
的職責爲以下:android
Scene
的狀態Animator
,並計算動畫效果,而後播放動畫。在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)
複製代碼
window.exitTransition =
Slide().apply {
duration = 200
slideEdge = Gravity.END
}
複製代碼
利用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)
複製代碼
A.exitTransition()
: 從A到B時A的退出動畫 B.enterTransition()
: 從A到B時B的進場動畫 B.returnTransition()
: 從B返回A時的退出動畫 A.reenterTransition()
: 從B返回A時的進場動畫框架
explore
: 將View移入場景中心或從中移出。slide
: 將視圖從場景的其中一個邊緣移入或移出。能夠利用slideEdge=Gravity.Start
方式設置移入移出邊緣。fade
: 經過更改視圖的不透明度,在場景中添加視圖或從中移除視圖。系統支持將任何擴展 Visibility 類的過渡做爲進入或退出過渡。ide
須要在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())
}
複製代碼
元素共享轉場是Meterial設計中我的比較喜歡的設計之一。 activity之間的轉場總有頓挫感,可是利用元素共享轉場可讓前一個畫面中的元素能夠在下一個畫面上流暢的顯示。
其實上面講到過設置方法,以下。
window.let {
// 設置分享元素的轉場
it.sharedElementEnterTransition
it.sharedElementExitTransition
it.sharedElementReenterTransition
it.sharedElementReturnTransition
}
複製代碼
要想讓元素共享,須要讓前一個畫面的元素的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" />
複製代碼
咱們須要爲轉場元素設置動畫。在activity的onCreate
的window
上進行設置。
override fun onCreate(savedInstanceState: Bundle?) {
// 爲轉場元素設置動畫
window.sharedElementEnterTransition = ChangeBounds()
window.sharedElementExitTransition = ChangeBounds()
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
複製代碼
須要注意的是先後兩個畫面都須要爲共享元素設置轉場動畫。固然動畫能夠是不同的,這個部分根據本身須要進行設置就行了。
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())
複製代碼
除了Activity之間的轉換還有一個佈局內的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相同。
建立Transition動畫。
val transition = TransitionInflater.from(this).inflateTransition(R.transition.slide_transition)
複製代碼
利用TransitionManager進行Scene的切換。
TransitionManager.go(scene2, transition)
複製代碼
// 建立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
}
}
複製代碼
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…