2015-05-06 4 views
5

Ошибка при прокрутке RecyclerView после прокрутки вниз и вверх. Идея состоит в том, чтобы изменить цвет элементов, но когда я прокручиваю вниз, все отлично, и когда свиток идет вверх - элементы, которые не должны быть окрашены, меняют цвет.RecyclerView перепутал данные при прокрутке

Вот мой адаптер:

public class NotificationsAdapter extends RecyclerView.Adapter<NotificationsAdapter.ViewHolder> { 

private NotificationData notificationData; 
private Context mContext; 
private ArrayList<NotificationData> infromationList = new ArrayList<>(); 


public NotificationsAdapter(Context context, ArrayList<NotificationData> infromationList) { 
    this.infromationList = infromationList; 
    this.mContext = context; 
} 


@Override 
public NotificationsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 

    View itemLayoutView; 
    ViewHolder viewHolder; 

    itemLayoutView = LayoutInflater.from(parent.getContext()) 
      .inflate(R.layout.notification_single_item, parent, false); 
    viewHolder = new ViewHolder(itemLayoutView, viewType); 

    return viewHolder; 
} 

@Override 
public void onBindViewHolder(NotificationsAdapter.ViewHolder holder, int position) { 

    notificationData = infromationList.get(position); 
    holder.notificationDate.setText(convertDate(notificationData.getDate())); 
    holder.notificationStatus.setText(notificationData.getNotificationStatus()); 
    holder.orderDescription.setText(notificationData.getNotificationLabel()); 

    if ("true".equals(notificationData.getReadStatus())) { 
     holder.root.setBackgroundColor(mContext.getResources().getColor(R.color.white)); 
     holder.notificationStatus.setTypeface(Typeface.create("sans-serif-light", Typeface.NORMAL)); 
    } 

} 

@Override 
public int getItemCount() { 
    return (null != infromationList ? infromationList.size() : 0); 
} 

public static class ViewHolder extends RecyclerView.ViewHolder { 

    public TextView notificationDate; 
    public TextView notificationStatus; 
    public TextView orderDescription; 
    public LinearLayout root; 

    public ViewHolder(View itemView, int position) { 
     super(itemView); 

     notificationDate = (TextView) itemView.findViewById(R.id.notificationDate); 
     notificationStatus = (TextView) itemView.findViewById(R.id.notificationStatus); 
     orderDescription = (TextView) itemView.findViewById(R.id.orderDescription); 
     root = (LinearLayout) itemView.findViewById(R.id.root); 
    } 

} 

private String convertDate(String date) { 
    String convertedDate; 

    String[] parts = new String[2]; 
    parts = date.split("T"); 
    date = parts[0]; 

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd"); 
    Date testDate = null; 
    try { 
     testDate = sdf.parse(date); 
    }catch(Exception ex){ 
     ex.printStackTrace(); 
    } 
    SimpleDateFormat formatter = new SimpleDateFormat("dd.mm.yyyy"); 
    convertedDate = formatter.format(testDate); 

    return convertedDate; 
} 
} 

ответ

2

Существует проблема в вашем onBindViewHolder(...), должно быть:

if ("true".equals(notificationData.getReadStatus())) { 
    holder.root.setBackgroundColor(mContext.getResources().getColor(R.color.white)); 
    holder.notificationStatus.setTypeface(Typeface.create("sans-serif-light", Typeface.NORMAL)); 
} 
else { 
    holder.root.setBackgroundColor(yourDefaultColor); 
    holder.notificationStatus.setTypeface(yourDefaultTypeface); 

} 
+0

Это сработало для меня. Я думал, что значения по умолчанию - defauf set, но были в полном недоумении. – MeLine

26

У меня была такая же проблема, и единственное решение, которое я нашел для этого:

holder.setIsRecyclable(false); 

Ваш переработчик больше не будет перерабатывать, поэтому элементы будут одинаковыми при прокрутке, и если вы хотите удалить какой-либо элемент, не используйте notifyitemRemoved(position), вместо этого используйте notifyDataSetChanged().

+2

Выше полезно для меня спасибо ..... – Dilip

+5

BEWARE: Вы не должны использовать ни одно из этих советов. Как сказал сам Джонатан, взгляды больше не будут переработаны, что полностью утрачивает цель рецидивирования и приведет к плохим результатам. Также использование функции notifyDataSetChanged() всегда должно быть вашим последним средством - если это вообще возможно, попытайтесь сообщить адаптеру точно, какие элементы были обновлены при удалении или добавлении данных - это не только улучшит производительность, но и позволит выполнять анимацию соответствующим образом. – jhm

+0

thanx man i был найден этот номер последние 3 дня .. –

0

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

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

Решение:

Если в случае, если блок установить видимость любого андроида widget.setVisibility (View.Gone), то в блоке еще вы должны установить его видимость напротив значения, как 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); 
      } 
     } 
    }); 
} 
0
@Override 
public DataObjectHolder onCreateViewHolder(ViewGroup parent, 
              int viewType) { 
    View view = LayoutInflater.from(parent.getContext()) 
      .inflate(R.layout.custom_layout, parent, false); 

    DataObjectHolder dataObjectHolder = new DataObjectHolder(view); 
    dataObjectHolder.setIsRecyclable(false); 

    return dataObjectHolder; 
} 
8

Добавить setHasStableIds(true); в конструктор адаптера и Перекрыть эти два methodes в адаптере.

@Override 
public long getItemId(int position) { 
      return position; 
} 

@Override 
public int getItemViewType(int position) { 
     return position; 
} 
+1

Это сработало для меня. Можете ли вы дать еще несколько объяснений, почему это работает? –

+0

Можете ли вы предоставить больше объяснений по этому поводу? – Rino

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