这可能是stackoverflow中关于Android RecyclerView的最常见问题,但我在任何地方都找不到任何合适的解决方案来满足我的要求。
我的问题
我正在使用带有 Room Database 和 Retrofit 的分页库来填充 Recyclerview 中的内容。有两个 VIEW_TYPE;一个是卡片视图中的实际数据,另一个是进度条布局,当调用 API 以获取下一组数据时,它会显示在 Recyclerview 的底部。列表中的每个卡片视图都相当复杂,包含图像和文本。
一切正常,直到我在内容混乱时开始向上滚动。准确地说,一个 textview 需要根据另一个 textView 的测量高度来显示。在我向下和向上滚动后,测量的高度没有正确显示。图片截图附在下面
我发现几乎每个人都建议有 2 个解决方案。
覆盖适配器中的 getItemViewType(int position) 并返回位置
~ 我不能使用这个解决方案,因为我必须保留 2 个 VIEW_TYPES。我的 getItemViewType 代码如下:
public int getItemViewType(int position) { if (hasExtraRow() && position == getItemCount() - 1) { return R.layout.item_network_state; } else { return R.layout.card_post_timeline; } }
在 ViewHolder 中使用setIsRecyclable(false)
~ 如果我使用这个解决方案,它可以解决我的问题,但我不想使用它,因为这违背了 Recyclerview 的全部目的,并且在有大数据集时会严重影响性能。
我的代码
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
if (viewType == R.layout.card_post_timeline) {
View view = layoutInflater.inflate(R.layout.card_post_timeline, parent, false);
TimelinePostViewHolder viewHolder = new TimelinePostViewHolder(view, context,optionsSelected );
return viewHolder;
} else if (viewType == R.layout.item_network_state) {
View view = layoutInflater.inflate(R.layout.item_network_state, parent, false);
return new NetworkStateItemViewHolder(view);
} else {
throw new IllegalArgumentException("unknown view type");
}
}
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (getItemViewType(position)) {
case R.layout.card_post_timeline:
((TimelinePostViewHolder) holder).bindTo(getItem(position)); // Data binding happens here
break;
case R.layout.item_network_state:
((NetworkStateItemViewHolder) holder).bindView(networkState);
break;
}
}`
问题
我们可以使用什么替代方案来解决这个古老的 Recyclerview 问题?
更新 -
唯一的问题是“显示更多”文本视图可见性是由 postBody 文本视图测量的高度计算的。向下然后向上滚动后,无论文本内容如何,Textview 的测量高度总是相同。
相同的逻辑如下:
private void renderPostContent(Post post) {
tvPostBody.fromHtml(post.getPostContent());
Log.d(StringConstants.LOG_TAG, tvPostBody.getText().toString());
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(IntegerConstants.SCREEN_WIDTH, View.MeasureSpec.AT_MOST);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
tvPostBody.measure(widthMeasureSpec, heightMeasureSpec);
int measuredTextViewHeight = tvPostBody.getMeasuredHeight();
Log.d(StringConstants.LOG_TAG, "list position - " + getAdapterPosition() + " measuredHeight - " + measuredTextViewHeight);
if (measuredTextViewHeight > IntegerConstants.SCREEN_WIDTH) {
tvPostBody.setMaxHeight(IntegerConstants.SCREEN_WIDTH);
tvShowMore.setVisibility(View.VISIBLE);
// setIsRecyclable(false);
Log.d(StringConstants.LOG_TAG, "ShowMore visibile");
} else {
tvPostBody.setMaxHeight(IntegerConstants.SCREEN_WIDTH);
tvShowMore.setVisibility(View.GONE);
//setIsRecyclable(true);
Log.d(StringConstants.LOG_TAG, "ShowMore gone");
}
}