RecyclerView - 获取所有现有视图/查看者

时间:2016-01-12 11:18:50

标签: android android-recyclerview

我希望在显示数据时更新RecyclerView,在我的情况下,我会显示带或不带标签的图片。

默认情况下,我在创建视图持有者时设置标签的可见性,这很好,但我希望用户在显示RecyclerView时通过菜单更改标签可见性,所以我想手动更新RecyclerView中所有现有视图的可见性。

我可以以某种方式获得所有现有的Views吗?我需要所有,不仅仅是可见的,我不希望以后回收的View没有更新......

5 个答案:

答案 0 :(得分:56)

首先,你需要获得所有观点'显示的索引,然后你需要遍历每个索引,并使用每个视图的viewHolder:

final int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
final int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();
for (int i = firstVisibleItemPosition; i <= lastVisibleItemPosition; ++i) {
    ViewHolder holder = (ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(i);
    ...
    }

编辑:似乎它并不总是返回您可能想要处理的所有ViewHolders。这似乎是一个更稳定的解决方案:

for (int childCount = recyclerView.getChildCount(), i = 0; i < childCount; ++i) {
   final ViewHolder holder = recyclerView.getChildViewHolder(recyclerView.getChildAt(i));
   ...
   }

答案 1 :(得分:17)

  • 使用notifyDataSetChanged()更新整个适配器列表大小并不方便。
  • 获取所有当前的RecyclerView子项(即所有可见项目)是不够的:有不可见的绑定视图持有者:在启动时加载后通常有2或3个项目绑定在最后一个可见位置(取决于你的LayoutManager)。

我只是尝试观察我放的日志,RV绑定了更多不可见的项目,实际上我找不到检索它们的方法。我最终在SetList onBindViewHolder()中的onViewRecycled() ViewHolders以及private Set<AbstractViewHolder> mBoundViewHolders = new HashSet<>(); private int mVisibility = View.VISIBILE; // So you can have access from the Activity/Fragment public Set<AbstractViewHolder> getAllBoundViewHolders() { return Collections.unmodifiableSet(mBoundViewHolders); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List payloads) { // Binding code ... holder.view.setVisibility(mVisibility); // Caching VH mBoundViewHolders.add((AbstractViewHolder) holder); } @Override public void onViewRecycled(RecyclerView.ViewHolder holder) { // Uncaching VH mBoundViewHolders.remove(holder); } // Your method becomes public void updateVisibility(int visibility) { mVisibility = visibility; for (AbstractViewHolder holder : mBoundViewHolders) { holder.updateVisibility(visibility); } } 取消隐藏缓存

notifyItemRangeChanged()

实现您的界面或抽象ViewHolder,以便您可以调用您的方法。 通过这种方式,您可以访问ViewHolder内容。

这就是我在FlexibleAdapter中取消选择而不是来调用toggleActivation()的内容。如果用户有动画,则会执行所有操作,并且当我调用方法listagg()时,背景也会更改。

如果您知道更好的方法来检索所有绑定的VH,请告诉我。

答案 2 :(得分:13)

在适配器类中:

Boolean isVisible = false;

public CustomAdapter(boolean isVisible) {
    this.isVisible= isVisible;
}
    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
     ...

         if (isVisible){
           //setVisibility(View.VISIBLE)
         }else{
         //setVisibility(View.INVISIBLE
         }
    }

public void updateVisibility(boolean newValue){
 isVisible= newValue;
}

Activity中要更新实例化适配器的值:

adapter.updateVisibility(false);
adapter.notifydataSetChanged();

答案 3 :(得分:6)

所有现有视图都是可见的,加上RecyclerView缓存的一些视图。您可以访问所有可见的View

View child;
for (int i = 0; i < mRecycler.getChildCount(); i++) {
    child = mRecycler.getChildAt(i);
    //In case you need to access ViewHolder:
    mRecycler.getChildViewHolder(child);
}

即使您访问了缓存的View,他们还没有绑定数据,因此您不知道标签是否可见。只需在Views中设置剩余onBindViewHolder的标签可见性。

View的其余部分尚不存在,因此您无法对其进行任何更改,即使它们对所有这些都有相同的标签可见性状态

答案 4 :(得分:0)

以上所有解决方案仅提供可见的持有者,但实际上还有2-3个其他持有者受约束但不可见。为了得到那些, 我想到的最简单和准确的方法是让所有持有者:

int lastBoundHolderPosition = -1;
int lastDetachedHolderPosition = -1;

public void onBindViewHolder(final MyViewHolder holder, int position) {
    lastBoundHolderPosition = position;
    //Your implementation
}
public void onViewDetachedFromWindow(MyViewHolder holder){
    lastDetachedHolderPosition = holder.holder.getAdapterPosition();
}

如果希望所有适配器都可见(加上绑定但不可见):

if(lastDetachedHolderPosition == -1){
    for(pos = 0; pos <= lastDetachedHolderPosition; pos++){
        ViewHolder holder = (ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(pos);
    }
}else{
    if(lastBoundHolderPosition > lastDetachedHolderPosition){ //Scroll down
        //get all the bound holders
        for(int pos = lastDetachedHolderPosition + 1; pos <= lastBoundHolderPosition; pos++){
            ViewHolder holder = (ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(pos);
        }
    }else{ //Scroll up
        //get all the bound holders
        for(int pos = lastBoundHolderPosition ; pos <= lastDetachedHolderPosition-1; pos++){
            ViewHolder holder = (ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(pos);
        }

    }
}