Criando uma ListActivity

Hoje aprenderemos a usar uma ListActivity para mostrar ao usuario uma lista com as anotações que ele inseriu em nossa aplicação QuickNotes.

ListActivity? O que é isso?

A ListActivity é uma classe filha da Activity cujo objetivo é mostrar ao usuário uma Lista (uma ListView). Em suma, é uma Activity com alguns métodos para gerenciamento de listas, criada com o intuito de facilitar a criação de telas com essa configuração, muito comuns nas aplicações android.

O primeiro passo para criar uma Activity desse tipo é assegurar que o layout XML a ser usado por ela possui um elemento ListView (afinal, estamos criando uma ListActivity!). Além disso, é preciso que seu id seja “@id/android:list”.

Adequando o layout da nossa aplicação, temos:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical"
    >
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	    android:layout_width="fill_parent"
   		android:layout_height="wrap_content"
    	>
	    <EditText
    	    android:id="@+id/edit_box"
        	android:layout_width="240px"
	        android:layout_height="wrap_content"
    	    android:text=""
    		>
    	</EditText>
    	<Button
			android:id="@+id/insert_button"
			android:layout_width="80px"
			android:layout_height="wrap_content"
			android:text="Inserir"
			>
		</Button>
	</LinearLayout>
    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
    	>
    </ListView>
</LinearLayout>

Depois disso, o próximo é fazer a nossa classe MainActivity ser uma classe filha da ListActivity:

public class MainActivity extends ListActivity

E então, inicializar a ListView no método onCreate. Mas para isso precisaremos de um Adapter.

Adapters

Adapters são classes responsáveis por fazer o que é chamado de “bind“: Receber os dados de um Cursor (ou de alguma outra fonte de dados) e colocá-los nos seus respectivos lugares no layout da Activity.

Para Activity’s complexas, tipicamente são criadas subclasses da classe CursorAdapter (Adapter dedicado a tratar cursores). No nosso caso, em que temos um layout bastante simples, é suficiente o uso do SimpleCursorAdapter.

No código abaixo eu mostro como usar este adapter, com uma explicação sobre seus parâmetros:

        ListAdapter adapter = new SimpleCursorAdapter(
        		              // O primeiro parametro eh o context.
        		              this, 
        		              // O segundo, o layout de cada item. 
        		              R.layout.list_item,
        		              // O terceiro parametro eh o cursor que contem os dados
        		              // a serem mostrados
        		              mCursor,
        		              // o quarto parametro eh um array com as colunas do 
        		              // cursor que serao mostradas
        		              new String[] {QuickNotesProvider.Notes.TEXT},
        		              // o quinto parametro eh um array (com o mesmo 
        		              // tamanho do anterior) com os elementos que 
        		              // receberao os dados.
        		              new int[] {R.id.text});
 
        setListAdapter(adapter);

Um dos parâmetros recebidos pelo contrutor da SimpleCursorAdapter é o layout dos itens da lista, que definimos da seguinte forma:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical">

     <TextView android:id="@+id/text"
         android:textSize="16sp"
         android:textStyle="bold"
         android:textColor="#FFFFFF"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"/>
</LinearLayout>

E por fim, a nossa Activity principal fica assim:


package br.com.felipesilveira.quicknotes;

import android.app.ListActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.SimpleCursorAdapter;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;

public class MainActivity extends ListActivity {
	
	private static final String TAG = "QuickNotesMainActivity";
	private Cursor mCursor;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        Log.d(TAG, "Criando a MainActivity");
      
        setContentView(R.layout.main);
        
        Intent i = new Intent(this, WelcomeActivity.class);
        startActivity(i);
        
        Button insertButton = (Button)findViewById(R.id.insert_button);
        insertButton.setOnClickListener(mInsertListener);

        // adicionando um 'Hint' ao Editbox.
        EditText editBox = (EditText)findViewById(R.id.edit_box);
        editBox.setHint("Nova nota...");
        
        mCursor = this.getContentResolver().
                  query(QuickNotesProvider.Notes.CONTENT_URI, null, null, null, null);

