我有一个RecyclerView,它接收数据列表 - 标题,每个标题都有一堆子标题和文本。所以我不知道我将为item提供多少个子标题,并使用此代码动态夸大内容:
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((ViewHolder) holder).header.setText(data.get(position).getTitle());
OrganizationInfoEntry entry = data.get(position);
Map<String, String> entryContent = entry.getContent();
for (Map.Entry<String, String> mapEntry : entryContent.entrySet()) {
String subheaderText = mapEntry.getKey();
String answerText = mapEntry.getValue();
View v = LayoutInflater.from(context).inflate(R.layout.item_card_content, null);
TextView subheader = (TextView) v.findViewById(R.id.subheader);
subheader.setText(subheaderText);
TextView answer = (TextView) v.findViewById(R.id.answer);
answer.setVisibility(GONE);
answer.setText(answerText);
subheader.setOnClickListener(v1 -> toggleVisibility(answer));
((ViewHolder) holder).content.addView(v);
}
}
从第一眼看,一切看起来都不错,但滚动后的第一个和最后一个项目的数据开始加倍,最后所有其他项目加入聚会,将我的回收转为绝对混乱。
请告诉我如何解决这个问题。
P.S。 holder.setIsRecycable(false)
不是解决方案。这会影响使用Recycler的整个想法,并在滚动后隐藏显示的文本。
P.P.S 这就是它在设备上的外观。
答案 0 :(得分:1)
这里的问题是您为回收站视图创建了不同的列表项,一开始就没问题,但滚动时,recyclerView会尝试回收带有n个subHeaders的旧视图并插入可能包含m的新数据! = n个subHeaders。有几种解决方案,如果你知道不同视图的常数和数量都很少(假设你知道你可以有3到5个subHeaders ---&gt; 3种不同的视图类型)你可以用不同的视图类型创建一个回收者视图ceckout this stackOverflow answer。另一个解决方案是创建一个costum视图组,并测量它对subHeader的数量的影响(如果你这样做,你不需要列表项xml文件)。
public class ItemView extends ViewGroup {
private static Paint mPaint;
private final ImageView mAvatar;
protected final TextView mText;
private final TextView mAuthor;
public ItemView(Context context) {
super(context);
setWillNotDraw(false);
mAvatar = new ImageView(context);
int size = getResources().getDimensionPixelSize(R.dimen.avatar_size);
mAvatar.setLayoutParams(new LayoutParams(size, size));
addView(mAvatar);
Point p = new Point();
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
display.getSize(p);
mText = new TextView(context);
addView(mText);
mAuthor = new TextView(context);
mAuthor.setSingleLine();
addView(mAuthor);
}
public void setData(Status item) {
AppContext.getImageHandler().load(item.getUser().getProfileImageURL(), mAvatar);
mAuthor.setText(item.getUser().getName());
mText.setText(item.getText());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int height = measureAllChildren(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), height);
}
protected int measureAllChildren(int widthMeasureSpec, int heightMeasureSpec) {
int m = getResources().getDimensionPixelSize(R.dimen.margin);
measureChild(mAvatar, widthMeasureSpec, heightMeasureSpec);
measureChild(mAuthor, widthMeasureSpec, heightMeasureSpec);
measureChild(mText, MeasureSpec.makeMeasureSpec(getMeasuredWidth() - 2 * m, MeasureSpec.EXACTLY), heightMeasureSpec);
mAvatar.layout(m, m, m + mAvatar.getMeasuredWidth(), m + mAvatar.getMeasuredHeight());
mAuthor.layout(mAvatar.getRight() + m, mAvatar.getTop(), mAvatar.getRight() + m + mAuthor.getMeasuredWidth(), m + mAuthor.getMeasuredHeight());
mText.layout(m, m + mAvatar.getBottom(), getMeasuredWidth(), m + mAvatar.getBottom() + mText.getMeasuredHeight());
return calculateFinalHeight(m);
}
protected int calculateFinalHeight(int margin) {
return mText.getBottom() + margin;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mPaint == null) {
mPaint = new Paint();
mPaint.setColor(Color.rgb(160, 200, 220));
mPaint.setStrokeWidth(getResources().getDisplayMetrics().density);
}
canvas.drawLine(0, getHeight(), getWidth(), getHeight(), mPaint);
}
}
您可以使用measureAllChildren方法测量所有subHeaders,然后使用calculateFinalHeight()来测量最后一个subheader的最终高度。
如果您使用costum视图组,那么适配器内的方法可能如下所示:
// Create new views (invoked by the layout manager)
@Override
public Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
ItemView itemView = new ItemView(context);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
((ItemView) holder.itemView).setData(mItems.get(position));
}
final class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private final Context context;
public ViewHolder(ItemView v) {
super(v);
context = v.getContext();
v.setOnClickListener(this);
}
@Override
public void onClick(View v) {
dispatchIntent();
}
}
祝你好运:)