Android: содержимое RecyclerView перепуталось после прокрутки [закрыто]

Я использую RecyclerView для отображения списка меток, и каждая метка значения отображается как CardView. Но некоторое содержимое карт теряется после прокрутки RecyclerView вниз и прокрутки назад, как показано на двух скриншотах ниже. Содержимое красного прямоугольника теряется после прокрутки.

ПЕРЕД ПРОКРУТКОЙ; enter image description here

ПОСЛЕ ПРОКРУТКИ; enter image description here

Мне интересно, является ли это ошибкой RecyclerView и не найти решения после того, как Googling для него.

все представления невидимы, кроме заголовка, их видимость зависит от значения метки.

кто-нибудь знает, почему это произойдет?

5 ответов


onBindHolder звонил несколько раз, как переработчик нужно посмотреть, если новый тип зрения изменилась. Поэтому каждый раз, когда вы устанавливаете visilibity в дочерних представлениях, другие состояния представлений также изменяются.

всякий раз, когда вы прокручиваете вверх и вниз, эти представления повторно рисуются с неправильными параметрами видимости.

устранение :

у вас есть значения проверки метода setValue и установлено в view. При необходимости он вызывает другой метод "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);
}

после борьбы с этой же проблемой в течение 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);
        }
    });
}

onBindHolder вызывается несколько раз, поскольку представление Recycler нуждается в представлении, если новый. Поэтому каждый раз, когда вы устанавливаете visilibity в дочерних представлениях, другие состояния представлений также изменяются.

всякий раз, когда вы прокручиваете вверх и вниз, эти представления повторно рисуются с неправильными параметрами видимости, поэтому всегда указывайте оба условия, которые вызывают представление recycler, не знает предыдущего состояния/условий/значений наших виджетов.

устранение :

Если в блоке If вы устанавливаете видимость любого виджет для Android.setVisibility (View.Gone), то в блоке else вы должны установить его видимость напротив виджета vwith.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);
            }
        }
    });
}

Это связано с тем, что представления повторно используются при прокрутке. Чтобы исправить это, вам нужно будет сбросить все представления, которые были сделаны видимыми для других ячеек (YUZME в вашем примере).

внутри setValue (значение объекта, TextView textView, строка TableRow, view seperator) просто сделайте все txtvize* скрытым снова.


Recycler view начинается с 3 просмотров:

[0] FIZ104

[1] MAT102

[2] REK361

когда вид прокручивается до нижних видов [0] и [1] рециркулируются. При прокрутке назад к верхнему виду [2] используется для отображения данных, содержащихся в FIZ104 и MAT102, и любые изменения, внесенные для REK361, все еще там.


Если у вас возникли проблемы с проблемой видимости для ex. если вы установили видимость представления на основе условия, но при прокрутке вниз, представления обновляются, а видимость представления внутри этого элемента представления recycler получает изменения и, следовательно, нарушает условие.

вот решение:

1. Сначала назначить tag к тому виду, видимость которого вы хотите поддерживать.

    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);
    }

ключ к ответу здесь не забывайте, что часть else.