2015-04-17 2 views
18

Я использую RecyclerView для отображения списка меток, и каждый знак значения отображается как CardView. Но некоторое содержимое карт теряется после прокрутки RecyclerView вниз и прокрутки назад, как показано на двух снимках экрана ниже. После прокрутки содержимое красного прямоугольника теряется.Android: содержимое RecyclerView перепуталось после прокрутки

ПЕРЕД НАПРАВЛЕНИЕМ; enter image description here

ПОСЛЕ Scrolling; enter image description here

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

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

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

+1

Предлагаю вам написать специальные компоненты для просмотра. Видимость настроек не является хорошей реализацией. Ваш проект находится на git? Поэтому я могу создать запрос на перенос к нему dostum;)? –

+0

Я бы настоятельно рекомендовал * рефакторинг * вашего кода, прежде чем продолжить. Чрезвычайно трудно следовать, и у вас есть ПУТЬ ко многим представлениям. Вы должны иметь возможность создавать много из них динамически, чтобы помочь сократить некоторые коды. Я действительно считаю, что проблемы находятся в 'onBindViewHolder'. –

+0

@ EmreAktürk К сожалению, его нет на git из-за этого есть некоторые специальные веб-сервисы из моего университета. Что я могу реализовать с пользовательским представлением, я не могу понять :) Я не могу думать, что делать, любая помощь будет отличной. -JaredBurrows На самом деле веб-сервис просмотра настолько грязный. Сервис имеет 10 полей Vize, и все они содержат лекционные знаки. Я пытаюсь проверить, не является ли поле Vize (метка) пустым из службы, а затем показать текст. –

ответ

22

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

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

Решение:

У вас есть обратные значения метода SetValue и установить для просмотра. Если необходимо, он вызывает другой метод «showView». Вы должны реализовать еще заявление (которое значение 0 или нуль) и 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); 
} 
+0

Как я дурак, я так не думал. Ты спас мне жизнь, большое спасибо. Kralsın :) –

+0

откуда должен называться этот метод? – kgandroid

+0

в методе OnBindHolder. –

0

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

Внутри setValue (значение объекта, TextView textView, TableRow row, View seperator) просто снова закроет все txtVize *.


Ресайклер вид начинается с 3-мя видами:

[0] FIZ104

[1] MAT102

[2] REK361

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

+0

Благодарим за ответ. Я знаю механизм просмотра на самом деле, что я хочу сделать, это не перерабатывать представления или сохранять свои состояния даже в пользовательских свитках. Я почти перебираю, чтобы понять это примерно через 6 часов, и попробовал все, но никто из них не работал. –

8

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

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

Решение:

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

Этот парень прав! –

19

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

Это не решение вообще, вы в основном говорите, что recyclerView не делает того, что он сделал, т. Е. Перерабатывает свои представления. Принятый ответ работает хорошо. –

+0

Своего согласия.Но принятый ответ не сработал для меня или, может быть, я не смог бы выполнить шаги, так как ссылки, опубликованные @Swisyn, нарушены. Я думаю, что Google намеренно создал «RecyclerView.ViewHolder.setIsRecyclable()» для случаев, когда RecyclerView не должен перерабатывать виды, а виды рециркуляции имеют неблагоприятные последствия. – aphoe

+1

Я согласен, что, возможно, это не лучшее решение, но для меня это единственный, который работает после более чем 24 часов, пытаясь найти решение. –

-1

Если у вас возникли проблемы с проблемой видимости для 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); 
    } 

Ключ к ответу здесь не забыть еще часть.

Смежные вопросы