ViewCompat.offsetTopAndBottom翻车现场

简介: ViewCompat.offsetTopAndBottom翻车现场

引言


去年我开源了一个RecyclerView吸顶库,关于它的介绍请大家移步“我开源了一个RecyclerView吸顶库”一文。别看这个库大量使用了泛型,对象池、链表等技术,但是吸顶的功能真正倚仗的只有ViewCompat.offsetTopAndBottom(View view,int offset)这一个方法。它能够帮我们实现将View上下平移。它的姐妹方法offsetLeftAndRight(View view, int offset)可以实现将View左右平移,一般情况使用它们实现平移效果非常简单,适合各种阶段的Android开发者使用,堪称老少咸宜,效果那是童叟无欺。但是在我的吸顶库中,偏偏在某些特殊的情况下,调用了offsetTopAndBottom方法,View并没有发生预期的偏移效果,而是呆呆的停留在原地,我靠,翻车了!本来想从源码的角度正面寻找这个问题的答案,奈何offsetTopAndBottom虽然使用简单,但是源码一点都不简单。正面攻破不了,能否有办法从侧面解决呢?下面我将还原一下翻车现场,以及几个侧面解决的方案。


还原翻车现场


640.png


这是来自我吸顶库中的一段代码,这里有翻车现场,如果你看不懂,也没关系,后面我会用一个非常简单的例子来还原这个现场。这段代码的功能是处理向下滑动RecyclerView时,切换吸顶功能。我们注意到addStickyView(newStickyView)方法将newStickyView视图添加到mStickyHeaderLayout布局中,紧接着调用ViewCompat.offsetTopAndBottom(mStickyHeaderLayout, mStickyHeaderLayoutTop - mStickyHeaderLayout.getMeasuredHeight() - mStickyHeaderLayout.getTop()),想要实现的效果是将mStickyHeaderLayout隐藏掉。问题就在于mStickyHeaderLayout此刻并没有隐藏掉,而是岿然不动的停留在原来的位置。所以在手机上的效果是,向下滑动RecyclerView时,当发生吸顶切换时,会有一个让人非常不适的闪动效果,当时出现这个问题时,我的内心肯定是在骂人的了,极度不理解,为啥调用了offset方法,却没有发生偏移呢,如果不解决这个问题,那么之前在该库上花的心血几乎要功亏一篑了。没办法,只能擦干眼泪找原因,找解决方案了。首先一个非常值得怀疑的点是,是不是因为先调用了addView 再调用offset方法,导致失效了呢?写个DEMO来验证一下。


DEMO还原现场


上面吸顶库的代码比较复杂,那我来写个简单的DEMO验证一下上面的疑问。代码我已上传至github,https://github.com/lizijin/zijiexiaozhan

640.png

640.png


上述代码,模拟了在吸顶库中遇到的问题,在addView后立马调用offset,点击“ADD AND OFFSET”按钮效果如下,仅仅是把newButton添加到屏幕中,并没有向下平移100像素。


image.png


解决问题


已经还原了问题现场,下一步就是定位问题和解决问题了。熟悉View.post(Runnable action)技巧的同学可能会第一时间想到用View.post来解决这个问题。我的第一反应也是这么想的。于是信手拈来,加个post。


1.1 使用post方式解决

640.png


1.2 效果


能够完美的解决不偏移的问题,但是引入了新问题,真机上可以明显看到闪烁。gif图由于分辨率的问题,看不出闪烁


image.png


2.1 使用post方式+setAlpha解决


既然有闪烁,于是我思索了好久,如何能解决这种肉眼可见的闪烁bug呢?突然有一天,灵光一现,能否在偏移前后,设置它的透明度呢?post之前setAlpha(0),post时setAlpha(1),于是尝试一番,果不其然能够解决闪烁的问题。

640.png


2.2 效果


能够完美的解决不偏移和闪烁的问题。但是在吸顶库中又引入了新的问题,即快速向下滑动的过程中,吸顶后面的视图会不合时宜的出现在视觉中,造成另外一种情况的闪烁


