这篇文章是RecyclerView系列文章的结尾篇。前三部分的链接在这里 :
当我在写这个系列的最后一篇文章,也就是关于predictIve animation的讨论时,我突然想到几个很有意思的点,并且很有讨论价值。这个系列文章以调查RecyclerView是否能够以简单的方式满足竖向、横向滚动的布局需求以及开发者要定制一个LayoutManager的难度有多大开始。这篇文章中我选择了一个基本的网格布局作为自定义layoutManager的示例。
下面这幅图展示了运用这个自定义LayoutManager到RecyclerView的滚动效果。
无论你打算如何组织Adapter的位置(从左到右,上到下等等),内容视图的视角都是显示部分不连贯数据集的区域。更确切地说,在第一个和最后一个可视位置之间的Adapter区域的数据项也会在可视区域view的外面。
这是一个很重要的点,因为它与在单轴上滚动的布局大相径庭(从而导致与当前框架下提供的默认布局背道而驰)。这些标准小工具显示,数据集是在一个连接块范围内--从第一个到最后一个可视位置之间不间断。
RecyclerView LayoutManager API会假定有一个可见的数据集合,RecyclerView LayoutManager只会显示数据集合中某个范围内可见的数据项,然后产生一个像上述所展示的网格布局一样的布局效果,这稍微有那么点挑战。在predictive animation里没有什么比这部分更加明显了。为了便于扩展,我感觉在这里指出这些毛病是非常必要的。
当你考虑到一个Adapter移除一个数据项时LinearLayoutManager或者GridLayoutManager会做何反应时,这两个LayoutManager实际上都处理得非常好。如果被移除的数据项是可见的,一个可用的区域将会空置出来,此时就需要一个周边的View进行填充。这意味着周边显示的View必须被布局到这个位置以填补缺口。然而,并没有一个示例表明当一个移除操作执行时会发送一个隐藏视图的操作,唯一被隐藏的视图是那些被显式移除的。如果被移除的View在可见区域之外,那么对于可见区域的布局不会产生影响。在这个情况之下,你不会看到任何动画,它可能做出的修改是数据项被移到其他位置。
从上述的情况看,这与文章开头我们提到的一样,LayoutManager显示的是一个不连续的数据项。然而,这一可视区域的不连续本质使得数据项在屏幕外从可视区域内移除!换种说法,它们的位置处于第一个和最后一个位置之间,但是目前数据项view并不在布局中。这导致的结果就是,屏幕外发生的数据项移除可以并且会影响我们在布局动画处理时view的生成和消失。
在有机会对view的生成进行布局时,预布局是RecyclerView动画的关键阶段。RecyclerView通过其初始位置值将view返回,据此我们可以将内容布局在其初始状态。但是,当view移除与可视区域不相交时。RecyclerView就会通过其最终位置值将view返回。这样一来,在没有附加记账的情况下处理view的生成就变得困难得多。不过话说回来,难是难,也还是可以做到。
在上一篇文章中我们看到的FixedGridLayoutManager,我们不仅要解析可视view,还要听从onItemsRemoved()的回调来找到移除点,并妥当处理所有生成的view案例。RecyclerView确保我们在需要时,该回调会在预布局之前出现(屏幕外案例),但相反情况下会在预布局之后出现。RecyclerView这么做是为了避免这些事件与你的布局产生冲突--其时间点对我们来说只是一个美丽的意外。
我们还需要追踪的一个事实就是,可视移除会以一种我们意料之中的方式偏移view的位置,而屏幕外移除则不会。这也是为什么移除会被冠以不同类型的原因。上一篇文章忽略的一点表明,在屏幕外进行移除时,我们会对view生成逻辑提供一个手动偏移。。。所以当移除可视时,位置之间会相互匹配。
private void fillGrid(int direction, int emptyLeft, int emptyTop, RecyclerView.Recycler recycler,
boolean preLayout, SparseIntArray removedPositions) {
…
for (int i = 0; i < getVisibleChildCount(); i++) {
int nextPosition = positionOfIndex(i);
/*
* When a removal happens out of bounds, the pre-layout positions of items
* after the removal are shifted to their final positions ahead of schedule.
* We have to track off-screen removals and shift those positions back
* so we can properly lay out all current (and appearing) views in their
* initial locations.
*/
int offsetPositionDelta = 0;
if (preLayout) {
int offsetPosition = nextPosition;
for (int offset = 0; offset < removedPositions.size(); offset++) {
//Look for off-screen removals that are less-than this
if (removedPositions.valueAt(offset) == REMOVE_INVISIBLE
&& removedPositions.keyAt(offset) < nextPosition) {
//Offset position to match
offsetPosition--;
}
}
offsetPositionDelta = nextPosition - offsetPosition;
nextPosition = offsetPosition;
}
if (nextPosition < 0 || nextPosition >= getItemCount()) {
//Item space beyond the data set, don't attempt to add a view
continue;
}
…
if (i % mVisibleColumnCount == (mVisibleColumnCount - 1)) {
leftOffset = startLeftOffset;
topOffset += mDecoratedChildHeight;
//During pre-layout, on each column end, apply any additional appearing views
if (preLayout) {
layoutAppearingViews(recycler, view, nextPosition, removedPositions.size(), offsetPositionDelta);
}
} else {
leftOffset += mDecoratedChildWidth;
}
}
…
}
之后offsetPositionDelta值会作为我们在预布局中使用到的行/列位置的全局偏移被传递到layoutAppearingViews()。如果不是出于附加记账要求,这一偏移完全可以不必存在。
添加了新的数据项之后,反面为真。如果在添加时数据项为可视,那么标准布局管理器会在屏幕外推开不可视的view以便腾出空间。之前没有出现过关于这种行为会同时触发一个或多个同级view滑向可视子类位置的案例。移除也是同样的道理,在可视区域外添加数据项并不会影响可视view,所以通常来说动画也不会起作用。
对于FixedGridLayoutManager或其他任何非连贯区域的布局,在可视区域内还是可视区域外进行添加并没有多大差别。两种情况中我们都需要管理可能出现的view生成和消失。而我们在移除中使用的方案在这里则不可行,因为onItemsAdded()总是在预布局之后被调用。。。这一次我们就没那么幸运地再一次能够碰到美丽的意外了。
缺少了那次回调,关于添加数据项,我们实际上在预布局时就没有多少可做的了。这样一来就变成了布局额外的view以备不时之需,而不布局一定量的额外view就会损害性能这两种情况之间的妥协。FixedGridLayoutManager在添加数据项时不支持预测view生成。
RecyclerView APIs是一个新生事物,现有案例中还有非常多的地方需要改进的。同时,它也非常复杂,想要做对并不容易。表面上看起来RecyclerView要求大家付出的努力,背后可能大家要花10倍的精力才能实现。而且这些类型越到后面可能月蛋疼。希望正在尝试这种做法的各位同仁可以视本文为一个预警,不要盲目浪费时间,但同时我们也期待这这个框架的日渐成熟。
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为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 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。