我有一个 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());
...
}
然后在您需要按位置获取它的方法上使用描述符上的大小数据,您将在用户向下滚动时创建描述符,这也是假设数据在适配器的生命周期中保持相同的位置。