2015-05-06 12 views
5

Problemy z przewijaniem RecyclerView po przewijaniu w dół iw górę. Chodzi o to, aby zmienić kolor elementów, ale kiedy przewijam w dół, wszystko jest wspaniałe, a kiedy przewijanie idzie w górę - elementy, które nie powinny być zabarwione, zmieniają kolor.RecyclerView zawiedli dane podczas przewijania

Oto mój adapter:

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

Odpowiedz

2

Istnieje problem w swojej onBindViewHolder(...), powinno być:

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

To zadziałało dla mnie. Myślałem, że domyślne wartości są ustawione przez defauf, ale były całkowicie nieporozumieniem. – MeLine

26

miałem ten sam problem, a jedynym rozwiązaniem znalazłem na to:

holder.setIsRecyclable(false); 

Twój recykler nie będzie już odzyskiwany, dzięki czemu przedmioty będą takie same podczas przewijania, a jeśli chcesz usunąć jakiś przedmiot, nie używaj notifyitemRemoved(position), zamiast tego użyj notifyDataSetChanged().

+2

Powyższe jest pomocne dla mnie, dzięki ..... – Dilip

+5

UWAGA: Nie należy używać żadnej z tych porad. Jak powiedział sam Jhonatan, poglądy nie będą już poddawane recyklingowi, co całkowicie negatywnie wpłynie na cel recyklingu i doprowadzi do złych wyników. Używanie brute-force notifyDataSetChanged() powinno być zawsze ostatecznością - jeśli to w ogóle możliwe, spróbuj podać adapterowi dokładnie, które elementy zostały zaktualizowane podczas usuwania lub dodawania danych - to nie tylko poprawi wydajność, ale również pozwoli na to. prawidłowo wykonuj animacje. – jhm

+0

thanx człowiek został znaleziony ten problem ostatni 3 dzień .. –

0

onBindHolder kilka razy wywoływany jako widok Recyklera potrzebuje widoku, chyba że nowy. Tak więc za każdym razem, gdy ustawisz visilibity w widokach potomnych, inne stany poglądów również są zmianami.

Za każdym razem, gdy przewijasz w górę lub w dół, widoki te są ponownie rysowane z niewłaściwymi opcjami widoczności, dlatego zawsze określ oba warunki, które powodują, że widok recyklerów nie zna poprzedniego stanu/warunków/wartości naszych widżetów.

Rozwiązanie:

Jeśli w przypadku bloku ustawić widoczność jakiegokolwiek androida widget.setVisibility (View.Gone), a następnie w innym bloku trzeba ustawić to widoczność naprzeciwko wartość jak widget.setVisibility (View.Visible) do przezwyciężyć powyższy problem.

@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

Dodaj setHasStableIds(true); w konstruktora adaptera i zastąpić te dwa methodes w adapterze.

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

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

To zadziałało dla mnie. Czy możesz wyjaśnić, dlaczego to działa? –

+0

Czy możesz podać więcej wyjaśnień na ten temat? – Rino

Powiązane problemy