Android 在不可操作时 获取Recyclerview的viewholder并动态改变view

应公司的需求,需要在没有触摸屏只有上下确定和取消的物理按键设备上操作Recyclerview并标记出当前选中栏(多一嘴,卧槽啊,搞毛啊,省预算也不是这么省的啊!不带触摸屏你用QT啊!QT效果不好?不带触摸屏加物理按键效果就好了?!),做的时候就想当然的在bindView里把holder添加到了集合里,然后根据上下键事件往下走改变view,然后,突然很傻比的发现忽略了最基本的事情,Recyclerview就只会在一开始创建当前屏幕显示数的holder,并不能获取到全部的holder,这样我在按下键的时候就只会走到当前显示的最后item上去,下面就再也走不动了。

好吧,开始找方法,大体思路就是动态的来获取holder改变布局,但是我需要在外面的物理按键回调里改变Recyclerview里面的view,嗯,一开始还就创建几个,后面的就不能再onBind里拿到了,再看看有没有什么其他方法,看见一个,getChildViewHolder(View child),嗯,看方法名很靠谱,但是参数是view。。。。

好吧,只能进去看看代码了,从上到下翻了一圈,发觉有一个方法

    /**
     * Return the ViewHolder for the item in the given position of the data set. Unlike
     * {@link #findViewHolderForLayoutPosition(int)} this method takes into account any pending
     * adapter changes that may not be reflected to the layout yet. On the other hand, if
     * {@link Adapter#notifyDataSetChanged()} has been called but the new layout has not been
     * calculated yet, this method will return <code>null</code> since the new positions of views
     * are unknown until the layout is calculated.
     * <p>
     * This method checks only the children of RecyclerView. If the item at the given
     * <code>position</code> is not laid out, it <em>will not</em> create a new one.
     * <p>
     * When the ItemAnimator is running a change animation, there might be 2 ViewHolders
     * representing the same Item. In this case, the updated ViewHolder will be returned.
     *
     * @param position The position of the item in the data set of the adapter
     * @return The ViewHolder at <code>position</code> or null if there is no such item
     */
    public ViewHolder findViewHolderForAdapterPosition(int position) {
        if (mDataSetHasChangedAfterLayout) {
            return null;
        }
        final int childCount = mChildHelper.getUnfilteredChildCount();
        // hidden VHs are not preferred but if that is the only one we find, we rather return it
        ViewHolder hidden = null;
        for (int i = 0; i < childCount; i++) {
            final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i));
            if (holder != null && !holder.isRemoved() && getAdapterPositionFor(holder) == position) {
                if (mChildHelper.isHidden(holder.itemView)) {
                    hidden = holder;
                } else {
                    return holder;
                }
            }
        }
        return hidden;
    }

嗯,除了mDataSetHasChangedAfterLayout这个变量看起来有点辣眼,后面明显就可以获取到我所需要的holder啊,可以可以,来边走边试

rvPsytopicList.scrollToPosition(index);
RecyclerView.ViewHolder viewHolderForAdapterPosition = rvPsytopicList.findViewHolderForAdapterPosition(index);

先让它滑动到我所需要改变的item,更新holder,然后我获取holder该干嘛干嘛,嗯,简直天才。嗯?走到超出屏幕的下一条返回了个null?嗯?继续按走到最后再往上走就能获取到了?这玩意还有延迟不成?好吧。。再进去源码看吧。

for (int i = 0; i < childCount; i++) {
            final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i));
            //这里循环检查已存在的holder
            if (holder != null && !holder.isRemoved() && getAdapterPositionFor(holder) == position) {
                if (mChildHelper.isHidden(holder.itemView)) {
                    hidden = holder;
                } else {
                    return holder;
                }
            }
        }

嗯。。。。。并没有找到为啥,但是看在以上循环检查的时候debug知道以前滚过的item的holder是有的,可以,这样这个需求的难度就是不存在的了兄弟~,立马改代码,让每次多scroll一个角标,成功实现!

rvPsytopicList.scrollToPosition(index+1);
RecyclerView.ViewHolder viewHolderForAdapterPosition = rvPsytopicList.findViewHolderForAdapterPosition(index);

(初来乍到,一脚踏入不知深浅,望多多指教!)

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,429评论 25 707
  • 这篇文章分三个部分,简单跟大家讲一下 RecyclerView 的常用方法与奇葩用法;工作原理与ListView比...
    LucasAdam阅读 4,374评论 0 27
  • 内容抽屉菜单ListViewWebViewSwitchButton按钮点赞按钮进度条TabLayout图标下拉刷新...
    皇小弟阅读 46,705评论 22 664
  • 今天朋友问我 你喜欢了那么久的他现在还有感觉吗 我想了很久 没有说那句差点脱口而出的没有 我说 我举个例子吧 你有...
    很怪阅读 269评论 0 0
  • 清明假日,我和小伙伴驱车前往,奔向梨木台。 梨木台,被专家学者称为“天津的神农架”、“北方的热带雨林”。它是国家地...
    安之腾阅读 1,026评论 16 13