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…