Criando uma lista com ListView no Android
Estou desenvolvendo um app para cadastrar todos os cursos do Alura que eu fiz ou estou fazendo, para que eu possa verificar quais são os cursos que eu já terminei ou se ainda precisa finalizar. Então inicialmente eu criei uma classe para representar meus cursos:
public class Curso {
private String nome;
private String descricao;
private EstadoAtual estado;
//métodos
}
E um ENUM
pra representar o estado atual do curso, ou seja, se ele está finalizado ou se está sendo feito:
public enum EstadoAtual {
FAZENDO{ @Override public String toString() { return "Fazendo"; }
}, FINALIZADO{ @Override public String toString() { return "finalizado"; }
};
}
Adicionando a ListView no layout
Como fazemos para criar a nossa tela? Precisamos criar um XML
para representá-la, certo? Então vamos criar esse XML
na pasta res/layout
com o nome activity_lista_de_cursos.xml
:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<ListView android:id="@+id/lista" android:layout_width="match_parent" android:layout_height="match_parent">
</ListView>
</RelativeLayout>
Muito bom, temos o nosso layout, porém precisamos associar esse layout a uma activity, como podemos fazer isso?
Bom, primeiro nós precisamos de uma activity, então vamos criar a ListaDeCursosActivity
que estende a classe Activity
ou uma de suas filhas, nesse caso, usarei a classe AppCompatActivity
por questão de compatibilidade:
public class ListaDeCursosActivity extends AppCompatActivity {
}
Buscando a referência da lista
Agora que temos a nossa activity, podemos implementar o método onCreate()
que irá settar o nosso layout e vai pegar a referência da ListView
:
public class ListaDeCursosActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lista_de_cursos);
ListView listaDeCursos = (ListView) findViewById(R.id.lista);
}
}
Settamos o nosso layout e pegamos a referência para a nossa ListView
e agora nós precisamos pegar a nossa lista de cursos:
@Override protected void onCreate(Bundle savedInstanceState) {
List<Curso> cursos = todosOsCursos();
ListView listaDeCursos = (ListView) findViewById(R.id.lista);
//métodos
}
Temos a nossa List
e a nossa ListView
, porém, não existe um método da classe ListView
capaz de adicionar uma List
, uma pena... E agora? O que podemos fazer?
Criando o Adapter da lista
No Android, existe um especialista em lidar com listas chamado adapter e, para nossa felicidade, a ListView
consegue adicionar esse adapter! E como podemos criar um adapter? Por meio da classe ArrayAdapter
:
@Override protected void onCreate(Bundle savedInstanceState) { //métodos
ArrayAdapter<Curso> adapter = new ArrayAdapter<Curso>();
}
Ops, há um detalhe na instância do ArrayAdapter
, todos os construtores dele exigem pelo menos um Context
que será a nossa activity e um int
que será o recurso que representará cada item da lista.
Inserindo um layout simples para cada item da lista
O Android disponibiliza para nós alguns recursos para utilizarmos, nesse caso, utilizaremos o recurso android.R.layout.simple_list_item_1
que é uma representação bem básica para cada item da lista:
@Override protected void onCreate(Bundle savedInstanceState) { //métodos
ArrayAdapter<Curso> adapter = new ArrayAdapter<Curso>(this, android.R.layout.simple_list_item_1);
}
Adicionando o Adapter da ListView
Certo, instanciamos o nosso ArrayAdapter
só que ainda não informamos em momento algum que queremos que ele adapte a nossa lista de cursos! Como podemos passar a nossa lista para ele?
O ArrayAdapter
possui diversos construtores e, para a nossa alegria, um deles recebe uma List
que é justamente o que precisamos:
@Override protected void onCreate(Bundle savedInstanceState) {
//métodos
List<Curso> cursos = todosOsCursos();
ArrayAdapter<Curso> adapter = new ArrayAdapter<Curso>(this, android.R.layout.simple_list_item_1, cursos);
}
Certo, criamos nosso adapter, o que precisamos fazer agora? De alguma forma, nós precisamos fazer com o que a nossa ListView
utilize esse adapter, mas como podemos fazer isso?
Sabemos que a classse ListView
não é capaz de adicionar uma List
, porém ela pode settar um adapter por meio do método setAdapter()
:
public class ListaDeCursosActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lista_de_cursos);
List<Curso> cursos = todosOsCursos();
ListView listaDeCursos = (ListView) findViewById(R.id.lista);
ArrayAdapter<Curso> adapter = new ArrayAdapter<Curso>(this, android.R.layout.simple_list_item_1, cursos);
listaDeCursos.setAdapter(adapter);
}
//métodos
}
Vamos testar a nossa app:
Opa! Calma aí! Hashcode da classe? Não era bem isso que eu queria... O que será que aconteceu?
Personalizando a impressão dos objetos
Quando um adapter recebe uma List
, ele imprime exatamente o conteúdo de cada posição da List
, por exemplo, se for uma lista de String
imprime a String
de cada posição, se for de int
imprime int
e por aí vai.
Porém no nosso caso, é uma lista de Curso
, ou seja, ele chamou o toString
de cada curso dentro da lista e por isso apareceu o hashcode de cada um... Que tal personalizarmos o toString()
?
Vamos então implementar o nosso toString()
para que seja impresso as informações de um curso:
public class Curso {
private String nome;
private String descricao;
private EstadoAtual estado; //métodos
@Override public String toString() {
return "Curso: " + nome + " Descrição: " + descricao + " Estado: " + estado;
}
}
Agora se testamos a nossa app novamente:
Maravilha! Agora sim a nossa lista mostra as informações de cada curso da lista!
Personalizando a ListView
Embora a nossa lista esteja funcionando, nem sempre é esse visual que desejamos... Seria legal, por exemplo, se tivesse alguma forma de modificar o aspecto visual de cada item da lista, certo? Pensando nisso, escrevi o post que ensina como é possível personalizar a ListView
;)
Resumo
Vimos que, para criarmos uma lista no android nós precisamos definir uma ListView
no nosso XML
que representará a nossa tela e referenciá-la na nossa activity.
Além disso, vimos que apenas a ListView
não é o suficiente para que possamos adicionarmos a nossa List
e por isso precisamos de um adapter que é especialista em lidar com List
e informar para a ListView
quais serão os valores de cada item da lista.
Vimos também que, quando passamos uma lista de objetos nossos, como por exemplo a classe Curso
, por padrão será impresso o próprio objeto, ou seja, o toString()
padrão e, se quisermos uma informação diferente, precisamos implementá-lo de acordo com a nossa necessidade.
Código fonte
Caso tiver dúvidas ou simplesmente quiser consultar o código fonte do projeto utilizado como exemplo, fique à vontade de dar uma olhada no github.
Quer aprender mais sobre Android? Que tal dar uma olhada na formação de Android? Neles ensinamos desde os conceitos mais básicos a avançados para que você construa a sua primeira App e inicie sua carreira como desenvolvedor Android!