        ListAdapter adapter = new SimpleCursorAdapter(
        		              // O primeiro parametro eh o context.
        		              this, 
        		              // O segundo, o layout de cada item. 
        		              R.layout.list_item,
        		              // O terceiro parametro eh o cursor que contem os dados
        		              // a serem mostrados
        		              mCursor,
        		              // o quarto parametro eh um array com as colunas do 
        		              // cursor que serao mostradas
        		              new String[] {QuickNotesProvider.Notes.TEXT},
        		              // o quinto parametro eh um array (com o mesmo 
        		              // tamanho do anterior) com os elementos que 
        		              // receberao os dados.
        		              new int[] {R.id.text});
 
        setListAdapter(adapter);
     }
     
     /*
      *  Definindo um OnClickListener para o botão "Inserir"
      */
     private OnClickListener mInsertListener = new OnClickListener() {
          public void onClick(View v) {
        	  EditText editBox = (EditText)findViewById(R.id.edit_box);
              addNote(editBox.getText().toString());
              editBox.setText("");
          }
     };
     
     /*
      * Método responsável por inserir um registro no content provider
      */
	 protected void addNote(String text) {
		 ContentValues values = new ContentValues();
		 values.put(QuickNotesProvider.Notes.TEXT, text);  

		 getContentResolver().insert(
		      QuickNotesProvider.Notes.CONTENT_URI, values);
	 } 	 
}

Executando a Activity, temos a seguinte tela, com a lista das notas que o usuário digitou!

Exemplo ListActivity

DICA: Tenha muito cuidado ao projetar uma lista. Lembre-se que um usuário pode inserir mil, dez mil registros! O que aconteceria nessa situação? A performance nesses casos é um fator a ser muito trabalhado e testado. Mas isso fica para um próximo artigo. Até lá!

Desenvolvendo para Android

