深入理解 Shared Element Transition (part 3a)
这篇文章会深度分析共享元素 transitions 和它在 Activity & Fragment Transitions API 中的作用。这篇文章是下面这个系列中的第三篇:
Part 3 会分成三个部分: part3a 介绍 共享元素 transitions 的底层操作,part3b 和 part3c 主要关注 API 的具体实现细节,例如推迟某些 共享元素 transition 的重要性和如何实现 SharedElementCallbacks。
我们首先会总结下在 part 1 中提到的关于 共享元素 transition 的知识点,然后说一说在 Android Lollipop 中是怎样使用它来构建合适的过渡动画。
共享元素 transition 决定了 共享元素 视图(也叫做主角视图)在 Activity/Fragment 场景过渡时的动画效果。共享元素 的动画 在被调用 Activity/Fragment 的 进入/返回 共享元素 transition (1) 中执行, 可以通过下面的Window/Fragment 方法设置:
Video 3.1 展示了在 Google Play Music 中是怎样使用共享元素 transition 的。这个 transition 包含两个元素:一个 ImageView和它的父视图 CardView。 Transition 期间,CardView 会扩展到全屏或收缩回原状, ImageView 能在这两个 Activity 里无缝的衔接。
在 part1 里只是简单的介绍了下这个话题,这篇文章将会对 共享元素 transition 做更深度的分析。例如 共享元素 Transition 在底层是如何实现的?都有哪些类型的 Transition 对象可以使用? Transition 期间 共享元素视图 是在哪里怎样绘制的?接下来的几章里 我们会逐个解答这些问题。
之前的文章已经介绍过 Transition 的两个主要任务分别是获取目标视图的 开始&结束 状态和创建这两个状态间视图的过渡动画(Animator)。共享元素 Transition 也一样: 在创建动画前需要捕获每一个 共享元素视图的起始和结束状态(就是共享元素在 调用/被调用 Activity/Fragment 里的位置,大小和外观)。有了这些信息 共享元素 Transition 就可以确定每一个 共享元素 视图应该执行的动画。
和 Content Transitions 的底层相似,框架通过在运行时明确的 更改每个 共享元素视图 的属性将这个状态信息提供给 共享元素 Transition 。 更准确地说 Activity A 启动 Activity B 时将会出现以下事件:(2)
Content transitions 是根据每个过渡视图的可见性变化来调节的,共享元素 transition 是根据每个共享元素视图的位置,大小和外观的变化来调节的。从 API 21 开始,框架提供了 几个自定义共享元素场景切换动画的 Transition 实现。
在上面的例子中,我们还可以发现 共享元素视图实例并没有在 Activities/Fragments 间 “共享”。事实上,进入/返回 共享元素 transitions期间,用户看到的绝大多数东西都是在 B 的 content view 中绘制的。框架并没有从 A 向 B 传递 共享元素视图实例, 而是采用了不同的方法实现相同的视觉效果。当 A 启动 B ,框架收集 A 中共享元素的所有相关信息,并传递给 B。接下来 B 使用这些信息初始化 共享元素视图的起始状态(它们在 A 中时对应的大小,位置和外观)。Transition 开始时,B 中除了共享元素视图外的所有东西都被初始化为对用户不可见。Tansition 的执行过程中,框架将 B 的 Activity 窗口逐渐显示,直到 B 中共享元素结束动画窗口变为不透明。
最后,如果想要完全理解共享元素 transition 的运作,我们必须先说说共享元素 overlay。 可能不是很明显,共享元素默认是在整个窗口视图层的顶层 ViewOverlay 上绘制。简单介绍下 , ViewOverlay 这个类是在 API 18 中为了方便在视图层顶层 绘制引入的。添加到视图 ViewOverlay 之中的Drawable 和 view (甚至是一个 ViewGroup 的子类) , 将会被绘制在视图的最上层。这就解释了框架为什么 默认选择在窗口视图层的 ViewOverlay 中绘制共享元素。 共享元素视图应该是贯穿整个 transition 的焦点; 如果 transitioning views 意外的绘制在共享元素之上就会 破坏这个效果(5)。
虽然共享元素默认绘制在共享元素的 ViewOverlay 之中,但是 框架也提供了关闭 overlay 的方法,只要调用 Window#setSharedElementsUseOverlay(false) 就可以了。如果你关闭了 overlay ,要留意这样做可能会引起的副作用。例如,Video 3.2 执行了一个简单的共享元素 transition 两次, 一次开启和一次关闭 共享元素 overlay 。第一次达到了预期想要的结果, 第二次关闭 overlay 后运行的效果不理想。Transition view 从底部向上移入 调用 Activity 的 content view 时挡住了部分 共享元素 ImageView 。虽然 可以改变在 View 上绘制视图的顺序或者通过在共享元素 parent 里调用 setClipChildren(false) 这些旁门左道来修复问题,但是与可能带来的维护问题 相比真是得不偿失。总之,除非你感觉必须要关掉共享元素 overlay 才能达到你想要的效果, 其他情况尽量不要关闭它,这样会保持代码简洁,并且共享元素 transition 效果更引人注目。
综上所诉,这篇文章讲了三个重点:
希望这篇文章对你有所帮助 ~
1 Note that the Activity Transition API gives you the ability to also specify exit and reenter shared element transitions using the setSharedElementExitTransition() and setSharedElementReenterTransition() methods, although doing so is usually not necessary. For an example illustrating one possible use case, check out this blog post. For an explanation why exit and reenter shared element transitions are not available for Fragment Transitions, see George Mount's answer and comments in this StackOverflow post. ↩
2 A similar sequence of events occurs during the exit/return/reenter transitions for both Activities and Fragments. ↩
3 One other subtle feature of ChangeTransform is that it can detect and handle changes made to a shared element view's parent during a transition. This comes in handy when, for example, the shared element's parent has an opaque background and is by default selected to be a transitioning view during the scene change. In this case, the ChangeTransform will detect that the shared element's `parent is being actively modified by the content transition, pull out the shared element from its parent, and animate the shared element separately. See George Mount's StackOverflow answer for more information. ↩
4 Note that this section only pertains to Activity Transitions. Unlike Activity Transitions, shared elements are not drawn in a ViewOverlay by default during Fragment Transitions. That said, you can achieve a similar effect by applying a ChangeTransform transition, which will have the shared element drawn on top of the hierarchy in a ViewOverlay if it detects that its parent has changed. See this StackOverflow post for more information. ↩
5 Note that one negative side-effect of having shared elements drawn on top of the entire view hierarchy is that this means it will become possible for shared elements to draw on top of the System UI (such as the status bar, navigation bar, and action bar). For more information on how you can prevent this from happening, see this Google+ post. ↩
Activity Transition API 也提供了 setSharedElementExitTransition() 和 setSharedElementReenterTransition() 这两个方法来设置 退出/重入 共享元素过渡,虽然通常来说是不必要的。 这篇文章介绍了一个可能会遇到的用例。在这个 stackoverflow 提问中 George Mount 的回答解释了为什么 退出/重入 共享元素 transition 在 Fragment Transitions 中不可用。 ↩
Activities 和 Fragments 的 退出/返回/重入 transition 过程中出现事件序列相似 ↩
ChangeTransform 还有一个超赞的特性,它可以检测并处理共享元素父视图过渡期间 的改变。当共享元素父视图有一个不透明背景,在场景变换过程中默认被选为 transitioning view 时,ChangeTransform 就有了用武之地。如果它检测出 共享元素父视图已被 content transition 更改,就会将共享元素提取出来,单独执行 共享元素的动画。StackOverflow answer 这里有 George Mount 的详细说明。 ↩
注意,这部分只与 Activity Transition 有关。和Activity Transition 不同,Fragment Transition 期间共享元素默认不在 ViewOverlay 中绘制。尽管如此,你仍可以使用 ChangeTransform transition 来达到相似的效果,如果它检测到父视图改变了,就会把共享元素绘制在 ViewOverlay 的顶层。StackOverflow 这里有更多信息。 ↩
注意,将共享元素绘制在整个图层最顶层也有一些负面效果。有可能 会将共享元素绘制在 System UI 之上(比如 status bar, navigation bar还有 action bar)。 解决方法看这里 Google+ post。 ↩
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。