🚀 3.6 ListViews
Para exibir coleções de dados, como a lista de viagens ou gastos, o Android utiliza componentes de listagem. O ListView é o precursor clássico e, embora o RecyclerView seja o padrão atual de mercado, entender o ListView é essencial para compreender a evolução das listas no Android.
IMPORTANT
O Sucessor: RecyclerView Para aplicações de escala profissional, utilize sempre o
RecyclerView. Ele é mais eficiente em termos de memória (reaproveita views de forma inteligente) e oferece animações nativas e maior flexibilidade de layout.
Implementando a Lista de Viagens (ViewBinding & Java 17)
Em vez de utilizarmos a antiga ListActivity, utilizaremos uma AppCompatActivity padrão com um ListView em seu layout XML. Isso nos dá total controle sobre a interface.
Layout XML (activity_viagem_list.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/listViewViagens"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>Atividade de Listagem
Utilizamos o SimpleAdapter para mapear os dados para o layout customizado lista_viagem.xml:
public class ViagemListActivity extends AppCompatActivity {
private ActivityViagemListBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityViagemListBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
var de = new String[] { "imagem", "destino", "data", "total" };
var para = new int[] { R.id.tipoViagem, R.id.destino, R.id.data, R.id.valor };
var adapter = new SimpleAdapter(this, listarViagens(), R.layout.lista_viagem, de, para);
binding.listViewViagens.setAdapter(adapter);
binding.listViewViagens.setOnItemClickListener((parent, view, position, id) -> {
var intent = new Intent(this, GastoListActivity.class);
startActivity(intent);
});
}
private List<Map<String, Object>> listarViagens() {
var viagens = new ArrayList<Map<String, Object>>();
viagens.add(Map.of(
"imagem", R.drawable.negocios,
"destino", "São Paulo",
"data", "02/02/2024 a 04/02/2024",
"total", "Gasto total R$ 314,98"
));
viagens.add(Map.of(
"imagem", R.drawable.lazer,
"destino", "Maceió",
"data", "14/05/2024 a 22/05/2024",
"total", "Gasto total R$ 2.534,67"
));
return viagens;
}
}Customização Avançada com ViewBinder
Para a lista de gastos, queremos mudar a cor de fundo dinamicamente. Para isso, utilizamos um ViewBinder. Note o uso de ContextCompat para garantir a compatibilidade de cores:
private class GastoViewBinder implements SimpleAdapter.ViewBinder {
@Override
public boolean setViewValue(View view, Object data, String textRepresentation) {
if (view.getId() == R.id.categoria) {
var colorId = (Integer) data;
// Forma correta de obter cores no Android moderno
view.setBackgroundColor(ContextCompat.getColor(view.getContext(), colorId));
return true;
}
return false;
}
}TIP
Ao lidar com listas longas, o uso de
Map.of()ouList.of()(Java 9+) torna a inicialização de dados estáticos muito mais legível e concisa.
CAUTION
Ao migrar para o RecyclerView no futuro, você substituirá o
SimpleAdapterpor uma classe herdeira deRecyclerView.Adapter, que implementa o padrão ViewHolder de forma nativa e obrigatória.