android - RecyclerView causes issue when recycling -


i have list of item created using recyclerview. when user clicks on 1 of them change background color of selected item. problem is, when scroll through items, , recycled, of items selected item's background color (which wrong). here can see adapter's code:

public class orderadapter extends recyclerview.adapter<orderadapter.viewholder> {  private static final string selected_color = "#ffedcc";  private list<ordermodel> morders;  public orderadapter() {     this.morders = new arraylist<>(); }  public void setorders(list<ordermodel> orders) {     morders = orders; }  public void addorders(list<ordermodel> orders) {     morders.addall(0, orders); }  public void addorder(ordermodel order) {     morders.add(0, order); }  @override public viewholder oncreateviewholder(viewgroup parent, int viewtype) {     context context = parent.getcontext();     layoutinflater inflater = layoutinflater.from(context);      // inflate custom layout     view contactview = inflater.inflate(r.layout.order_main_item, parent, false);      // return new holder instance     viewholder viewholder = new viewholder(contactview);     return viewholder; }  @override public void onbindviewholder(final viewholder viewholder, final int position) {     final ordermodel ordermodel = morders.get(position);      // set item views based on data model     textview customername = viewholder.customernametext;      simpledateformat simpledateformat = new simpledateformat("mm/dd/yyyy'   'hh:mm:ss:s");     string time = simpledateformat.format(ordermodel.getordertime());     customername.settext(time);      textview ordernumber = viewholder.ordernumbertext;     ordernumber.settext("order no: " + ordermodel.getordernumber());      button button = viewholder.acceptbutton;     button.setonclicklistener(new view.onclicklistener() {         @override         public void onclick(view v) {             viewholder.useractions.acceptbuttonclicked(position);         }     });      final linearlayout orderitem = viewholder.orderitem;     orderitem.setonclicklistener(new view.onclicklistener() {         @override         public void onclick(view v) {             viewholder.useractions.itemclicked(ordermodel);             viewholder.orderitem.setbackgroundcolor(color.parsecolor(selected_color));         }     }); }  @override public int getitemcount() {     return morders.size(); }   public static class viewholder extends recyclerview.viewholder implements ordercontract.view {      public textview customernametext;     public button acceptbutton;     public textview ordernumbertext;     public ordercontract.useractions useractions;     public linearlayout orderitem;      public viewholder(view itemview) {         super(itemview);          useractions = new orderpresenter(this);          customernametext = (textview) itemview.findviewbyid(r.id.customer_name);         acceptbutton = (button) itemview.findviewbyid(r.id.accept_button);         ordernumbertext = (textview) itemview.findviewbyid(r.id.order_number);         orderitem = (linearlayout) itemview.findviewbyid(r.id.order_item_selection);     }      @override     public void removeitem() {      } } 

the problem recyclerview recycling behavior assign out of screen viewholder items new items coming displayed on screen. not suggest bind logic based on viewholder object in above answers. cause problem. should build logic based on state of data object not viewholder object never know when gets recycled.

suppose save state boolean isselected in viewholder check, , if true, same state there new item when viewholder recycled.

better way above holding state in datamodel object. in case boolean isselected.

sample example like

package chhimwal.mahendra.multipleviewrecyclerproject;  import android.content.context; import android.support.v7.widget.recyclerview; import android.view.layoutinflater; import android.view.view; import android.view.viewgroup; import android.support.v7.widget.cardview; import android.widget.textview;  import java.util.list;  /**  * created mahendra.chhimwal on 12/10/2015.  */ public class myrecyclerviewadapter extends recyclerview.adapter<myrecyclerviewadapter.viewholder> {      private context mcontext;     private list<datamodel> mrviewdatalist;       public myrecyclerviewadapter(context context, list<datamodel> rviewdatalist) {         this.mcontext = context;         this.mrviewdatalist = rviewdatalist;     }      @override     public myrecyclerviewadapter.viewholder oncreateviewholder(viewgroup parent, int viewtype) {         layoutinflater inflater = layoutinflater.from(parent.getcontext());         view view = inflater.inflate(r.layout.item_recycler_view, parent, false);         return new viewholder(view);     }      @override     public void onbindviewholder(viewholder holder, int position) {         holder.binddatawithviewholder(mrviewdatalist.get(position));     }      @override     public int getitemcount() {         return mrviewdatalist != null ? mrviewdatalist.size() : 0;     }       public class viewholder extends recyclerview.viewholder {         private textview textview;         private linearlayout llview;         private datamodel mdataitem=null;          public viewholder(view itemview) {             super(itemview);             llview=(linearlayout)itemview.findviewbyid(r.id.ll_root_view);             textview = (textview) itemview.findviewbyid(r.id.tvitemname);             cvitemview.setonclicklistener(new view.onclicklistener() {                 @override                 public void onclick(view v) {                   // 1 should handle onclick of event here based on dataitem i.e. mdataitem in case.                   // that..                 /* intent intent = new intent(mcontext,resultactivity.class);                  intent.putextra("my_data",mdataitem);   //if want pass data.                  intent.putextra("clicked_item_postion",getadapterposition()); // if 1 want selected item position                  startactivity(intent);*/                  toast.maketext(mcontext,"you clicked item number "+viewholder.this.getadapterposition(),toast.lenth_short).show();                 }             });         }          //this clean method bind data viewholder. dirty things on view based on dataitem.         //must called onbindviewholder(),with dataitem. in our case dataitem string object.         public void binddatawithviewholder(datamodel dataitem){             this.mdataitem=dataitem;              if(mdataitem.isselected()){                 llview.setbackgroundcolor(color.parsecolor(selcted_color);             }else{                 llview.setbackgroundcolor(color.parsecolor(default_color);             }             //other view binding logics setting text , loading image  etc.             textview.settext(mdataitem);         }     } } 

as @gabriel asked in comment,

what if 1 want select single item @ time?

in case, again 1 should not save selected item state in viewholder object, same gets recycled , cause problem. better way have field int selecteditemposition in adapter class not viewholder . following code snippet show it.

public class myrecyclerviewadapter extends recyclerview.adapter<myrecyclerviewadapter.viewholder> {            private context mcontext;         private list<datamodel> mrviewdatalist;          //variable hold selected item position         private int mselecteditemposition = -1;           public myrecyclerviewadapter(context context, list<datamodel> rviewdatalist) {             this.mcontext = context;             this.mrviewdatalist = rviewdatalist;         }          @override         public myrecyclerviewadapter.viewholder oncreateviewholder(viewgroup parent, int viewtype) {             layoutinflater inflater = layoutinflater.from(parent.getcontext());             view view = inflater.inflate(r.layout.item_recycler_view, parent, false);             return new viewholder(view);         }          @override         public void onbindviewholder(viewholder holder, int position) {             holder.binddatawithviewholder(mrviewdatalist.get(position),position);         }          @override         public int getitemcount() {             return mrviewdatalist != null ? mrviewdatalist.size() : 0;         }           public class viewholder extends recyclerview.viewholder {             private textview textview;             private linearlayout llview;             private datamodel mdataitem=null;              public viewholder(view itemview) {                 super(itemview);                 llview=(linearlayout)itemview.findviewbyid(r.id.ll_root_view);                 textview = (textview) itemview.findviewbyid(r.id.tvitemname);                 cvitemview.setonclicklistener(new view.onclicklistener() {                     @override                     public void onclick(view v) {                         //handling background selection state changed                         int previousselectstate=mselecteditemposition;                         mselecteditemposition = getadapterposition();                         //notify previous selected item                         notifyitemchanged(previousselectstate);                         //notify new selected item                         notifyitemchanged(mselecteditemposition);                          //your other handling in onclick                      }                 });             }              //this clean method bind data viewholder. dirty things on view based on dataitem.             //must called onbindviewholder(),with dataitem. in our case dataitem string object.             public void binddatawithviewholder(datamodel dataitem, int currentposition){                 this.mdataitem=dataitem;                 //handle selection  state in object view.                 if(currentposition == mselecteditemposition){                     llview.setbackgroundcolor(color.parsecolor(selcted_color);                 }else{                     llview.setbackgroundcolor(color.parsecolor(default_color);                 }                 //other view binding logics setting text , loading image  etc.                 textview.settext(mdataitem);             }         }     } 

if have maintain selected item state, discourage use of notifydatasetchanged() method of adapter class recyclerview provides more flexibility these cases.


Comments

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -