在RecyclerView中保存和检索膨胀的View的大小

时间:2016-02-24 23:24:14

标签: android android-layout android-recyclerview recycler-adapter

我有一个RecyclerView,它有一个staggeredGridLayoutManager作为布局管理器。我的布局有2个跨度(cols),里面的项目可能有不同的高度。 膨胀的项目在LinearLayout容器中有一个ImageView和一些其他视图。

我想保存Inflated(或者我应该说是binded?)视图图像完全加载后View的大小(高度和宽度)。因为此操作让我知道在将图像放置在布局中之后,LinearLayout在最后占用的宽度和高度。

滚动后,此容器可以再次回收并粘贴。我想要实现的是根据先前计算的高度和宽度值,在绑定之后立即保存绑定布局的大小,因为这使得recyclerView的项目位置更加稳定。他们不太可能四处走动。

我的ViewHolder中有mWidth和mHeight成员,它们基本上存储了这些值。但是,我在适配器中的项目位置和相应的ViewHolder之间丢失了同步。例如,我将第8个项目的高度计算为380px,当它首次变为可见时,这是正确的。再次回收并绑定第8个位置后,我的视图高度检索为300像素,这是不正确的。

代码: BasicActivity派生自Activity ..

public ItemsRVAdapter(BasicActivity activity, JSONArray items){
    this.items = items;
    this.activity = activity;
    this.itemControl = new Items(activity);
}

OnCreate中:

@Override
public ItemListViewHolders onCreateViewHolder(ViewGroup viewGroup, int i) {


    View layoutView =activity.getLayoutInflater().inflate(R.layout.list_element_items, viewGroup, false);
    ItemListViewHolders rcv = new ItemListViewHolders(layoutView);
    return rcv;
}

OnViewAttachedToWindow(我在不同的地方尝试过相同的代码,比如onViewRecycled,但我不知道这个方法是计算大小的最合适的地方)

@Override
public void onViewAttachedToWindow(ItemListViewHolders holder)
{
    holder.layoutCapsule.measure(LinearLayout.MeasureSpec.makeMeasureSpec(0, LinearLayout.MeasureSpec.UNSPECIFIED), LinearLayout.MeasureSpec.makeMeasureSpec(0, LinearLayout.MeasureSpec.UNSPECIFIED));
    if(holder.image.getDrawable() != null){

        holder.height = holder.layoutCapsule.getHeight();
        holder.width = holder.layoutCapsule.getWidth();
    }else{
        holder.height = 0;
        holder.width = 0;
    }

}

onBindViewHolder:只有相关部分。这里我配对了位置值和我的数组的成员索引

@Override
public void onBindViewHolder(ItemListViewHolders holder, int position) {
    try {

        //JSONObject item = items.getJSONObject(holder.getAdapterPosition());
        JSONObject item = items.getJSONObject(position);
        holder.image.setImageDrawable(null);
        ViewGroup viewGroup = holder.layoutCapsule; //Main Container
        ...
    }
}

1 个答案:

答案 0 :(得分:2)

我建议寻找一种不同的方法来解决您的问题,这些项目不会因视图大小而移动,但如果您想这样做,这是我建议的解决方案:

不要依赖或保存持有者的大小值,因为这会被回收,你需要创建一个对象"描述符"使用每个位置的值(宽度和高度)并将它们保存在HashMap或类似的东西上,保存已经存在的值,我理解" onViewAttachedToWindow"。

class Descriptor(){
   int width;
   int height;

void setWidth(int width){
   this.width = width;
}
int getWidth(){
   return width;
}
void setHeight(int height){
   this.height = height;
}
int getHeight(){
   return height;
}

在构造函数上初始化数组:

descriptors = new HashMap<Integer, Descriptor>();
onBindViewHolder中的

保存视图标记上的位置以在OnViewAttachedToWindow上使用它

public void onBindViewHolder(ItemListViewHolders holder, int position) {
   ....
   holder.image.setTag(position);
   ...
}

在onViewAttachedToWindow上填充值

public void onViewAttachedToWindow(ItemListViewHolders holder){
   ...
   int position = (Integer)holder.image.getTag();
   Descriptor d = descriptors.get(position);
   if(d == null){
      d = new Descriptor();
      descriptors.put(position, d);
   }
   d.setWidth(holder.layoutCapsule.getWidth());
   d.setHeight(holder.layoutCapsule.getHeight());
   ...
}

然后在你需要按位置获取它的方法上使用描述符上的大小数据,你将在用户向下滚动时创建描述符,这也可以假设数据在生命周期中保持相同的位置。适配器。