滚动后,RecycleView会将项目内容加倍

时间:2017-03-25 10:20:20

标签: android android-recyclerview

我有一个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 这就是它在设备上的外观。

  1. 一切都好。
  2. enter image description here

    1. 我们显示内容文本,因此第一项变得比屏幕大。
    2. enter image description here

      1. 向下滚动 - 开始乱七八糟。
      2. enter image description here

1 个答案:

答案 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();
    }
}
祝你好运:)