image.png


3.1 使用post方式+OnPreDrawListener解决


使用post+alpha在快速滑动时会出现,吸顶短暂消失,漏出吸顶背后的View,这种闪烁的效果如果交互给用户,肯定会被喷的。于是又陷入了苦苦思索的状态,然后从View的绘制流程的各个节点尝试了一遍,了无收获,直到有一天尝试了下ViewTreeObserver.addOnPreDrawListener方法,意外的发现可以解决以上的问题,开心~ 解决方案640.png


3.2 效果


完美解决了以上的所有问题


image.png


相关文章
|
26天前
|
缓存 监控 前端开发
前端代码评审问题总结年度代码翻车现场 |
团队已持续进行了一年多的线下周代码评审,作为主要评审人,我认识到虽然初衷是提供代码改进建议,但实际上大部分问题集中在基础代码质量上,而非设计或业务逻辑。因此,团队需保持耐心,逐步解决基础问题。本文总结了一年来常见的代码评审问题,如魔法值、eslint禁用、幽灵依赖等,并提出具体改进建议。此外,还强调了良好的代码习惯、命名规范及异常处理的重要性。通过持续代码评审,希望团队能在卓越工程的道路上不断进步。以下是常见问题的具体分析: ### 二、翻车现场(CR中的常见问题) #### 2.1 代码规范类 ##### 2.1.1 使用魔法值 - **危害**:代码不易读、不复用、易出错 - **建
21 3
|
5月前
|
测试技术 程序员 项目管理
甲方怒喷半小时:一次项目上线失败的深刻教训
小米分享了一次项目上线失败的经历,起因是运营提出一个看似简单的白名单功能。问题包括:没有需求原型导致理解偏差,新成员对项目不熟悉,测试流程不全面,以及人员变动大。解决方案涉及需求确认会、原型图设计、交接制度、团队培训和全流程测试等。这次失败提供了关于需求分析、项目管理及团队协作的教训。
52 2
|
5月前
|
缓存 前端开发 JavaScript
年度代码翻车现场 |前端代码评审问题总结
代码评审于技术团队的工程师文化建设非常有意义,它是形成团队统一代码风格最有效的方式,作者把自己团队在一年的CR中常见的那些小问题做了一些梳理,希望能对大家起到一点小帮助。
219678 7
|
5月前
|
新能源 图形学
两千字——零基础开始打化工设计大赛——附搜集到的小白资料站、一次项目复盘
两千字——零基础开始打化工设计大赛——附搜集到的小白资料站、一次项目复盘
73 0
|
5月前
|
存储 人工智能
近期复盘 | 想多了都是问题,想开了都是答案
近期复盘 | 想多了都是问题,想开了都是答案
如何开发自主体育直播足球竞猜系统?说难不难,做好这三步就行了
随着网络技术的发展,体育直播已经成为人们观看体育比赛的主要方式之一。对于想要开发自主体育直播系统的企业或个人来说,以下三步是必须要做的。
|
C语言 C++
提前做好准备吧,过个浪漫的圣诞。
圣诞节没什么礼物,来个爱心和彩色圣诞树代码(彩色圣诞树可以写喜欢的人名字哦)
101 0
提前做好准备吧,过个浪漫的圣诞。
|
传感器
和12岁小同志搞创客开发:检测按键状态的两件法宝
和12岁小同志搞创客开发:检测按键状态的两件法宝
和12岁小同志搞创客开发:检测按键状态的两件法宝
|
算法 Java 数据库
面试现场:遇到不会回答的问题,如何力挽狂澜 ?
今天给大家讲讲面试过程当中最长遇到的窘境,也是最能体现一个候选人临场应变能力的地方,那就是当我们在面试的过程当中,遇
|
存储 监控 安全
杂货机器人翻车实录:会被路人“吓”到,还会跟错主人!3千美元怕是买了个寂寞?
杂货机器人翻车实录:会被路人“吓”到,还会跟错主人!3千美元怕是买了个寂寞?
196 0
下一篇
无影云桌面