工作记录:RecyclerView获取子View、Item错乱以及禁用RecyclerView滑动的问题

前言

在最近的项目中,有这样一个需求:在RecyclerView通过ID查询到指定Item,然后滚动视图到指定Item,并对视进行呼吸灯闪烁显示。一种快速查询定位的需求。
首选我想尝试使用RecyclerView中Item动画去实现,无果。于是就通过使用获取指定Item的View然后对View施加动画实现这种效果。
我相信使用RecyclerView动画应该能更好的实现这种效果,但我并未涉足过这块,项目中也没有充足的时间去了解,若有更好的实现方式请大家留言评论,让我学习一下。
接下来结合我的实现方式记录一下期间遇到坑。

一 RecyclerView getChildAt()异常

异常分析

遇到的第一个麻烦就是recyclerview.getChildAt(pos)获取View之后的操作报空指针异常(java.lang.NullPointException),因为通过getChildAt(pos)方法返回null.这个问题比较好解决,是因为粗心造成的——RecyclerView并不会为每一个Item创建一个View,RecyclerView的缓存机制只会维护一部分View,通过回收离屏Item的View给入屏Item复用的方式实现展示效果(详情请阅读RecyclerView与ListView 对比浅析:缓存机制)。所以如果所要获取的pos不在当前屏幕内显示,它是没有View实体存在的,必然返回空。

解决办法

解决办法很简单:<u>首先让recyclerview滑动,使得要获取的Item出现在屏幕内,让后再去获取</u>
此处有坑,不能直接用指定Item的pos去获取View,因为<u>这个pos标注的是Item在RecyclerView中排列的位置,而不是Item在RecyclerView所呈现视图中的位置</u>

image

如图:Item的pos对应图中红色的数字,而要使用recyclerview.getChildAt(pos)获取RecyclerView的子View,应该使用图中绿色的角标。那么问题来了,怎么获取pos对应的绿色角标值呢?
结合上文中我们的前提条件<u>让recyclerview滑动,使得要获取的Item出现在屏幕内。</u>在我们需要的View显示在屏幕的前提下,我们可以首先获取屏幕内显示的第一个Item在整个RecyclerView中排列的位置,通过计算目标Item和屏幕内第一个Item的位置角标差值,就可以知道目标Item处在屏幕中的第几个。代码实现如下:

LinearLayoutManager manager = (LinearLayoutManager) recyclerview.getLayoutManager();
int first = manager.findFirstVisibleItemPosition();//获取第一个显示的Item的pos
int acutalPos = (position - first) >= 0 ? position - first : 0;//计算差值确定位置
View childAt = recyclerview.getChildAt(acutalPos);//获取目标Item对用的View

二 改变Item颜色导致其它Item颜色错乱

通过问题一种的方案,我成功的拿到了目标Item进行修改背景的操作,一切看起来都是那么的正常。但是当我在执行背景操作,也就是动画闪烁的时候,细心的我滑动了一下RecyclerView。哇靠,什么情况,无数的Item的背景颜色被改变了。刚开始我还以为是pos错乱,或者滑动监听出现了问题,导致其他Item也执行了闪烁动画。但细心的我发现,这些View的背景颜色并不是被执行动画了,而是被”永久“的改变了颜色。而且只在执行动画时进行滑动才会出现——一定又是缓存机制搞得鬼!!!
没错,就是RecyclerView在复用View时带来的颜色改变:
当我们对目标View进行动画时,它的背景颜色被动态的改变。加入在某一时刻,它的背景被改为红色。而这个时候我们进行滑动,目标View离开屏幕。这个View在背景为红色的情况下被回收。紧接着新入屏的Item会复用这个View,从此一生无法摆脱这个喜庆的背景了!!!
解决方案很简单:<u>在执行动画的时候禁止滑动,动画执行结束之后再解锁。</u>这就带来了第三个问题。

三 禁止RecyclerView滚动

怎么禁止RecyclerView滚动呢?
第一个想到:setEnabled()幸运的是,这是无效的。
查看RecyclerView的方法:setNestedScrollingEnabled没用,这是解决嵌套滑动的。
想着可以通过重写RecyclerView的OnTouch事件解决。但是工程量太大了,事件不允许啊!还要加一些回调,麻烦。慢慢的看着RecyclerView的源码,当addOnItemTouchListener()跃入我的眼帘。灵机一闪,如果让RecyclerView的子View拦截事件呢?
当执行动画的时候让子View拦截所有事件,动画结束的时候再解锁拦截!代码如下:

//创建一个OnItemTouchListener,拦截所有的Touch事件。但不执行任何后续操作
RecyclerView.OnItemTouchListener disabler = new RecyclerView.OnItemTouchListener() {

            @Override
            public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                //拦截事件
                return true;
            }

            @Override
            public void onTouchEvent(RecyclerView rv, MotionEvent e) {

            }

            @Override
            public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

            }
        };
//在动画开始执行得到时候添加监听
recyclerview.addOnItemTouchListener(disabler);
//在动画执行完成后释放监听
mBinding.recyclerview.removeOnItemTouchListener(disabler);

总结

上面就是我在工作中遇到的问题之一,才疏学浅,如有更好的解决办法还望不吝赐教,留言告知!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容