在 Android 5.0 之后,我们可以使用 Material Design 为我们带来的转场动画。
不说别的,先看几个案例:
官方Demo
掘金APP
我的APP
从上到下依次是官方Demo、掘金App和我的开源项目Hoo,与最初的转场的不同点如下:
-
如果说 overridePendingTransition 对应着 View 动画,那么 Material 转场对应着的是属性动画,所以可以自定义界面过渡动画。
-
除了进入、退出场景,Material 转场为我们增加一种新的场景,共享元素,上述三图的动画过渡都用到了共享元素。
-
不仅仅能用在Activity,还可以用在Fragment和View之间。
三张图中都使用了ImageView作为共享元素(Hoo中使用更加复杂的PhotoView),共享元素的动画看着十分有趣,看着就像图片从A界面中跳到了B界面上。
为什么我可以判断掘金也是使用的 Material 转场?因为 Material 共享元素动画开始的时候默认会将 StartView 的 Alpha 设置为0,仔细看掘金大图打开的一瞬间,后面的图已经没了~,并且一开始过渡还有一点小瑕疵。
1. 进入和退出动画
进入和退出动画不包括共享元素的动画,只支持三种动画类型:
| 动画 | 解释 |
| :-: | :-- |
| Explode
(爆炸式) | 将视图移入场景中心或从中移出 |
| Slide
(滑动式) | 将视图从场景的其中一个边缘移入或移出 |
| Fade
(淡入淡出式) | 通过更改视图的不透明度,在场景中添加视图或从中移除视图 |
细心的同学可能发现,Material Design没有支持 Scale
和 Rotation
这两种类型的动画,可能这两种类型的过渡动画使用场景实在太少,如果实在想用,可以自定义实现。
步骤一 创建Material Bundle
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
步骤二 设置动画
override fun onCreate(savedInstanceState: Bundle?) {
// 开启Material动画
window.requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)
super.onCreate(savedInstanceState)
//setContentView(R.layout.detail_activity)
// 设置进入的动画
window.enterTransition = Slide()
// 设置退出动画
window.exitTransition = Slide()
}
除了这种方式,还可以通过设置主题的方式设置进入和退出动画,同样也适用于共享动画。
2. 共享元素动画
启用共享元素动画的步骤跟之前的步骤稍有不同。
步骤一 设置Activity A
先给 View
设置 transitionName
:
ivShoe.transitionName = transitionName
接着,它需要提供共享的 View
和 TransitionName
。
其实,就是想让你告诉系统,什么样的 View
需要做动画,那如果有多个 View
呢?所以,你还得给View
绑定一个 TransitionName
,防止动画做混了。
代码:
val options = ActivityOptions.makeSceneTransitionAnimation(this, binding.ivShoe, transitionName)
ImageGalleryActivity.start(this, it, options.toBundle(), transitionName)
如果有多个共享元素,可以将关系存进 Pair
,然后把 Pair
放进去,不懂的可以看一下 Api。
步骤二 为Activity B设置共享元素动画
默认支持的共享元素的动画也是有限的,支持的种类有:
| 动画 | 说明 |
| :-: | :-- |
| changeBounds
| 为目标视图布局边界的变化添加动画效果 |
| changeClipBounds
| 为目标视图裁剪边界的变化添加动画效果 |
| changeTransform
| 为目标视图缩放和旋转方面的变化添加动画效果 |
| changeImageTransform
| 为目标图片尺寸和缩放方面的变化添加动画效果 |
通过 Window
设置 sharedElementEnterTransition
和 sharedElementExitTransition
:
override fun onCreate(savedInstanceState: Bundle?) {
// 开启Material动画
window.requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)
val transitionSet = TransitionSet()
transitionSet.addTransition(ChangeBounds())
transitionSet.addTransition(ChangeClipBounds())
transitionSet.addTransition(ChangeImageTransform())
window.sharedElementEnterTransition = transitionSet
window.sharedElementExitTransition = transitionSet
super.onCreate(savedInstanceState)
// 我这里的transitionName是通过Intent传进去的
val transitionName = intent.getStringExtra(CUS_TRANSITION_NAME)
// 给ImageView设置transitionName
binding.ivShoe.transitionName = transitionName
}
这样写完大部分场景都是可以用的,但是,如果你是通过 Glide 加载或者其他图片库加载的网络图片,恭喜你,大概率会遇到这样的问题:
为什么会出现这样的情况?因为加载网络图片是需要时间的,我们可以等 B 页面的图片加载好了,再去开启动画,Material 装厂就支持这样的操作。
在 onCreate 中调用 postponeEnterTransition()
方法表明我们的动画需要延迟执行,等我们需要的时机,再调用 Activity
中的 startPostponedEnterTransition()
方法来开始执行动画,所以,即便是在 A 界面中,跳转到 B 界面中的 Fragment
,动画也是一样可以执行的。
到这儿,界面就可以正常跳转了,图片就不放了。
共享元素动画原理其实也很简单,如果是 A 跳到 B,会先把 A 和 B 的共享元素的状态分别记录下来,之后跳到 B,根据先前记录的状态执行属性动画,虽然是叫共享元素,它们可是不同的 View
。
不仅仅 Activity 可以支持 Material 转场动画,Fragment 和 View 也都是可以的(之前我一直以为是不可以的~),感兴趣的同学可以自行研究。
新出的 Motion 动画是什么呢?
1. Android Motion 简介
其实它就是新支持的四种动画类型,分别是:
1.1 Container transform
Container transform 也是基于共享元素的动画,跟之前共享元素动画最大的不同点在于它的 Start View可以是一个 ViewGroup
,也可以是一个 View
,如图一中所看到的那样,它的 Start View 是一个 CardView
。
1.2 Shared axis
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YmE0W7km-1624345484780)(https://upload-images.jianshu.io/upload_images/25211949-732ee3c87e85306e.image?imageMogr2/auto-orient/strip)]
Shared axis 看上去像平移动画,官方展示的三个例子分别是,横向平移、纵向平移和Z轴平移。
1.3 Fade Through
Fade Through 本质上是一个透明度+缩放动画,官方的建议是用在两个关联性不强的界面的跳转中。
1.4 Fade
乍一看,Fade 动画和上面的 Fade Through 是一致的,就动画本质而言,它们的确是一样的透明度+缩放动画,但是官方建议,如果发生在同一个界面,比如弹出Dialog、Menu等这类的弹框可以考虑这种动画。
Google 提供了两种库供大家使用。
一种是 AndroidX 包,特点是:
-
兼容到 API 14
-
仅支持 Fragment 和 View 之间的过渡
-
行为一致性
另外一种是 Platform 包,特点是:
-
兼容到 API 21
-
支持 Fragment、View、Activity 和 Window
-
在不同的 API 上,可能会有点差异
现在的 App,最低版本应该都在 21 了,而且支持 Activity,所以建议还是选择 Platform。
2. Material Motion 初体验
我们以 Container transform 为例,来个 Activity 之间的 Android Motion 动画的初体验:
步骤一 引入依赖
implementation ‘com.google.android.material:material:1.4.0-alpha01’
步骤二 设置Activity A
这里的 Activity A 对应着 MainActivity
,在 MainActivity
中启用转场动画:
class MainActivity : AppCompatActivity() {
//…
override fun onCreate(savedInstanceState: Bundle?) {
window.requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)
setExitSharedElementCallback(MaterialContainerTransformSharedElementCallback())
window.sharedElementsUseOverlay = false
super.onCreate(savedInstanceState)
//…
}
}
步骤三 设置跳转事件
跟创建共享元素的步骤一样,先设置 TransitionName:
private fun onCreateListener(id: Long, url: String): View.OnClickListener {
return View.OnClickListener {
val transitionName = “ i d − {id}- id−{url}”
it.transitionName = transitionName
DetailActivity.start(context, id, it as ConstraintLayout, transitionName)
}
}
这里偷了懒,将 TransitionName 的设置放在了点击事件中,接着创建 Bundle:
const val CUS_TRANSITION_NAME: String = “transition_name”
class DetailActivity : AppCompatActivity() {
companion object {
fun start(context: Context, id: Long, viewGroup: ConstraintLayout, transitionName: String){
val intent = Intent(context, DetailActivity::class.java)
intent.putExtra(BaseConstant.DETAIL_SHOE_ID, id)
尾声
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。
最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。
当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。
进阶学习视频
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
了,理论看多了总要实践的。
进阶学习视频
[外链图片转存中…(img-nL6eRbnJ-1714686469071)]
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
[外链图片转存中…(img-NGWVRCyI-1714686469071)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!