Como implementar carregar-mais (scroll infinito)
Propósito. Carregar mais dados automaticamente à medida que o usuário se aproxima do fim da lista, anexando itens ao dataset existente (append). Diferente da paginação com cache LRU (paginacao.md), aqui você controla o dataset e a lista apenas avisa quando é hora de buscar mais.
APIs usadas
VirtualListView.onLoadMore(Runnable callback)— dispara quando o scroll chega perto do fim. Só um disparo por vez fica pendente (loadMorePending), evitando chamadas duplicadas.VirtualListView.loadMoreThreshold(int threshold)— quantos itens antes do fim disparam o callback. Default5.VirtualListView.notifyDataChanged()— obrigatório chamar depois de anexar os novos itens; ele limpa oloadMorePending, esconde o spinner e re-mede o conteúdo.
Exemplo completo (copiar, colar e rodar)
package com.exemplo;
import java.util.*; // List / ArrayList
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.graphics.*; // Relative (para VirtualListView)
/** Tela principal executável. Aponte o launcher (classname) e rode: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
final List<String> dados = new ArrayList<>();
int proxima = 0;
/** Anexa uma leva de 30 itens ao dataset (simula uma página do servidor). */
private void carregarPagina()
{
for (int i = 0; i < 30; i++)
dados.add("Registro " + (proxima++));
}
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
carregarPagina(); // popula a primeira leva
VirtualListView lista = new VirtualListView(Relative.ofFont(3f), new VirtualListView.DataAdapter()
{
public int getCount() { return dados.size(); }
public Component createView() { return new Label(""); }
public void bindView(Component v, int i) throws Exception
{
((Label) v).setText(dados.get(i));
}
});
lista.loadMoreThreshold(8); // começa a buscar 8 itens antes do fim (default é 5)
lista.onLoadMore(() ->
{
// dispara UMA vez ao aproximar do fim; próximos disparos só após notifyDataChanged
onUI(() ->
{
carregarPagina(); // ANEXA (novos índices no fim)
lista.notifyDataChanged(); // libera o próximo load-more e esconde o spinner
});
});
add(LAY_FILL, lista);
}
}
O trecho abaixo mostra só o miolo. Para rodar, coloque-o no esqueleto
MainWindowacima.
Trecho mínimo
// verificado na fonte: VirtualListView.java (onLoadMore / loadMoreThreshold / notifyDataChanged)
final Array<String> dados = new Array<>();
carregarPagina(dados, 0); // popula a primeira leva
VirtualListView lista = new VirtualListView(Relative.ofFont(3f), new VirtualListView.DataAdapter()
{
public int getCount() { return dados.size(); }
public Component createView() { return new Label(""); }
public void bindView(Component v, int i) throws Exception
{
((Label) v).setText(dados.get(i));
}
});
lista.loadMoreThreshold(8); // começa a buscar 8 itens antes do fim (default é 5)
lista.onLoadMore(() ->
{
// dispara UMA vez ao aproximar do fim; próximos disparos só após notifyDataChanged
api.proximaPagina(novos ->
{
dados.addAll(novos); // ANEXA (novos índices no fim)
lista.notifyDataChanged(); // libera o próximo load-more e esconde o spinner
});
});
layout.add(1f, lista);
Aprofunde-se
- O
VirtualListViewmostra automaticamente um spinner no rodapé enquanto o load-more está pendente (controlado peloVirtualListViewStyle.showSpinner). - Se você não chamar
notifyDataChanged(),loadMorePendingfica travado emtruee o callback nunca mais dispara. - Precisa de páginas descartáveis com cache limitado (em vez de append infinito)? Use paginacao.md.
- Guia de widget: VirtualListView · Receita irmã: lista-virtual-grande.md · Fonte canônica: Capítulo 15
Esta página foi útil?Obrigado pelo feedback!