Obviamente, você deve usar threads separados para ações de longa duração (como carregar dados da Web) e pode indicar progresso no último item da lista (como o mercado ou os aplicativos do Gmail).
huh, isso não ativaria o tamanho do adaptador se você parasse de rolar no meio da tela? ele deve carregar apenas os próximos 10 quando realmente chegar ao final da lista.
Matthias
9
Percebo muitos exemplos como este usando o BaseAdapter. Queria mencionar que, se você estiver usando um banco de dados, tente usar um SimpleCursorAdapter. Quando você precisar adicionar à lista, atualize seu banco de dados, obtenha um novo cursor e use SimpleCursorAdapter # changeCursor junto com notifyDataSetChanged. Não é necessária nenhuma subclasse e ele tem um desempenho melhor que um BaseAdapter (novamente, apenas se você estiver usando um banco de dados).
brack
1
Depois de chamar notifyDataSetChanged (), ele ficará no topo da lista, como posso evitá-lo?
desenhar
2
Uma observação - usei essa abordagem, mas precisava adicionar uma verificação de quando visibleCount é 0. Para cada lista, recebo um retorno de chamada no onScroll onde firstVisible, visibleCount e totalCount são todos 0, o que tecnicamente atende ao condicional, mas não é quando eu quero carregar mais.
Eric moinho
5
Outro problema com esse código é que a condição firstVisible + visibleCount >= totalCounté atendida várias vezes com várias chamadas para o ouvinte. Se a função carregar mais for uma solicitação da Web (provavelmente será), adicione outra verificação para verificar se uma solicitação está em andamento ou não. Por outro lado, verifique se o totalCount não é igual à contagem total anterior, porque não precisamos de várias solicitações para o mesmo número de itens na lista.
Subin Sebastian
94
Só queria contribuir com uma solução que eu usei para o meu aplicativo.
Também é baseado na OnScrollListenerinterface, mas achei que ele tinha um desempenho de rolagem muito melhor em dispositivos low-end, pois nenhum dos cálculos de contagem total / visível é realizado durante as operações de rolagem.
Deixe seu ListFragmentou ListActivityimplementeOnScrollListener
Adicione os seguintes métodos a essa classe:
@Overridepublicvoid onScroll(AbsListView view,int firstVisibleItem,int visibleItemCount,int totalItemCount){//leave this empty}@Overridepublicvoid onScrollStateChanged(AbsListView listView,int scrollState){if(scrollState == SCROLL_STATE_IDLE){if(listView.getLastVisiblePosition()>= listView.getCount()-1- threshold){
currentPage++;//load more list items:
loadElements(currentPage);}}}
onde currentPageé a página da sua fonte de dados que deve ser adicionada à sua lista e thresholdo número de itens da lista (contados no final) que, se visíveis, acionam o processo de carregamento. Se você definir thresholda 0, por exemplo, o usuário tem que rolar até o fim da lista, a fim de carregar mais itens.
(opcional) Como você pode ver, a "verificação de carregar mais" é chamada apenas quando o usuário para de rolar. Para melhorar a usabilidade, você pode aumentar e adicionar um indicador de carregamento ao final da lista via listView.addFooterView(yourFooterView). Um exemplo para essa visualização de rodapé:
Eu tentei isso, mas não funciona para ListFragment. Como ele pode ser usado no ListFragment.
21413 z133:
Bem, eu também o uso ListFragmentsem problemas - basta seguir cada uma das etapas acima e você ficará bem;) Ou você poderia fornecer alguma mensagem de erro?
note: adicionar e remover rodapé no listview é problemático (o rodapé não aparece se setAdapter é chamado antes de adicionar o rodapé). Acabei modificando a visibilidade da exibição do rodapé diretamente, sem removê-lo.
Dvd
O que deve ser adicionado no loadElements (currentPage) ??? Quero dizer, eu chamo meu AsyncTask ou um thread?
android_developer 28/11
20
Você pode detectar o final da lista com a ajuda de onScrollListener , o código de trabalho é apresentado abaixo:
Outra maneira de fazer isso (adaptador interno) é a seguinte:
publicView getView(int pos,View v,ViewGroup p){if(pos==getCount()-1){
addMoreData();//should be asynctask or thread}return view;}
Esteja ciente de que esse método será chamado várias vezes; portanto, você precisa adicionar outra condição para bloquear várias chamadas de addMoreData().
Ao adicionar todos os elementos à lista, ligue para notifyDataSetChanged () dentro do seu adaptador para atualizar o View (ele deve ser executado no encadeamento da UI - runOnUiThread )
É uma prática ruim fazer outras coisas além de retornar uma visualização getView. Por exemplo, você não tem garantia de que posé visualizado pelo usuário. Pode ser simplesmente material de medição do ListView.
Thomas Ahle
Quero carregar mais itens após a rolagem de 10 itens. mas percebo que o carregamento começa antes do 10º item ser visível significa no 9º item. Então, como parar isso?
Ele faz uso do Volley HTTP libraryque torna a rede para aplicativos Android mais fácil e, o mais importante, mais rápida. O Volley está disponível no repositório AOSP aberto.
O código fornecido demonstra:
ListView, preenchido por solicitações paginadas HTTP.
Uso do NetworkImageView.
Paginação ListView "sem fim" com leitura antecipada.
Pode ser um pouco tarde, mas a seguinte solução aconteceu muito útil no meu caso. De certa forma, tudo o que você precisa fazer é adicionar ao seu ListView a Footere criar para ele addOnLayoutChangeListener.
ListView listView1 =(ListView) v.findViewById(R.id.dialogsList);// Your listViewView loadMoreView = getActivity().getLayoutInflater().inflate(R.layout.list_load_more,null);// Getting your layout of FooterView, which will always be at the bottom of your listview. E.g. you may place on it the ProgressBar or leave it empty-layout.
listView1.addFooterView(loadMoreView);// Adding your View to your listview ...
loadMoreView.addOnLayoutChangeListener(newView.OnLayoutChangeListener(){@Overridepublicvoid onLayoutChange(View v,int left,int top,int right,int bottom,int oldLeft,int oldTop,int oldRight,int oldBottom){Log.d("Hey!","Your list has reached bottom");}});
Este evento é acionado uma vez quando um rodapé se torna visível e funciona como um encanto.
A chave desse problema é detectar o evento carregar mais, iniciar uma solicitação assíncrona de dados e atualizar a lista. Também é necessário um adaptador com indicador de carga e outros decoradores. De fato, o problema é muito complicado em alguns casos extremos. Apenas uma OnScrollListenerimplementação não é suficiente, porque às vezes os itens não preenchem a tela.
Eu escrevi um pacote pessoal que suporta uma lista sem fim RecyclerViewe também fornece uma implementação de carregador assíncrono AutoPagerFragmentque facilita muito a obtenção de dados de uma fonte de várias páginas. Ele pode carregar qualquer página desejada em um RecyclerViewevento personalizado, não apenas na próxima página.
Eu tenho trabalhado em outra solução muito semelhante a isso, mas estou usando a footerViewpara dar ao usuário a possibilidade de baixar mais elementos clicando em footerView, estou usando um "menu" que é mostrado acima ListViewe na parte inferior do Na visualização principal, esse "menu" oculta a parte inferior do menu ListView. Assim, quando o listViewmenu está rolando desaparece e quando o estado da rolagem está ocioso, o menu aparece novamente, mas quando o usuário rola para o final do menu listView, eu "peço" para saber se o footerViewé mostrado nesse caso, o menu não aparece e o usuário pode ver o footerViewpara carregar mais conteúdo. Aqui o código:
Eu sei que é uma pergunta antiga e o mundo do Android mudou para o RecyclerViews, mas para qualquer pessoa interessada, você pode achar esta biblioteca muito interessante.
Ele usa o BaseAdapter usado com o ListView para detectar quando a lista foi rolada para o último item ou quando está sendo rolada para longe do último item.
Ele vem com um exemplo de projeto (apenas 100 linhas de código de atividade) que pode ser usado para entender rapidamente como funciona.
O loadMoreitem é um botão ou outro elemento da interface do usuário que pode ser clicado para buscar mais dados do URL. Quando colocado conforme descrito no código, o adaptador sabe exatamente quando mostrar esse botão e quando desativá-lo. Basta criar o botão no seu xml e colocá-lo como mostrado no código do adaptador acima.
Respostas:
Uma solução é implementar
OnScrollListener
e fazer alterações (como adicionar itens etc.) aoListAdapter
estado conveniente em seuonScroll
método.A seguir, é
ListActivity
exibida uma lista de números inteiros, começando com 40, adicionando itens quando o usuário rola para o final da lista.Obviamente, você deve usar threads separados para ações de longa duração (como carregar dados da Web) e pode indicar progresso no último item da lista (como o mercado ou os aplicativos do Gmail).
fonte
firstVisible + visibleCount >= totalCount
é atendida várias vezes com várias chamadas para o ouvinte. Se a função carregar mais for uma solicitação da Web (provavelmente será), adicione outra verificação para verificar se uma solicitação está em andamento ou não. Por outro lado, verifique se o totalCount não é igual à contagem total anterior, porque não precisamos de várias solicitações para o mesmo número de itens na lista.Só queria contribuir com uma solução que eu usei para o meu aplicativo.
Também é baseado na
OnScrollListener
interface, mas achei que ele tinha um desempenho de rolagem muito melhor em dispositivos low-end, pois nenhum dos cálculos de contagem total / visível é realizado durante as operações de rolagem.ListFragment
ouListActivity
implementeOnScrollListener
Adicione os seguintes métodos a essa classe:
onde
currentPage
é a página da sua fonte de dados que deve ser adicionada à sua lista ethreshold
o número de itens da lista (contados no final) que, se visíveis, acionam o processo de carregamento. Se você definirthreshold
a0
, por exemplo, o usuário tem que rolar até o fim da lista, a fim de carregar mais itens.(opcional) Como você pode ver, a "verificação de carregar mais" é chamada apenas quando o usuário para de rolar. Para melhorar a usabilidade, você pode aumentar e adicionar um indicador de carregamento ao final da lista via
listView.addFooterView(yourFooterView)
. Um exemplo para essa visualização de rodapé:(opcional) Por fim, remova esse indicador de carregamento chamando
listView.removeFooterView(yourFooterView)
se não houver mais itens ou páginas.fonte
ListFragment
sem problemas - basta seguir cada uma das etapas acima e você ficará bem;) Ou você poderia fornecer alguma mensagem de erro?getListView().setOnScrollListener(this)
Você pode detectar o final da lista com a ajuda de onScrollListener , o código de trabalho é apresentado abaixo:
Outra maneira de fazer isso (adaptador interno) é a seguinte:
Esteja ciente de que esse método será chamado várias vezes; portanto, você precisa adicionar outra condição para bloquear várias chamadas de
addMoreData()
.Ao adicionar todos os elementos à lista, ligue para notifyDataSetChanged () dentro do seu adaptador para atualizar o View (ele deve ser executado no encadeamento da UI - runOnUiThread )
fonte
getView
. Por exemplo, você não tem garantia de quepos
é visualizado pelo usuário. Pode ser simplesmente material de medição do ListView.Na
Ognyan Bankov GitHub
eu encontrei uma solução simples e funcional!Ele faz uso do
Volley HTTP library
que torna a rede para aplicativos Android mais fácil e, o mais importante, mais rápida. O Volley está disponível no repositório AOSP aberto.O código fornecido demonstra:
Para uma consistência futura, peguei o repo do Bankov .
fonte
Aqui está uma solução que também facilita a exibição de uma exibição de carregamento no final do ListView durante o carregamento.
Você pode ver as aulas aqui:
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java - Auxiliar para tornar possível o uso do recursos sem estender-se de SimpleListViewWithLoadingIndicator.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java - Ouvinte que inicia o carregamento de dados quando o usuário está prestes a chegar ao final do ListView.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java - The EndlessListView. Você pode usar essa classe diretamente ou estender a partir dela.
fonte
Pode ser um pouco tarde, mas a seguinte solução aconteceu muito útil no meu caso. De certa forma, tudo o que você precisa fazer é adicionar ao seu ListView a
Footer
e criar para eleaddOnLayoutChangeListener
.http://developer.android.com/reference/android/widget/ListView.html#addFooterView(android.view.View)
Por exemplo:
Este evento é acionado uma vez quando um rodapé se torna visível e funciona como um encanto.
fonte
A chave desse problema é detectar o evento carregar mais, iniciar uma solicitação assíncrona de dados e atualizar a lista. Também é necessário um adaptador com indicador de carga e outros decoradores. De fato, o problema é muito complicado em alguns casos extremos. Apenas uma
OnScrollListener
implementação não é suficiente, porque às vezes os itens não preenchem a tela.Eu escrevi um pacote pessoal que suporta uma lista sem fim
RecyclerView
e também fornece uma implementação de carregador assíncronoAutoPagerFragment
que facilita muito a obtenção de dados de uma fonte de várias páginas. Ele pode carregar qualquer página desejada em umRecyclerView
evento personalizado, não apenas na próxima página.Aqui está o endereço: https://github.com/SphiaTower/AutoPagerRecyclerManager
fonte
A melhor solução até agora que eu vi está na biblioteca FastAdapter para visualizações de recicladores. Tem um
EndlessRecyclerOnScrollListener
.Aqui está um exemplo de uso: EndlessScrollListActivity
Depois que o usei para uma lista de rolagem interminável, percebi que a configuração é muito robusta. Eu definitivamente recomendo.
fonte
Eu tenho trabalhado em outra solução muito semelhante a isso, mas estou usando a
footerView
para dar ao usuário a possibilidade de baixar mais elementos clicando emfooterView
, estou usando um "menu" que é mostrado acimaListView
e na parte inferior do Na visualização principal, esse "menu" oculta a parte inferior do menuListView
. Assim, quando olistView
menu está rolando desaparece e quando o estado da rolagem está ocioso, o menu aparece novamente, mas quando o usuário rola para o final do menulistView
, eu "peço" para saber se ofooterView
é mostrado nesse caso, o menu não aparece e o usuário pode ver ofooterView
para carregar mais conteúdo. Aqui o código:Saudações.
fonte
Eu sei que é uma pergunta antiga e o mundo do Android mudou para o RecyclerViews, mas para qualquer pessoa interessada, você pode achar esta biblioteca muito interessante.
Ele usa o BaseAdapter usado com o ListView para detectar quando a lista foi rolada para o último item ou quando está sendo rolada para longe do último item.
Ele vem com um exemplo de projeto (apenas 100 linhas de código de atividade) que pode ser usado para entender rapidamente como funciona.
Uso simples:
Um adaptador para armazenar objetos Boy seria semelhante a:
Observe como o método getView do BoysAdapter retorna uma chamada para o
getView
método da superclasse EndlessAdapter . Isso é 100% essencial.Agora, para criar o adaptador, faça:
O
loadMore
item é um botão ou outro elemento da interface do usuário que pode ser clicado para buscar mais dados do URL. Quando colocado conforme descrito no código, o adaptador sabe exatamente quando mostrar esse botão e quando desativá-lo. Basta criar o botão no seu xml e colocá-lo como mostrado no código do adaptador acima.Aproveitar.
fonte