LisetView是Android框架中最流程的控件之一。它有很多功能,然而它是很复杂的,修改难度很大。随着用户体验的发展和手机变的越来越快,它的局限性使它的特色黯然失色。
在Lollipop中,Android团队决定发布一个新的控件,使得该控件的不同的行为更容易实现。以下的改变会很容易控制:
- items如何被展现
- 动画效果
- item修饰
- 回收策略
- ...
极大的灵活性也伴随着一个巨大架构的复杂性。同样也有更多需要学习。
在这篇文章中,我要深入RecyclerView的内部,特别在动画如何实现上。
在Honeycomb上,Android框架引进了LayoutTransition,ViewGroup内部动画的一个很简单的方法。它工作原理是布局改变前和改变后分别生成两个ViewGroup快照,然后在这两个状态间创建一个动画效果。这个过程和Adapter中RecyclerView的动画非常相似。
LayoutTransition例子:
不幸的,List有一个主要的区别使得LayoutTransitions不适合它们的动画,list中的item和ViewGroup中的不一样。处理“items”动画机制和动态显示“views”的内容是很重要的差别。
在一个标准的ViewGroup中,如果一个View是新被添加到视图层的,它可以被认为是一个新加入的View,因此可以设置相应的动态效果(例如,淡入)。对于集合,这是不同的。例如,在Adapter中一个item的View变为可见仅是因为之前有一个item被移除。在这个情况下,已经在列表中的运行淡入的动画效果的item会被误认为是一个新的view,因为它刚被看见。RecyclerView知道item是否是新的,但是不知道如果item不是新的它在哪。同样对于消失中的View也是一样,如果没有被Adapter移除,RecyclerView不知道View去哪里了。
对于列表LayoutTransition是无效的:
为了修复这个问题,RecuclerView会问LayoutManager新View的之前的位置。虽然这会工作,它将会需要LayoutManager结尾的一些统计,对于更复杂的LauoutManager可能不需要繁琐的计算。
RecyclerView控制item显示和消失动画的方式(就是说,view的显示和消失的动画是指它仍然在list中)是依赖LayoutManager处理layout逻辑的预测性。一方面,RecyclerView需要知道变化之前view被展示在哪一层。另一方面,RecyclerView想要知道变化之后view被展示在哪一层,如果LayoutManager展示items出现了问题,则item不可见。
为了LayoutManager更容易的提供这个信息,RecyclerView使用两个层来配合动画效果。具体如下描述:
- 在第一个层中的变化(preLayout),RecyclerView询问LayoutManager当前层之前状态的更多信息。比如上面的例子,就好像请求“‘C’被移除了”。LayoutManager正常执行‘C’被移除的操作,用新的View填补‘C’的空档。
出色的是RecyclerView仍然知道‘C’还在Adapter中。比如,当LayoutManager想要知道位置为‘2’的View是什么时,RecyclerView会返回‘C’(
getViewForPosition(2) == View('C')
)。如果问位置为‘4’的View是什么时,会返回来‘E’(虽然‘D’是Adapter第四个元素)。返回View的有一个isItemRemoved方法,LayoutManager可以通过检查这个方法来判断是否是消失的View。
- 在第二个层中的变化(postLayout),RecycleView请求LayoutManager布置它自己的item。这时,‘C’已经不在Adapter中了。
getViewForPosition(2)
会返回‘D’,getViewForPosition(4)
会返回‘F’。记住,‘C’已经被Adapter移除了。但是因为RecyclerView保留了它的引用,它表现的好像‘C’仍然存在。换句话说,RecyclerView做了LayoutManager统计的工作。
每次调用LayoutManager中的onLayoutChildren
的时候,它会临时拆开所有的View并从头开始布局。没有改变的View会被从废弃的缓存中返回,因此它们还是有效的。这使得重新布局相当高效。
LinearLayoutManager之前的布局结果:(红色框范围内对用户是可见的)
LinearLayoutManager之后的布局结果
这两个布局变化后,RecyclerView知道View来自哪里所以能运行正确的动画效果。
你可能会问:‘C’没有被LayoutManager展示,那为什么还会可见?
要清楚,在pre-layout中被LayoutManager展示的‘C’是因为它看起来是在Adapter中。事实是在post-layout中不被LayoutManager展示的‘C’已经不再Adapter中存在了。也就说是‘C’不再是LayoutManager的孩子,但对于RecyclerView不是这样的。当LayoutManager移除了View,如果要实现动画效果,RecyclerView会使他做为孩子一直存在(所以动画会正确的显示)。更多的细节会在Part 2。
消失的Items
通过了两个布局过程的变化,RecyclerView可以正确的执行新View的动画效果。但是,消失的View存在另一个问题。考虑一下新添加的元素在list什么位置,会把一些元素移出可见区域。它看起来像LayoutTransitions:
当‘X’被添加在‘A’后,它把‘F’移出了可见区域。因为LayoutManager没有展示‘F’,LayoutTransition认为它已经被一个淡出的动画效果移出UI。实际上,‘F’仍然在Adapter中只是被移出了可见区域。
为了解决这个问题,RecyclerView给LayoutManager提供了一个额外的API。在postLayout变化的末尾,LayoutManager会调用getScrapList获得列表中的View(没有被LayoutManager展示,但仍然在Adapter中)。然后,它展示了这些view,好像RecyclerView的规模大到足以展示它们。
LinearLayoutManager之后的布局结果:(红色框范围内对用户是可见的)
一个重要的细节是,因为这些View在动画效果结束后就不是必需的了,LayoutManager会调用addDisappearingView来代替addView
。这就告诉了RecyclerView这个View的动画效果完成后就被移除。RecyclerView会把这个View加入到隐藏View的列表中,所以postLayout
方法返回时在LayoutManager子View的列表中是不可见的。这样,LayoutManager就会忽视它。
首先,至少对于LinearLayoutManager来说,你可能认为它会计算View来自哪里和要去哪里(如果消失),这样就不需要两次布局计算。令人遗憾的是,许多类型的Adapter在同一个布局中发生变化时会有很多意外情况。除此之外,对于更复杂的LayoutManager,它不总是简单的计算一个item放在什么地方(例如StaggeredGridLayout)。这个方法会删除来自LayoutManager所有的负担,它可以很容易的支持一些适当的动画效果。
到目前为止,我的主要想法是RecyclerView如何预测动画的运行。实际上有很多简单的实现(对于LayoutManager来说)。你可以在Part 2 - 幕后中了解更多。
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为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 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。