android - ListView "coming back" when scrolling -
i'm getting strange behavior in listview, , 1 listview, have lot of listviews in app, in happening.
i try explain, when scroll bottom, right, scrolls go , stop in end. when scroll top, it's scroll splash in top , come bottom.
i have this video showing problem.
this xml of listview:
<listview android:id="@+id/lv_resultado_produtos" android:layout_width="fill_parent" android:layout_height="fill_parent" android:divider="@color/black" android:dividerheight="1dip" android:fastscrollenabled="true" android:scrollx="0dip" android:scrolly="0dip" android:scrollbarsize="22dip" android:scrollbarstyle="outsideoverlay" />
and programmatically set adapter customadapter, nothing more.
i tested in others listviews , didn't behavior.
i glad if me on this.
[edit]
here adapter, it's little complex, sorry, tried keep have limitation in size of characters:
[package] [imports] public class customadapter_produto_insercao extends arrayadapter<produto_insercao> { static view view_aux = null; static onclicklistener listener_convertview = null; static onclicklistener listener_btn_editar_produto = null; static activity ctx; static dialog_tw ad_estoque; static list<condicao_preco> list_tabela_preco_condicao; public static boolean clickable = true; public static boolean highlight = false; public static int linha_atual = 0; public static view view_atual = null; static boolean id_margem = false; static boolean id_destaca_ipi = false; static string ls_id_tipo_regime; static integer li_cd_cliente; static string caminho_foto; static decimalformat decimalformat = null; static repositorio repositorio; static condicao_preco c_p_null; static boolean innotify = false; private final layoutinflater inflater; private final int resourceid; public void setclickable(boolean b){ clickable = b; } public customadapter_produto_insercao setid_margem(boolean id_margem){ this.id_margem = id_margem; return this; } public customadapter_produto_insercao sethighlight(boolean highlight){ this.highlight = highlight; return this; } public customadapter_produto_insercao setlistener_convertview(onclicklistener listener){ this.listener_convertview = listener; return this; } public customadapter_produto_insercao setlistener_btn_editar_produto(onclicklistener listener){ this.listener_btn_editar_produto = listener; return this; } public customadapter_produto_insercao(activity context, int resource, list<produto_insercao> objects, list<condicao_preco> list_tabela_preco_condicao, string ls_id_tipo_regime, integer li_cd_cliente) { super(context, resource, objects); ctx = context; this.list_tabela_preco_condicao = list_tabela_preco_condicao; this.inflater = layoutinflater.from(context); this.resourceid = resource; this.ls_id_tipo_regime = ls_id_tipo_regime; this.li_cd_cliente = li_cd_cliente; decimalformatsymbols decimalformatsymbols = new decimalformatsymbols(); decimalformatsymbols.setdecimalseparator(','); decimalformatsymbols.setgroupingseparator('.'); decimalformat = new decimalformat("#,##0.00", decimalformatsymbols); repositorio = new repositorio(ctx); string s_id_margem = repositorio.parametro_getvalue("id_margem"); if(s_id_margem != null && s_id_margem.equals("s")){ id_margem = true; } string s_id_destaca_ipi = repositorio.parametro_getvalue("id_destaca_ipi"); if(s_id_destaca_ipi != null && s_id_destaca_ipi.equals("s")){ id_destaca_ipi = true; } for(produto_insercao p_i : objects){ if(p_i.getqt_pedida() == null || p_i.getqt_pedida() == 0d){ p_i.setid_selecionado(false); p_i.setid_tabela_condicao_preco(-1); p_i.setcd_tabela_preco_condicao(-1); } else { p_i.setid_selecionado(true); } } caminho_foto = repositorio.parametro_getvalue("caminho_foto"); c_p_null = new condicao_preco(); c_p_null.setcd_condicao_preco(0); c_p_null.setcd_tabela_preco_condicao(0); c_p_null.setds_condicao_preco("selecione"); c_p_null.setid_promocao("n"); c_p_null.setid_fake(true); } private static class viewholder { public int position; public textview cd_produto; public textview ds_produto; public textview ds_unidade; public button btn_vl_saldo; public spinner spn_tabela_condicao_preco; public textview vl_unidade_unitario; public textview vl_unitario; public button qt_produto_menos; public button qt_produto_mais; public edittext_decimal_tw qt_produto; public textview vl_total; public button btn_editar_produto; public textview vl_custo; public textview pr_ipi; public imagebutton foto_produto; public button mais_opcoes; } @override public void notifydatasetchanged() { innotify = true; boolean b = false; if(view_aux != null && view_aux.ispressed()){ b = true; } super.notifydatasetchanged(); if(b){ view_aux.requestfocus(); view_aux.setpressed(true); view_aux.setselected(true); } innotify = false; } public view getview(final int position, view convertview, viewgroup parent) { final viewholder viewholder; final produto_insercao p = getitem(position); if(p.getcd_tabela_preco_condicao() == -1){ p.setid_selecionado(false); } else { p.setid_selecionado(true); } if (convertview == null) { convertview = inflater.inflate(resourceid, parent, false); viewholder = new viewholder(); viewholder.cd_produto = (textview) convertview.findviewbyid(r.id.cd_produto); viewholder.ds_produto = (textview) convertview.findviewbyid(r.id.ds_produto); viewholder.ds_unidade = (textview) convertview.findviewbyid(r.id.ds_unidade); viewholder.btn_vl_saldo = (button) convertview.findviewbyid(r.id.btn_vl_saldo); viewholder.spn_tabela_condicao_preco = (spinner) convertview.findviewbyid(r.id.spn_tabela_condicao_preco); viewholder.vl_unidade_unitario = (textview) convertview.findviewbyid(r.id.vl_unidade_unitario); viewholder.vl_unitario = (textview) convertview.findviewbyid(r.id.vl_unitario); viewholder.qt_produto_menos = (button) convertview.findviewbyid(r.id.qt_produto_menos); viewholder.qt_produto_mais = (button) convertview.findviewbyid(r.id.qt_produto_mais); viewholder.qt_produto = (edittext_decimal_tw) convertview.findviewbyid(r.id.qt_produto); viewholder.vl_total = (textview) convertview.findviewbyid(r.id.vl_total); viewholder.btn_editar_produto = (button) convertview.findviewbyid(r.id.btn_editar_produto); viewholder.vl_custo = (textview) convertview.findviewbyid(r.id.vl_custo); viewholder.pr_ipi = (textview) convertview.findviewbyid(r.id.pr_ipi); viewholder.foto_produto = (imagebutton) convertview.findviewbyid(r.id.foto_produto); viewholder.mais_opcoes = (button) convertview.findviewbyid(r.id.mais_opcoes); boolean id_mobile_utiliza_valor_unitario = false; string s_id_mobile_utiliza_valor_unitario = repositorio.parametro_getvalue("id_mobile_utiliza_valor_unitario"); if(s_id_mobile_utiliza_valor_unitario != null && s_id_mobile_utiliza_valor_unitario.equals("s")){ id_mobile_utiliza_valor_unitario = true; } if(!id_mobile_utiliza_valor_unitario){ viewholder.vl_unidade_unitario.setlayoutparams(new linearlayout.layoutparams(0, 0)); linearlayout.layoutparams ll = new linearlayout.layoutparams(0, linearlayout.layoutparams.wrap_content, 13); viewholder.mais_opcoes.setlayoutparams(ll); } else { linearlayout.layoutparams ll = new linearlayout.layoutparams(0, linearlayout.layoutparams.wrap_content, 15); viewholder.mais_opcoes.setlayoutparams(ll); } convertview.settag(viewholder); } else { viewholder = (viewholder) convertview.gettag(); } repeater qt_produto_menos_repeater = new repeater(viewholder.qt_produto_menos); viewholder.qt_produto_menos.setonlongclicklistener(qt_produto_menos_repeater); repeater qt_produto_mais_repeater = new repeater(viewholder.qt_produto_mais); viewholder.qt_produto_mais.setonlongclicklistener(qt_produto_mais_repeater); if(p.isid_liberado()){ viewholder.mais_opcoes .setvisibility(view.gone); viewholder.qt_produto_menos .setvisibility(view.visible); viewholder.qt_produto_mais .setvisibility(view.visible); viewholder.qt_produto .setvisibility(view.visible); viewholder.spn_tabela_condicao_preco.setvisibility(view.visible); viewholder.vl_unidade_unitario .setvisibility(view.visible); viewholder.vl_unitario .setvisibility(view.visible); viewholder.vl_total .setvisibility(view.visible); viewholder.btn_editar_produto .setvisibility(view.visible); } else { viewholder.mais_opcoes .setvisibility(view.visible); viewholder.qt_produto_menos .setvisibility(view.gone); viewholder.qt_produto_mais .setvisibility(view.gone); viewholder.qt_produto .setvisibility(view.gone); viewholder.spn_tabela_condicao_preco.setvisibility(view.gone); viewholder.vl_unidade_unitario .setvisibility(view.gone); viewholder.vl_unitario .setvisibility(view.gone); viewholder.vl_total .setvisibility(view.gone); viewholder.btn_editar_produto .setvisibility(view.gone); p.setid_liberado(false); } viewholder.mais_opcoes.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { p.setid_liberado(true); notifydatasetchanged(); } }); viewholder.position = position; if(!innotify) new myasynctask(position, viewholder, convertview, p, this).executeonexecutor(asynctask.thread_pool_executor, null); if(p.getqt_pedida() != null && p.getqt_pedida() > 0d){ convertview.setbackgroundresource(r.color.duapi_pressed); } else { convertview.setbackgroundresource(r.color.whitesmoke); } if(p.getvl_saldo() != null && p.getvl_saldo() > 0d){ viewholder.cd_produto .settextcolor(color.black); viewholder.ds_produto .settextcolor(color.black); viewholder.ds_unidade .settextcolor(color.black); viewholder.btn_vl_saldo .settextcolor(color.black); } else { viewholder.cd_produto .settextcolor(color.red); viewholder.ds_produto .settextcolor(color.red); viewholder.ds_unidade .settextcolor(color.red); viewholder.btn_vl_saldo .settextcolor(color.red); } if(highlight && position == linha_atual){ convertview.setbackgroundresource(r.color.duapi); } else { convertview.setbackgroundresource(r.drawable.listview_background); } return convertview; } private static class myasynctask extends asynctask { private int position; private viewholder viewholder; private view convertview; private produto_insercao p; private list<condicao_preco> lista_tabela_preco_condicao; private customadapter_produto_insercao madapter; private spinneradapter_condicao_preco adapter; public myasynctask(int position, viewholder viewholder, view convertview, produto_insercao p, customadapter_produto_insercao madapter) { this.position = position; this.viewholder = viewholder; this.convertview = convertview; this.p = p; this.madapter = madapter; lista_tabela_preco_condicao = new arraylist<condicao_preco>(); } @override protected object doinbackground(object... params) { if(p.isid_liberado()){ viewholder.btn_editar_produto.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { linha_atual = position; view_atual = convertview; if(listener_btn_editar_produto != null){ listener_btn_editar_produto.onclick(v); } } }); viewholder.qt_produto_menos.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { view_aux = viewholder.qt_produto_menos; double qt_anterior = viewholder.qt_produto.getvalor_double(); viewholder.qt_produto.setvalor(viewholder.qt_produto.getvalor_double() - p.getfator_venda()); //verifica se o produto não está na lista de itens pedido, se tiver não deixa zerar... if(pedidotabactivity2.find_produto_em_itens(p.getcd_produto())){ if(viewholder.qt_produto.getvalor_double() <= 0d){ viewholder.qt_produto.setvalor(qt_anterior); return; } } if(viewholder.qt_produto.getvalor_double() < 0d){ viewholder.qt_produto.setvalor(0d); } p.setqt_pedida(viewholder.qt_produto.getvalor_double()); calculainformacoes(false); if(!atualizaflex(p, 30)){ viewholder.qt_produto.setvalor(qt_anterior); p.setqt_pedida(qt_anterior); atualizaflex(p, 10); calculainformacoes(false); return; } } }); viewholder.qt_produto_mais.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { view_aux = viewholder.qt_produto_menos; double qt_anterior = viewholder.qt_produto.getvalor_double(); viewholder.qt_produto.setvalor(viewholder.qt_produto.getvalor_double() + p.getfator_venda()); p.setqt_pedida(viewholder.qt_produto.getvalor_double()); calculainformacoes(false); if(!atualizaflex(p, 30)){ viewholder.qt_produto.setvalor(qt_anterior); p.setqt_pedida(qt_anterior); atualizaflex(p, 10); calculainformacoes(false); return; } } }); lista_tabela_preco_condicao.add(c_p_null); lista_tabela_preco_condicao.addall(list_tabela_preco_condicao); if(p.getid_promocao() < 1){ for(int = 0; < lista_tabela_preco_condicao.size(); i++){ if(lista_tabela_preco_condicao.get(i).getid_promocao().equals("s")){ lista_tabela_preco_condicao.remove(i--); } } } onitemselectedlistener onitemselectedlistener = new onitemselectedlistener() { @override public void onitemselected(adapterview<?> arg0, view arg1, int arg2, long arg3) { selection(arg2); } @override public void onnothingselected(adapterview<?> arg0) { } }; viewholder.spn_tabela_condicao_preco.setonitemselectedlistener(onitemselectedlistener); adapter = new spinneradapter_condicao_preco(ctx, android.r.layout.simple_spinner_item, lista_tabela_preco_condicao, ls_id_tipo_regime, p.getcd_tabela_preco(), p.getcd_produto(), li_cd_cliente); adapter.setdropdownviewresource(android.r.layout.simple_spinner_dropdown_item); } convertview.setonclicklistener(new onclicklistener() { public void onclick(view v) { if(!clickable){ return ; } linha_atual = position; view_atual = convertview; if(listener_convertview != null){ listener_convertview.onclick(v); } p.setid_liberado(true); madapter.notifydatasetchanged(); } }); viewholder.btn_vl_saldo.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { if(ad_estoque != null){ return ; } ad_estoque = new dialog_tw(ctx); final dialog_tw ad_estoque_temp = ad_estoque; ad_estoque.setview(r.layout.layout_pedido_venda_tab_insercao_estoque); ad_estoque.settitle("consulta de estoque"); ad_estoque.setcancelable(false); view view_estoque = ad_estoque.getview(); textview ds_produto = (textview) view_estoque.findviewbyid(r.id.ds_produto); button btn_ok = (button) view_estoque.findviewbyid(r.id.btn_ok); listview lv_resultado = (listview) view_estoque.findviewbyid(r.id.lv_resultado); textview vl_total = (textview) view_estoque.findviewbyid(r.id.vl_total); ds_produto.settext(p.tostring()); btn_ok.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { ad_estoque_temp.getdialog(false, 50d).dismiss(); } }); ad_estoque.setondismisslistener(new ondismisslistener() { @override public void ondismiss(dialoginterface dialog) { ad_estoque = null; if(customadapter_pedido_venda_pendente_item_rascunho.editar){ customadapter_pedido_venda_pendente_item_rascunho.editar = false; } } }); repositorio repositorio = new repositorio(ctx); list<saldo_estoque> lista_saldo_estoque = repositorio.generic_getlist(saldo_estoque.class, "cd_produto = '" + p.getcd_produto() + "'", null, null, null, "cd_empresa asc", false); double total = 0d; for(saldo_estoque s_e : lista_saldo_estoque){ list<empresa> lista_empresa = repositorio.generic_getlist(empresa.class, "cd_empresa = '" + s_e.getcd_empresa() + "'", null, null, null, null, false); empresa e = null; if(lista_empresa != null && lista_empresa.size() > 0){ e = lista_empresa.get(0); s_e.setnm_reduzido(e.getnm_reduzido()); } total += s_e.getqt_disponivel(); } vl_total.settext(decimalformat.format(total)); customadapter_estoque adapter_estoque = new customadapter_estoque(ctx, r.layout.layout_pedido_venda_tab_insercao_estoque_lista, lista_saldo_estoque).sethighlight(true); lv_resultado.setadapter(adapter_estoque); ad_estoque.getdialog(false, 50d).show(); } }); return null; } @override protected void onpostexecute(object result) { if(id_margem){ viewholder.vl_custo.setvisibility(view.visible); viewholder.vl_custo.settext(p.getvl_custo_unitario() == null ? "-" : decimalformat.format(p.getvl_custo_unitario())); } if(id_destaca_ipi){ viewholder.pr_ipi.setvisibility(view.visible); viewholder.pr_ipi.settext(decimalformat.format(p.getpr_ipi())); } if(caminho_foto != null && p.getid_foto() != null && p.getid_foto().equals("s")){ viewholder.foto_produto.setvisibility(view.visible); viewholder.foto_produto.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { util.carregar_foto_produto(p.getcd_produto(), p.getds_produto(), p.getnm_foto(), ctx); } }); } viewholder.cd_produto .settext(p.getcd_produto()); viewholder.ds_produto .settext(p.getds_produto()); viewholder.ds_unidade .settext(p.getds_unidade_unitaria()); viewholder.btn_vl_saldo.settext(decimalformat.format(p.getvl_saldo())); if(p.isid_liberado()){ if(p.isid_selecionado()){ unidade u = null; list<unidade> lista_unidade = repositorio.generic_getlist(unidade.class, "cd_unidade = " + p.getcd_unidade_embalagem(), null, null, null, null, false); if(lista_unidade != null && lista_unidade.size() > 0){ u = lista_unidade.get(0); } double vl_unidade_unitario = util.rounddouble(p.getvl_unitario() / (u != null ? u.getfator_conversao() : 1), 2); viewholder.vl_unidade_unitario.settext(decimalformat.format(vl_unidade_unitario)); viewholder.vl_unitario.settext(decimalformat.format(p.getvl_unitario())); viewholder.vl_total .settext(decimalformat.format(p.getvl_total())); } else { viewholder.vl_unidade_unitario.settext(" - "); viewholder.vl_unitario .settext(" - "); viewholder.vl_total .settext(" - "); } viewholder.qt_produto.setvalor(p.getqt_pedida() == null ? 0d : p.getqt_pedida()); viewholder.spn_tabela_condicao_preco.setadapter(adapter); if(lista_tabela_preco_condicao.size() > 1){ viewholder.spn_tabela_condicao_preco.setenabled(true); } else { viewholder.spn_tabela_condicao_preco.setenabled(false); } if(p.isid_selecionado()){ viewholder.spn_tabela_condicao_preco.setselection(find_condicao_preco_position(lista_tabela_preco_condicao, p.getcd_tabela_preco_condicao())); } else { viewholder.spn_tabela_condicao_preco.setselection(0); } if(lista_tabela_preco_condicao == null || lista_tabela_preco_condicao.size() < 2){ viewholder.btn_editar_produto.setenabled(false); } else { viewholder.btn_editar_produto.setenabled(true); } if(!p.isid_selecionado() && lista_tabela_preco_condicao.size() == 3){ adapter.getdropdownview(2, null, null); viewholder.spn_tabela_condicao_preco.setselection(2); } } convertview.setclickable(true); convertview.setfocusable(true); } private double calculainformacoes_getvl_unitario(){ [only calculates values] } private void calculainformacoes(boolean calcula_preco){ [only calculates values] } private boolean atualizaflex(produto_insercao p_i, int operacao) { [only calculates values] } public condicao_preco find_condicao_preco(list<condicao_preco> lista, integer cd_tabela_preco_condicao){ for(condicao_preco c_p : lista){ if(c_p.getcd_tabela_preco_condicao().equals(cd_tabela_preco_condicao)){ return c_p; } } return null; } public integer find_condicao_preco_position(list<condicao_preco> lista, integer cd_tabela_preco_condicao){ for(int = 0; < lista.size(); i++){ condicao_preco c_p = lista.get(i); if(c_p.getcd_tabela_preco_condicao().equals(cd_tabela_preco_condicao)){ return i; } } return null; } public void selection(integer arg2){ if(arg2 > 0){ condicao_preco c_p = find_condicao_preco(lista_tabela_preco_condicao, p.getcd_tabela_preco_condicao()); condicao_preco c_p_aux = lista_tabela_preco_condicao.get(arg2); if(c_p == null || !c_p.getcd_tabela_preco_condicao().equals(c_p_aux.getcd_tabela_preco_condicao())){ if(p.getid_gera_flex().equals("s") && c_p_aux.getds_condicao_preco().equals("Última venda")){ if(c_p_aux.getds_condicao_preco().equals("Última venda")){ util.messagedialog_ok(ctx, ctx.getresources().getstring(r.string.titulo_dialog_padrao), "produto que gera flex não pode ser selecionado 'Última venda'.", util.icone_information); } p.setcd_tabela_preco_condicao(p.getcd_tabela_preco_condicao()); madapter.notifydatasetchanged(); return; } if(c_p_aux.getvl_valor() != null){ p.setcd_tabela_preco_condicao(c_p_aux.getcd_tabela_preco_condicao()); p.setid_selecionado(true); calculainformacoes(true); } else { util.messagedialog_ok(ctx, ctx.getresources().getstring(r.string.titulo_dialog_padrao), "não foi possível encontrar última venda deste item para este cliente.", util.icone_information); p.setcd_tabela_preco_condicao(p.getcd_tabela_preco_condicao()); madapter.notifydatasetchanged(); } } } else { p.setcd_tabela_preco_condicao(-1); p.setid_selecionado(false); calculainformacoes(true); } } } }
kind regards,
william bertan
couple of things:
1) asynctask super buggy. first, it's triggered - static variable never true when you're in getview
- main thread can't both in notifydatasetchanged
, getview
@ same time! more importantly, you're changing views
off main thread , bad, bad, bad. it's riddled race conditions, both against own code , against framework. has redone touch views in onpostexecute
2) code in notifydatasetchanged()
seems flaky - you're holding reference view if click , scroll before onclick listener gets executed view may no longer on screen. it's rare case, granted, in general avoid @ costs running holding references of listview items or subviews. that's bound cause trouble and/or memory leaks (especially in case reference static!).
i'm not sure exact cause of bug but, if had guess, i'd it's viewaux.setpressed/setselected/requestfocus
lines. specifically, requestfocus
super suspicious - android scrolls scrolling containers in window put focused view in visible area.
3) remove android:scrollx
, scrolly
listview - i'm pretty sure don't if do, it's wrong thing.
Comments
Post a Comment