android - Row background changes due recyclation. getView() implementation doesn't fix this -
i've been looking lot guides, tutorials , answers here on stack, still can't figure 1 out.
i have custom drawable state. if click on row in listview
, gets highlighted , updates information in database. (that task (habit) has been performed). works great until start scrolling. i've learnt, required override getview()
method , getitemviewtype()
getviewtypecount()
.
how this? code habitscursoradapter getview() , other mentioned methods @ moment looks this.
public class habitscursoradapter extends cursoradapter { private layoutinflater inflater; private context context; public static final int performed = 1; public static final int not_performed = 0; public habitscursoradapter(context context, cursor c) { super(context, c, 0); inflater = layoutinflater.from(context); this.context = context; } @override public void bindview(view view, context context, cursor cursor) { string habitname = cursor.getstring(cursor .getcolumnindexorthrow(sqlitehabithelper.column_name)); textview habitnametv = (textview) view.findviewbyid(r.id.habit_name); habitnametv.settext(habitname); /******************* ok ***********************/ imagebutton editbutton = (imagebutton) view.findviewbyid(r.id.habit_edit_button); integer _id = cursor.getint(cursor.getcolumnindexorthrow(sqlitehabithelper.column_id)); editbutton.settag(r.id.edited_habit_id, _id); view.settag(_id); editbutton.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { intent = new intent(habitscursoradapter.this.context, habitdetailactivity.class); i.putextra("_id", (integer) v.gettag(r.id.edited_habit_id)); habitscursoradapter.this.context.startactivity(i); } }); imagebutton deletebutton = (imagebutton) view .findviewbyid(r.id.habit_history_button); // need rewrite deleting button deletebutton.settag(r.id.edited_habit_id, _id); deletebutton.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { //itemized due debugging issue habitlistactivity hla = ((habitlistactivity) habitscursoradapter.this.context); object o = v.gettag(r.id.edited_habit_id); integer = (integer) o; long l = i.longvalue(); hla.delete(l); } }); /******************* ok **********************/ habitlistitemview hv = (habitlistitemview) view; hv.sethabitperformed( (1 == cursor.getint(cursor.getcolumnindexorthrow(sqlitehabithelper.column_performed))) ? true : false ); view.refreshdrawablestate(); } @override public view newview(context context, cursor c, viewgroup container) { habitlistitemview v = (habitlistitemview) inflater.inflate( r.layout.habit_item_layout, container, false); bindview(v, context, c); return v; } @override public int getviewtypecount() { return 2; } @override public int getitemviewtype(int position) { cursor c = (cursor) getitem(position); c.movetoposition(position); int value = c.getint(c.getcolumnindexorthrow(sqlitehabithelper.column_performed)); if(0 != value){ return performed; } return not_performed; } @override public view getview(int position, view convertview, viewgroup parent) { if (!mdatavalid) { throw new illegalstateexception("this should called when cursor valid"); } if (!mcursor.movetoposition(position)) { throw new illegalstateexception("couldn't move cursor position " + position); } view v; if (convertview == null) { v = newview(mcontext, mcursor, parent); return v; } else { mcursor.movetoposition(position); habitlistitemview hv = (habitlistitemview) convertview; int convertviewisperformed = hv.gethabitperformed() ? 1 : 0; int actualitemperformed = getitemviewtype(position); if(actualitemperformed == convertviewisperformed){ v = convertview; bindview(v, mcontext, mcursor); return v; }else{ v = newview(mcontext, mcursor, parent); return v; } } } }
and custom row view is:
public class habitlistitemview extends relativelayout { private static final int[] state_habit_performed = { r.attr.state_habit_performed }; private boolean performed; public habitlistitemview(context context) { this(context, null); } public habitlistitemview(context context, attributeset attributeset) { super(context, attributeset); loadviews(); } public habitlistitemview(context context, attributeset attributeset, int defstyle) { super(context, attributeset, defstyle); loadviews(); } private void loadviews() { setbackgroundresource(r.drawable.habit_list_item_background); } @override protected int[] oncreatedrawablestate(int extraspace) { if (performed) { final int[] drawablestate = super .oncreatedrawablestate(extraspace + 1); mergedrawablestates(drawablestate, state_habit_performed); return drawablestate; } else { return super.oncreatedrawablestate(extraspace); } } public void sethabitperformed(boolean performed) { this.performed = performed; refreshdrawablestate(); } public boolean gethabitperformed() { return performed; } }
and onlistitemclick()
in listfragment
@override public void onlistitemclick(listview l, view v, int position, long id) { super.onlistitemclick(l, v, position, id); habitlistitemview hv = (habitlistitemview) v; contentvalues cv = new contentvalues(); string habitid = v.gettag().tostring(); sqlitedatabase db = dh.getwritabledatabase(); cursor cperfomed = db.query(sqlitehabithelper.table_habit, new string[]{sqlitehabithelper.column_id, sqlitehabithelper.column_performed}, "_id = ?", new string[]{habitid}, null, null, null); cperfomed.movetofirst(); int performed = cperfomed.getint(cperfomed.getcolumnindexorthrow(sqlitehabithelper.column_performed)); cperfomed.close(); cv.put(sqlitehabithelper.column_id, (integer) v.gettag()); cv.put(sqlitehabithelper.column_performed, (performed == 0) ? 1 : 0); db.update(sqlitehabithelper.table_habit, cv, "_id = ?", new string[]{habitid}); db.close(); hv.sethabitperformed((performed == 0) ? true : false); }
a thorough explanation on how , when overriden methods called maybe me resolve issue. presume, newview , bindview called getview, believe can control overriden getview. getitemviewtype , getviewtypecount called methods did not implement , not understand why , how results used. maybe cause problems.
if more code required, i'll edit post according requirements.
any appreciated!
a friend of mine helped me sending me link
android: cursoradapter, listview , checkbox
i tried solution, however, did not work out checkboxes, background color.
i had modify getview() method accordingly:
public view getview(int position, view inview, viewgroup parent) { if (inview == null) { layoutinflater inflater = (layoutinflater) context .getsystemservice(context.layout_inflater_service); inview = inflater.inflate(r.layout.habit_item_layout, null); } habitlistitemview hliv = (habitlistitemview) inview; mcursor.movetoposition(position); bindview(hliv, mcontext, mcursor); hliv.sethabitperformed(habitperformed.get(position)); //line added return inview; }
and add adapter array, store, if should have background green or not.
public arraylist<boolean> habitperformed = new arraylist<boolean>();
and in fragment list in method onlistitemclick() added code modified array accordingly.
if (hv.gethabitperformed()) { adapter.habitperformed.set(position, true); } else if (!hv.gethabitperformed()) { adapter.habitperformed.set(position, false); }
this solved problem.
Comments
Post a Comment