RecyclerView仅显示单个条目问题求助(含Header、GridLayoutManager)
我帮你梳理下当前代码里的几个核心问题,正是这些问题导致了列表显示异常:
1. Adapter的条目计数与视图类型逻辑完全错误
你现在的getItemCount()只返回了Media条目的数量(2个),但每个Media条目包含1个Header + N张图片Item,所以总条目数应该是所有Media的(1 + imageUrl.size())之和。同时,isPositionHeader()只判断position==0是Header,这就导致第二个Media的Header根本不会被识别,更别说它的图片了。
修复代码:
首先,我们需要重新计算总条目数,并且能根据position判断当前是哪个Media的Header或者Item:
// 新增方法计算总条目数 @Override public int getItemCount() { int total = 0; for (Media media : mediaArrayList) { total += 1 + media.getImageUrl().size(); // 每个Media占1个Header + 图片数量的Item } return total; } // 新增方法,根据position找到对应的Media和当前是Header还是Item private MediaItemInfo getMediaItemInfo(int position) { int currentPos = 0; for (Media media : mediaArrayList) { // 先判断当前position是不是这个Media的Header if (currentPos == position) { return new MediaItemInfo(media, true, -1); } currentPos++; // 再判断是不是这个Media的图片Item for (int i = 0; i < media.getImageUrl().size(); i++) { if (currentPos == position) { return new MediaItemInfo(media, false, i); } currentPos++; } } return null; } // 辅助类,用来存储当前条目对应的Media、是否是Header、图片索引 private static class MediaItemInfo { Media media; boolean isHeader; int imageIndex; MediaItemInfo(Media media, boolean isHeader, int imageIndex) { this.media = media; this.isHeader = isHeader; this.imageIndex = imageIndex; } } // 修复getItemViewType @Override public int getItemViewType(int position) { MediaItemInfo info = getMediaItemInfo(position); return info.isHeader ? TYPE_HEADER : TYPE_ITEM; }
2. onBindViewHolder逻辑错误
现在你在绑定Item的时候,循环遍历当前Media的所有图片,最后只会把最后一张图片设置到ViewHolder的ImageView里,因为每个ItemViewHolder只对应一张图片,不是一个ViewHolder显示所有图。而且之前的position和Media的对应关系错误,现在用上面的getMediaItemInfo来获取正确的数据。
修复代码:
@Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { MediaItemInfo info = getMediaItemInfo(position); if (info == null) return; if (holder instanceof MediaViewHeader) { MediaViewHeader mediaViewHeader = (MediaViewHeader) holder; mediaViewHeader.textViewDate.setText(info.media.getDate()); } else if (holder instanceof MediaItemView) { MediaItemView mediaItemView = (MediaItemView) holder; String url = info.media.getImageUrl().get(info.imageIndex); if (!TextUtils.isEmpty(url)) { Picasso.get() .load(url) .resize(300, 250) .placeholder(R.drawable.progress_animation_small) .error(R.drawable.ic_avatar_small) .into(mediaItemView.imageViewPhoto); } else { mediaItemView.imageViewPhoto.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_avatar_small)); } } }
3. GridLayoutManager的SpanSizeLookup配置错误
你设置的Grid是3列,但Header的spanSize设为1,Item设为2,这会导致布局排列混乱,Header应该占满整个一行(也就是spanSize=3),每个图片Item占1列。
修复代码:
final GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 3); gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { // Header占满3列,Item占1列 return mediaAdapter.getItemViewType(position) == MediaAdapter.TYPE_HEADER ? 3 : 1; } });
4. 额外优化:布局的小问题
media_item_header_layout的根布局用match_parent没问题,但可以给TextView加左右margin,和图片保持一致;另外media_item_layout的根布局可以用wrap_content或者match_parent(因为GridLayoutManager会控制宽度),确保图片之间的间距正确。
按照上面的修改后,你的RecyclerView应该能正确显示两个Media条目:每个条目先显示日期Header,然后显示3张图片,第二个Media的内容也会正常展示。
内容的提问来源于stack exchange,提问作者Siddhi Jambhale