43 respostas to “Criando uma ListActivity”

  1. Hugo Sousa disse:

    Olá Felipe, parabéns pelos Posts, são de grande ajuda e esclarecimentos.
    Gostaria de pedir os arquivos desta app para tirar algumas dúvidas, poderia ser?
    Eu não entendi a parte do layout dos itens da lista, se vc se refere a um arquivo separado ou apenas inclui dentro da listview do layout principal, no caso tudo ser no layout principal a mainactivity reclama no paramentro R.layout.list_item,.
    Bom, se puder ajudar neste sentido…

    Novamente parabéns pelo blog

  2. Oi Hugo!
    Ótima pergunta, realmente não ficou muito claro.

    O trecho de XML que eu citei como o layout dos itens do menu deve ser colocado em um arquivo separado, chamado list_item.xml (pois foi esse o nome que passamos para o adapter.

    E vou colocar para download o código sim!

    Um abraço!

  3. Hugo Sousa disse:

    Beleza Felipe, estou no aguardo.valeu!

  4. Italo disse:

    Oi Felipe, muito bons seus posts! parabéns!!!
    Só me tira uma dúvida:
    Na classe MainActivity, o trecho …QuickNotesProvider.Notes.TEXT…, acessa uma classe “Notes” e uma constante “TEXT”, ok? mas onde estão definidos esses elementos?

    Valeu!

  5. Oi Italo,
    A constante que você citou está definida na classe QuickNotesProvider, que foi criada nesse artigo: Como Usar um banco de dados em uma aplicação android

    Um abraço!

  6. Italo disse:

    Beleza cara!
    Rodou!

    Obrigado pela agilidade em responder os posts!

    Abraço!

  7. Charles disse:

    Felipe, se possível poste os arquivos do projeto, pois no exemplo que criei está dando erro no trcho “Intent i = new Intent(this, WelcomeActivity.class); ” que corresponde a linha 30.
    Att,

  8. Nanda disse:

    Oi Felipe, tem como postar os arquivos? Nao ficou muito claro alguns pontos e ta dando alguns erros…
    obrigada

  9. Pessoal, vou postar o projeto completo (com todos os arquivos fontes) hoje a noite no blog.

    Um abraço!

  10. Hugo Sousa disse:

    5:30 da matina, acordei para beber água e fui ver se vc tinha colocado para download, ahh cara não durmo mesmo agora rsrssr, Valeu Felipe!!!

  11. Ved disse:

    Excelente! Li todos os artigos da série e agora vou implementa-los! Muito obrigado.

  12. Erick disse:

    Muito bacana, a série estava muito boa! Parou de publicar?

  13. Não parei não Erick! estou preparando alguns novos posts.
    obrigado!

  14. Rita disse:

    Olá, Felipe!
    Parabéns pela iniciativa!
    Fiquei particularmente curiosa em relação à parte final, i.e., quando por motivos de performance não se deseja carregar a lista inteira mas apenas partes dela.
    Sempre pensa em dar continuidade a este artigo?
    Cumprimentos,
    Rita

  15. Lindemberg disse:

    Felipe, muito bom os posts, mas eu tenho uma dúvida, eu estou criando uma aplicação pra android que precisa armazenar dois valores. Por exemplo, Nome e Telefone, no seu caso ele só armazena uma String, como eu faria pra armazenar duas ou mais string. Obrigado.

  16. Oi Lindemberg,

    A melhor forma para fazer isso é criar um banco de dados com 2 campos, ao invés de apenas um.

    Boa sorte!

  17. Lindemberg disse:

    Felipe, como eu faço para criar um banco de dados com 2 campos? Onde eu modifico o código? Obrigado!

  18. Sérgio Ferraz disse:

    Sem Comentários…

    Parabéns mesmo Felipe, você vem se tornando referência quando o assunto é desenvolvimento para Android.

    Excelente seu blog, já está nos meus Favoritos.

    Abraços !!

  19. Magno Junior disse:

    Olá,
    primeiro parabéns pelo ótimo blog (foram as melhores dicas que já encontrei sobre android em sites do Brasil – Faz pouco tempo que comecei e ainda nem fiz minha primeira app).

    segundo, queria tirar uma dúvida sobre o código contido na linha 30 e 31 da classe MainActivite:
    Intent i = new Intent(this, WelcomeActivity.class);
    startActivity(i);

    Qual o propósito dessa chamada? Meu onCreate está iniciando uma nova activite que é igual a ela mesma? Isso é mesmo necessário? Não geraria um “loop infinito” com cada nova activite criada gerando ela mesma?
    Poderia detalhar um pouco mais sobre a necessidade desse trecho de código?

  20. Magno Junior disse:

    Hum…
    pensando bem, startActivite não deve criar outra activite, mas chamar o onRestart(?)
    Mas ainda continuo sem entender a necessidade de chamar esse método.

  21. Dario disse:

    Vlw, Felipe…
    ainda n~~ao tive a oportunidade de ter contato com
    JAVA para android… Mas apenas lendo seus tutoriais estou me animando a experimentar! o/
    Vlw!

  22. Dennys disse:

    Olá Filipe Silveira, muito bom o seu tutorial.

    Estou com um probleminha na implementação da ListActivity, pois não vejo a implementação da mesma bem como o método setListAdapter. Agradeço se puder postar esse código…
    Vlw!!!

  23. Oi Dennys,

    A classe ListActivity é nativa de android.

  24. Dennys disse:

    Vlw Felipe, Não tinha percebido.

  25. Ronaldo Ottoni disse:

    Olá Felipe, companheiro você está de parabéns pela material toda…
    Estou com um probleminha aqui…na parte final, quando mudamos a extends da MainActivity de “extends Activity” para “extends ListActivity”, a aplicação não abre no emulador 🙁 ele apresenta uma mensagem de terminou inesperadamente, tente novamente e fecha.

    Por favor, me dê uma luz grande mestre..

    Forte abraço

  26. Oi Ronaldo,

    Você poderia colocar qual é a mensagem que aparece no log? lá deve aparecer alguma exception, e ela vai ajudar a achar o problema.

  27. Derzu disse:

    Uma pequena correção, na descrição do list_item.xml substituir:

    linearlayout -> LinearLayout
    textview -> TextView
    textsize -> textSize
    textstyle -> textStyle
    textcolor -> textColor

  28. Derzu disse:

    Oi Felipe, só uma dica sobre um problema que eu tive, alguém pode passar pelo mesmo. Tava tudo rodando, sem quebrar, mas a lista dos nomes não aparecia. Percebi o seguinte:

    No tópico Trabalhando com layouts XML em Android (II) (http://www.felipesilveira.com.br/2010/04/trabalhando-com-layouts-xml-em-android-ii/), o segundo LinearLayout, tem o parâmetro android:layout_height=”fill_parent”.

    Já o main.xml descrito neste post, tem o segundo LinearLayout com o parâmetro android:layout_height=”wrap_content”.

    Usando o fill_parent não aparece a lista, utilizando o wrap_content funciona blz.

    Abraço.

  29. Paulo Eduardo disse:

    Pessoal,

    não consegui fazer a lista aparecer. Não dá erro nenhum. A aplicação sobe normalmente, mas quando inserido não aparece na tabela.

    Ja tentei a dica do colega acima, mas também não deu.

    Alguém dá um help?

    Como faço para acessar o SQLite pelo Aparelho Android para ver se está gravando mesmo, porque estou usando o próprio aparelho para testar as minhas aplicações?

  30. Ednaldo Nascimento disse:

    Parabens pelo projeto Felipe. Quando saem as próximas com a edição e exclusão de dados?? E como faço para acessar o banco SQLight?

  31. Eduardo Silva disse:

    Parabéns Felipe.
    Eu já havia seguido alguns vídeos do xda-developers que me ensinaram a configurar o eclipse e iniciar uma aplicação, mas depois de seguir o seu tutorial consegui aprofundar bastante o conhecimento.

    Trabalho a bastante tempo com Java, mas só agora resolvi enfrentar o Java para Android.

    Agradeço também ao Derzu, pois sem a dica dele eu ficaria um bom tempo com problemas.

    E Paulo Eduardo, eu também estou testando no aparelho, e consegui fazer funcionar sem problemas seguindo a alteração que o Derzu propôs. Você tem certeza que fez a alteração no local correto? Ela deve ser feita no segundo LinearLayout do arquivo principal.

  32. Filipe Moraes disse:

    Parabéns Felipe pelas dicas, ajudaram e muito!
    Por favor, gostaria apenas de tirar uma dúvida, claro, se você tiver um tempinho.
    No LinearLayout onde aparece cada nota registrada, gostaria de saber se é possível que ao clicar no conteúdo, uma nova Activity se abra, como se fosse “mais informações”.

    Obrigado pela sua atenção.

  33. Thiago disse:

    Ola excelente post.
    mas so falta uma coisa pra meu sw rodar.

    ele ta dando problema no R.id.text
    o id desse obj estaria no list_item.xml nao e?

    mas de acordo codigo acima ( primeiro codigo desse post)
    nao tem declarado o text
    e abaixo nao intendi mt bem onde insiro o text

    no seu codigo vc disponibilizou para download esta diferente desse codigo desse post.

    quem puder me ajudar Obg

  34. elpidio disse:

    Muito bom os seus Posts, está sendo de grande ajuda.

  35. Caro Paulo,

    Se você ainda estiver com problemas.. eu também estava passando pela mesma situação mas descobri que a cor do texto definida no arquivo list_item.xml é BRANCO (#FFFFFF) no meu caso meu ADV esta com o fundo branco, sendo assim, coloquei o mesmo para fundo preto (#000000) e vualá problema resolvido!

    Valeu demais Felipe.

    Excelentes posts.

  36. Guga disse:

    tenho um bloguesinho, ta indicado la no site, e tambem no grupo de java que tenho.

    Parabens rapaz, sucesso ai pra vc.

  37. Daniel dos Santos disse:

    Olá, eu consegui arrumar um erro no código do ListView, trocando o nome do id.
    Nome do Erro:
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.daniel.olamundo/com.example.daniel.olamundo.MinhaAtividade}: java.lang.RuntimeException: Your content must have a ListView whose id attribute is ‘android.R.id.list’

    solução:

    para quem tiver este erro, um abraço. 😀

  38. Daniel dos Santos disse:

    Olá,não apareceu a solução, botei entre aspas pra ver, mas está ae, consegui arrumar um erro no código do ListView, trocando o nome do id.
    Nome do Erro:
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.daniel.olamundo/com.example.daniel.olamundo.MinhaAtividade}: java.lang.RuntimeException: Your content must have a ListView whose id attribute is ‘android.R.id.list’

    solução:
    “”
    o comando fill_parent está depreciado, por isso troquei, mas faz a mesma coisa.
    para quem tiver este erro, um abraço. 😀

  39. Daniel dos Santos disse:

    solução:
    android:id=”@android:id/list”
    android:layout_width=”match_parent”]

    agora vai, ashsah

  40. Thais disse:

    Ola!!
    Como faço para um AlertDialog.Builder retornar no setPositiveButton uma Lista dos Nomes informados (Adicionados)?

Deixe um comentário