i'm trying implement action mode delete items within firebaserecyclerview. weird thing deleted items not selected items. i'm think error in toogleselection method or removeitems method, i'm don't know is.
the adapter code:
public class newsadapter extends firebaserecycleradapter<noticia, noticiasviewholder> { private int color; private int selectedcolor; private noticiasfragment fragment; private final globals globals; private actionmode actionmode; private final simpledateformat dateformat = new simpledateformat("dd/mm/yyyy"); private sparseintarray selecteditems = new sparseintarray(); public newsadapter(noticiasfragment fragment, query ref) { super(noticia.class, r.layout.list_item_noticia, noticiasviewholder.class, ref); this.color = contextcompat.getcolor(fragment.getactivity(), r.color.background_card); this.selectedcolor = contextcompat.getcolor(fragment.getactivity(), r.color.background_selected); this.globals = (globals) fragment.getactivity().getapplicationcontext(); this.fragment = fragment; } @override protected void populateviewholder(noticiasviewholder viewholder, final noticia model, final int position) { viewholder.imageview.setimageurl(model.linkimg, globals.getimageloader()); viewholder.bindtonoticia(fragment.getactivity(), model, dateformat); final databasereference noticiaref = getref(position); viewholder.itemview.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { if (getselecteditemcount()>0) { if (toggleselection(position)) { v.setbackgroundcolor(selectedcolor); } else { v.setbackgroundcolor(color); if (getselecteditemcount()==0 && actionmode!=null) { actionmode.finish(); } } return; } if (!server.isonline(fragment.getactivity(), r.string.sem_conexao_noticia)) return; intent = new intent(fragment.getactivity(), newsactivity.class); i.putextra("noticia", model); fragment.startactivity(i); } }); viewholder.itemview.setonlongclicklistener(new view.onlongclicklistener() { @override public boolean onlongclick(view v) { if (toggleselection(position)) { v.setbackgroundcolor(selectedcolor); if (actionmode != null) return true; toolbar toolbar = (toolbar) fragment.getactivity().findviewbyid(r.id.toolbar); actionmode = toolbar.startactionmode(mactionmodecallback); actionmode.settitle("1 selecionado"); } else { v.setbackgroundcolor(color); if (getselecteditemcount() == 0 && actionmode != null) { actionmode.finish(); } } return true; } }); if (selecteditems.get(position)!=0) viewholder.itemview.setbackgroundcolor(selectedcolor); else viewholder.itemview.setbackgroundcolor(color); } /* returns selected items count */ public int getselecteditemcount() { return selecteditems.size(); } /* select/unselect deletion */ public boolean toggleselection(int position) { boolean b; if (selecteditems.get(position)!=0) { selecteditems.delete(position); b = false; } else { selecteditems.put(position, position); b = true; } int n = getselecteditemcount(); if (n>0 && actionmode!=null) { actionmode.settitle(string.valueof(n) + (n==1 ? " selecionado" : " selecionados")); } return b; } /* action delete selected items */ private void removeitems() { string userid = fragment.getuid(); while (selecteditems.size()>0) { int position = selecteditems.keyat(0); databasereference noticiaref = getref(position); fragment.mdatabase.child("user-news").child(userid).child(noticiaref.getkey()).removevalue(); selecteditems.removeat(0); } } private actionmode.callback mactionmodecallback = new actionmode.callback() { @override public boolean oncreateactionmode(actionmode actionmode, menu menu) { menuinflater inflater = actionmode.getmenuinflater(); inflater.inflate(r.menu.menu_delete_noticias, menu); toolbar toolbar = (toolbar) fragment.getactivity().findviewbyid(r.id.toolbar); toolbar.setbackgroundcolor(contextcompat.getcolor(fragment.getactivity(), r.color.accent2)); tablayout tablayout = (tablayout) fragment.getactivity().findviewbyid(r.id.sliding_tabs); tablayout.setbackgroundcolor(contextcompat.getcolor(fragment.getactivity(), r.color.accent2)); final globals globals = (globals) fragment.getactivity().getapplicationcontext(); globals.isinactionmode = true; ((mainactivity) fragment.getactivity()).updatepage(0); if (build.version.sdk_int >= build.version_codes.lollipop) { window window = (fragment.getactivity()).getwindow(); window.addflags(windowmanager.layoutparams.flag_draws_system_bar_backgrounds); window.setstatusbarcolor(contextcompat.getcolor(fragment.getactivity(), r.color.accent3)); } return true; } @override public boolean onprepareactionmode(actionmode actionmode, menu menu) { return false; } @override public boolean onactionitemclicked(final actionmode actionmode, menuitem menuitem) { switch (menuitem.getitemid()) { case r.id.menu_main_delete_noticias: new sweetalertdialog(fragment.getcontext(), sweetalertdialog.warning_type) .settitletext(fragment.getresources().getstring(r.string.excluir_noticias)) .setcontenttext(fragment.getresources().getstring(r.string.excluir_noticias_message)) .setcanceltext(fragment.getresources().getstring(r.string.btn_nao_excluir)) .setconfirmtext(fragment.getresources().getstring(r.string.btn_sim_excluir)) .showcancelbutton(true) .setcancelclicklistener(new sweetalertdialog.onsweetclicklistener() { @override public void onclick(sweetalertdialog sdialog) { actionmode.finish(); sdialog.cancel(); } }) .setconfirmclicklistener(new sweetalertdialog.onsweetclicklistener() { @override public void onclick(sweetalertdialog sdialog) { /* execute deletion */ removeitems(); actionmode.finish(); sdialog .settitletext(fragment.getresources().getstring(r.string.noticias_excluidas)) .setcontenttext(fragment.getresources().getstring(r.string.noticias_excluidas_message)) .setconfirmtext(fragment.getresources().getstring(r.string.btn_ok)) .showcancelbutton(false) .setconfirmclicklistener(null) .changealerttype(sweetalertdialog.success_type); } }) .show(); return true; default: return false; } } @override public void ondestroyactionmode(actionmode amode) { fragment.getactivity().findviewbyid(r.id.action_mode_bar).setvisibility(view.invisible); toolbar toolbar = (toolbar) fragment.getactivity().findviewbyid(r.id.toolbar); toolbar.setbackgroundcolor(contextcompat.getcolor(fragment.getactivity(), r.color.primary)); tablayout tablayout = (tablayout) fragment.getactivity().findviewbyid(r.id.sliding_tabs); tablayout.setbackgroundcolor(contextcompat.getcolor(fragment.getactivity(), r.color.primary)); final globals globals = (globals) fragment.getactivity().getapplicationcontext(); globals.isinactionmode = false; ((mainactivity) fragment.getactivity()).selectpage(3); if (build.version.sdk_int >= build.version_codes.lollipop) { window window = fragment.getactivity().getwindow(); window.addflags(windowmanager.layoutparams.flag_draws_system_bar_backgrounds); window.setstatusbarcolor(contextcompat.getcolor(fragment.getactivity(), r.color.primarydark)); } selecteditems.clear(); notifydatasetchanged(); actionmode = null; } }; }
edit:
seems me index positions firebaserecyclerview not updated immediatly after remotions. realized that, if have 20 items , delete first 15 items, , if try delete new first one, following error:
08-01 21:12:35.816 10747-10747/com.doeal.doeal e/androidruntime: fatal exception: main process: com.doeal.doeal, pid: 10747 java.lang.indexoutofboundsexception: invalid index 15, size 5 @ java.util.arraylist.throwindexoutofboundsexception(arraylist.java:255) @ java.util.arraylist.get(arraylist.java:308) @ com.firebase.ui.database.firebasearray.getitem(firebasearray.java:52) @ com.firebase.ui.database.firebaserecycleradapter.getref(firebaserecycleradapter.java:150) @ com.doeal.doeal.adapters.noticiasadapter.removeitems(noticiasadapter.java:187) @ com.doeal.doeal.adapters.noticiasadapter.access$700(noticiasadapter.java:43) @ com.doeal.doeal.adapters.noticiasadapter$4$1.onclick(noticiasadapter.java:248) @ cn.pedant.sweetalert.sweetalertdialog.onclick(sweetalertdialog.java:372) @ android.view.view.performclick(view.java:5201) @ android.view.view$performclick.run(view.java:21163) @ android.os.handler.handlecallback(handler.java:746) @ android.os.handler.dispatchmessage(handler.java:95) @ android.os.looper.loop(looper.java:148) @ android.app.activitythread.main(activitythread.java:5443) @ java.lang.reflect.method.invoke(native method) @ com.android.internal.os.zygoteinit$methodandargscaller.run(zygoteinit.java:728) @ com.android.internal.os.zygoteinit.main(zygoteinit.java:618)
i tried execute notifydatasetchanged rebuild indexes, has no effect.
i found issue, that's mistake. in populateviewholder method, passing int position instead reference key onclicklistener , onlongclicklistener events. more relevant changes are:
private map<string, string> selecteditems = new hashmap<>();
...
viewholder.itemview.setonlongclicklistener(new view.onlongclicklistener() { @override public boolean onlongclick(view v) { if (toggleselection(noticiaref.getkey())) { v.setbackgroundcolor(selectedcolor); if (actionmode != null) return true; toolbar toolbar = (toolbar) fragment.getactivity().findviewbyid(r.id.toolbar); actionmode = toolbar.startactionmode(mactionmodecallback); actionmode.settitle("1 selecionado"); } else { v.setbackgroundcolor(color); if (getselecteditemcount() == 0 && actionmode != null) { actionmode.finish(); } } return true; } });
...
public boolean toggleselection(string key) { boolean b; if (selecteditems.get(key)!=null) { selecteditems.remove(key); b = false; } else { selecteditems.put(key, key); b = true; } int n = getselecteditemcount(); if (n>0 && actionmode!=null) { actionmode.settitle(string.valueof(n) + (n==1 ? " selecionado" : " selecionados")); } return b; } private void removeitems() { string userid = fragment.getuid(); iterator iterator = selecteditems.keyset().iterator(); while(iterator.hasnext()) { string key=(string) iterator.next(); fragment.mdatabase.child("user-news").child(userid).child(key).removevalue(); } selecteditems.clear(); }
Comments
Post a Comment