Android:滚动后,RecyclerView内容搞砸了

时间:2015-04-17 14:43:08

标签: android android-recyclerview android-viewholder

我使用RecyclerView显示标记列表,并且值的每个标记都显示为CardView。但是,在向下滚动RecyclerView并向后滚动之后,卡片的某些内容会丢失,如下面的两个屏幕截图所示。滚动后,红色矩形中的内容将丢失。

在滚动之前; enter image description here

滚动后 enter image description here

我想知道它是否是RecyclerView的一个错误,并且在谷歌搜索后找不到解决方案。

除标题外,所有观点均不可见,其可见性取决于商标的价值。

有谁知道为什么会这样?

5 个答案:

答案 0 :(得分:32)

在与同样的问题进行了大约24小时的斗争之后,我发现了一个对我有用的解决方案。关键是使用setIsRecyclable()类的RecyclerView.ViewHolder方法。

以下是我的onBindViewHolder()代码的一部分。

@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
    final DataSource dataSource = dataSourceList.get(position);

    holder.setIsRecyclable(false);

    holder.name.setText(dataSource.getName());
    holder.active.setChecked(dataSource.getActive());

    String logoStr = dataSource.getLogo();

    //Logo
    /**
     * Do all the logo insertion stunts here
     */
    /**
     * Register the changes to the Switch
     */
    holder.active.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){
            dataSource.setActive(isChecked);
        }
    });
}

答案 1 :(得分:28)

onBindHolder多次调用,因为回收者需要一个视图,除非在视图类型改变的情况下使用新视图。 因此,每次在子视图中设置visilibity时,其他视图状态也会发生变化。

无论何时向上和向下滚动,都会使用错误的可见性选项重新绘制这些视图。

解决方案:

您有一个setValue方法检查值并设置为查看。如果需要,它会调用另一种方法" showView"。你需要实现else语句(值为0或null)和hideView那里......

void setValue(Object value, TextView textView, TableRow row, View seperator) {
    if (value != null) {
        if (!isEmpty(value.toString())) {
            textView.setText(String.valueOf(value));
            showViews(row, seperator);
        }
    } else
        hideViews(row, seperator);
}

private void showViews(TableRow row, View seperator) {
    row.setVisibility(View.VISIBLE);
    seperator.setVisibility(View.VISIBLE);
}

private void hideViews(TableRow row, View seperator) {
    row.setVisibility(View.INVISIBLE); // if there is a empty space change it with View.GONE
    seperator.setVisibility(View.INVISIBLE);
}

答案 2 :(得分:12)

onBindHolder多次调用,因为Recycler View需要一个视图,除非是新视图。因此,每次在子视图中设置相关性时,其他视图状态也会发生变化。

无论何时向上和向下滚动,都会使用错误的可见性选项重新绘制这些视图,因此请始终指定这两个条件,因为回收者视图不会知道我们小部件的先前状态/条件/值。

解决方案:

如果在If块中你设置任何android widget.setVisibility(View.Gone)的可见性,那么在else块中你必须设置它的可见性与widget.setVisibility(View.Visible)相反以克服上述问题

 @Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {

    viewHolder.tvName.setText(ModelCategoryProducts.name.get(i));
    viewHolder.tvPrice.setText("Rs."+String.format("%.2f", Float.parseFloat(ModelCategoryProducts.price.get(i))));
    if(ModelCategoryProducts.special_price.get(i).equals("null")) {
        viewHolder.tvSpecialPrice.setVisibility(View.GONE); // here visibility is gone and in else it's opposite visibility i set.
        viewHolder.tvPrice.setTextColor(Color.parseColor("#ff0000"));
        viewHolder.tvPrice.setPaintFlags(0);// here paint flag is 0 and in else it's opposite flag that i want is set.
    }else if(!ModelCategoryProducts.special_price.get(i).equals("null")){
        viewHolder.tvPrice.setTextColor(Color.parseColor("#E0E0E0"));
        viewHolder.tvSpecialPrice.setVisibility(View.VISIBLE);
        viewHolder.tvSpecialPrice.setText("Rs." + String.format("%.2f", Float.parseFloat(ModelCategoryProducts.special_price.get(i))));
        viewHolder.tvPrice.setPaintFlags(viewHolder.tvPrice.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
    }
    if (!ModelCategoryProducts.image_url.get(i).isEmpty()) {
        Picasso.with(context)
                .load(ModelCategoryProducts.image_url.get(i))
                .into(viewHolder.ivProduct);
    }

    viewHolder.setClickListener(new ItemClickListener() {
        @Override
        public void onClick(View view, int position, boolean isLongClick) {
            if (isLongClick) {
//                    Toast.makeText(context, "#" + position + " - " + ModelCategoryProducts.name.get(position) + " (Long click)", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(context, "#" + position + " - " + ModelCategoryProducts.name.get(position), Toast.LENGTH_SHORT).show();
                Intent i = new Intent(context, ProductDetail.class);
                i.putExtra("position",position);
                i.putExtra("flagHlvCheck", 5);
                context.startActivity(i);
            }
        }
    });
}

答案 3 :(得分:0)

这是由于在滚动时重复使用视图。要解决此问题,您需要重置其他单元格可见的任何视图(示例中为YUZME)。

在setValue(对象值,TextView textView,TableRow行,View seperator)中,只需再次隐藏所有txtVize *。


Recycler视图以3个视图开始:

[0] FIZ104

[1] MAT102

[2] REK361

当视图滚动到底部视图[0]和[1]被回收时。当您向后滚动到顶视图时[2]用于显示FIZ104和MAT102中包含的数据,并且对REK361所做的任何更改仍然存在。

答案 4 :(得分:0)

如果您遇到ex的可见性问题。如果您已根据条件设置了视图的可见性,但是如果向下滚动,则视图会刷新,并且该回收器视图项内的视图的可见性会发生变化,从而违反条件。

以下是解决方案:

<强> 1。首先将标记分配给您要维护其可见性的视图。

    holder.myImageView.setTag(myTeamLists.get(position));
    MyDTOClass checkWetherToShow=(MyDTOClass)holder.myImageView.getTag();

<强> 2。现在应用您的条件并切换可见性

    if (checkWetherToShow.getHasToShowImage()){
        holder.myImageView.setVisibility(View.VISIBLE);
    }else{
        holder.myImageView.setVisibility(View.GONE);
    }

答案的关键是不要忘记其他部分