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

我想在 View 图像完全加载后保存 Inflated(或者我应该说绑定(bind)?) View 的大小(高度和宽度)。因为这个操作让我知道了LinearLayout在final中占据了多少宽度和高度——在图像放入布局之后——。

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

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

代码:
BasicActivity 派生自 Activity..

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

在创建:
@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
        ...
    }
}

最佳答案

我建议寻找一种不同的方法来解决您的项目移动问题而不取决于 View 大小,但如果您想以这种方式进行,这是我建议的解决方案:

不要依赖或保存持有人的大小值,因为这会被回收,您需要创建一个对象“描述符”,其中包含每个位置的值(宽度和高度)并将它们保存在 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 中保存 View 标签上的位置以在 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());
   ...
}

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

10-06 12:27