quinta-feira, 8 de dezembro de 2011

Android - ListView Parte 5

Olá,

Dando sequência a série sobre ListView, esse que é um dos recursos mais importantes do Android, estamos chegando a parte 5.

Hoje iremos ver como criar um listview com ícone e mais de uma linha de texto para cada registro do ListView.

Nesse caso precisaremos criar um BaseAdapter customizado que irá receber uma lista de Estados e criar dois arquivos de layout XML, um sendo o principal que conterá as linha da lista e o outro sendo as próprias linhas da lista.

Abaixo segue o fonte utilizado todo comentado para facilitar seu aprendizado:

Arquivo estados.java:
package br.com.empresa;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class estados extends Activity {
    //Criamos uma lista de Estados baseados na classe Estado
    private List<estado> lstEstados = null;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        setContentView(R.layout.estados);
        
        ListView list = (ListView) findViewById(R.id.ListView12);

        //Iniciamos a lista de Estados
        //no método add já inserimos um novo registro de cada Estados desejado
        lstEstados = new ArrayList<estado>();
        lstEstados.add(new Estado("Sao Paulo", "Sao Paulo", R.drawable.saopaulo));
        lstEstados.add(new Estado("Rio de Janeiro", "Rio de Janeiro", R.drawable.riodejaneiro));
        lstEstados.add(new Estado("Minas Gerais", "Belo Horizonte", R.drawable.minasgerais));
        lstEstados.add(new Estado("Rio Grande do Sul", "Porto Alegre", R.drawable.riograndedosul));
        lstEstados.add(new Estado("Santa Catarina", "Florianópolis", R.drawable.santacatarina));
        lstEstados.add(new Estado("Paraná", "Curitiba", R.drawable.parana));
        lstEstados.add(new Estado("Mato Grosso", "Cuiabá", R.drawable.matogrosso));
        lstEstados.add(new Estado("Amazonas", "Manaus", R.drawable.amazonas));

        //Criação do Adapter e passamos a nossa lista de Estados para ele
        EstadoAdapter adapter = new EstadoAdapter(this, lstEstados);

        //referenciamos a função que será invocada quando o usuário
        //clicar em algum item da lista
        list.setOnItemClickListener(onItemClick_List);
    
        list.setAdapter(adapter);
    
        //caso seja preciso adicionar mais algum item na lista você
        //pode utilizar também a forma abaixo
        adapter.addItem(new Estado("Bahia", "Salvador", R.drawable.bahia));
    }

    OnItemClickListener onItemClick_List = new OnItemClickListener() {
        public void onItemClick(AdapterView arg0, View view, int position, long index) {
            //Pegar o item clicado
            showToast("Você clicou no estado : " + lstEstados.get(position).getEstado());
        }
    };
    
    private void showToast(String message) {
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }        
}

Arquivo Estado.java (classe POJO):
package br.com.empresa;

public class Estado {
    private String estado;
    private String capital;
    private int bandeira;

    public Estado(String estado, String capital, int bandeira) {
        super();
        this.estado = estado;
        this.capital = capital;
        this.bandeira = bandeira;
    }

    public String getEstado() {
        return estado;
    }
    public void setEstado(String estado) {
        this.estado = estado;
    }
    public String getCapital() {
        return capital;
    }
    public void setCapital(String capital) {
        this.capital = capital;
    }
    public int getBandeira() {
        return bandeira;
    }
    public void setBandeira(int bandeira) {
        this.bandeira = bandeira;
    }
}

Arquivo EstadoAdapter.java:
package br.com.empresa;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class EstadoAdapter extends BaseAdapter{
    private List<estado> listEstados;

    //Classe utilizada para instanciar os objetos do XML
    private LayoutInflater inflater;
    
    public EstadoAdapter(Context context, List<estado> plistEstados) {
        this.listEstados = plistEstados;
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public void addItem(final Estado item) {
        this.listEstados.add(item);
        //Atualizar a lista caso seja adicionado algum item
        notifyDataSetChanged();
    }    
    
    @Override
    public int getCount() {
        return listEstados.size();
    }

    @Override
    public Object getItem(int position) {
        return listEstados.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup viewGroup) {
        //Pega o registro da lista e trasnfere para o objeto estadoVO
        Estado estadoVO = listEstados.get(position);
        
        //Utiliza o XML estado_row para apresentar na tela
        convertView = inflater.inflate(R.layout.estado_row, null);
        
        //Instância os objetos do XML
        ImageView bandeira = (ImageView)convertView.findViewById(R.id.bandeira);
        TextView tvEstado = (TextView)convertView.findViewById(R.id.tvEstado);
        TextView tvCapital = (TextView)convertView.findViewById(R.id.tvCapital);
            
        //pega os dados que estão no objeto estadoVO e transfere para os objetos do XML
        bandeira.setImageResource(estadoVO.getBandeira());
        tvEstado.setText(estadoVO.getEstado());
        tvCapital.setText(estadoVO.getCapital());
        
        return convertView;
    }
}

Abaixo segue o código fonte do arquivo estados.xml:
<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout 
    android:layout_height="match_parent" 
    android:layout_width="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <ListView 
        android:id="@+id/ListView12" 
        android:layout_height="wrap_content" 
        android:layout_width="fill_parent">
    </ListView>
</LinearLayout>


Abaixo segue o código fonte do arquivo estado_row.xml:
<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout 
    android:id="@+id/LinearLayout01" 
    android:layout_height="wrap_content" 
    android:layout_margintop="10dp" 
    android:layout_width="fill_parent" 
    android:orientation="vertical" 
    xmlns:android="http://schemas.android.com/apk/res/android">
    <RelativeLayout 
        android:id="@+id/LinearLayout02" 
        android:layout_height="wrap_content" 
        android:layout_marginbottom="3dp" 
        android:layout_margintop="3dp" 
        android:layout_width="fill_parent">
        <ImageView 
            android:focusable="false" 
            android:id="@+id/bandeira" 
            android:layout_height="wrap_content" 
            android:layout_width="wrap_content" 
            android:src="@drawable/icon">                        
        </ImageView>
        <TextView 
            android:id="@+id/lblEstado" 
            android:layout_height="wrap_content" 
            android:layout_torightof="@+id/bandeira" 
            android:layout_width="wrap_content" 
            android:text="Estado : " 
            android:textsize="16sp" 
            android:textstyle="bold">
        </TextView>
        <TextView 
            android:focusable="false" 
            android:id="@+id/tvEstado" 
            android:layout_height="wrap_content" 
            android:layout_torightof="@+id/lblEstado" 
            android:layout_width="wrap_content" 
            android:text="nome do estado" 
            android:textsize="16sp" 
            android:textstyle="bold">
        </TextView>
        <TextView 
            android:focusable="false" 
            android:id="@+id/lblCapital" 
            android:layout_below="@+id/lblEstado" 
            android:layout_height="wrap_content" 
            android:layout_torightof="@+id/bandeira" 
            android:layout_width="wrap_content" 
            android:text="Capital : " 
            android:textsize="13sp" 
            android:textstyle="bold">
        </TextView>
        <TextView 
            android:focusable="false" 
            android:id="@+id/tvCapital" 
            android:layout_below="@+id/lblEstado" 
            android:layout_height="wrap_content" 
            android:layout_torightof="@+id/lblCapital" 
            android:layout_width="wrap_content" 
            android:text="nome da capital" 
            android:textsize="13sp">
        </TextView>
    </RelativeLayout>
</LinearLayout>

Abaixo seguem as figuras que foram utilizadas no sistema na pasta res\drawable-ldpi:


Abaixo segue o resultado do nosso sistema:
ListView


Em breve estarei postando mais opções relacionadas a layout e listview.



Trabalhando com Banco de Dados SQLite:
http://escoladeandroid.blogspot.com/2012/02/android-criando-uma-agenda-de-contatos.html


Desenvolvi o jogo Circus Puzzle Free ele é um quebra-cabeça e está publicado no Android Market, agradeço a todos que baixarem, jogarem e comentarem.





Desenv com qualidade!

7 comentários:

Douglas T. disse...

Olá Marcio, estou tentando aplicar este modelo, porém os 2 xml's que criei na pasta layout, não estão reconhecendo como layout na hora que chama nesta linha:

setContentView(R.layout.usus);
//mudei o nome para usus, pois aqui serão listados usuários. Mas o código é o mesmo.
//problema aqui é q o usus fica sublinhado como se fosse erro

Teria idéia do que pode estar acontecendo?

Marcio de Souza disse...

Olá Douglas,

Qual erro acusa?

Sem ver, imagino que deve ter dado algum problema com renomear arquivo, sempre tenho problemas com isso, as vezes o Eclipse não atualiza o arquivo R.java (nesse caso não adicionando o arquivo .xml na seção layout).

Se com essas informações conseguir resolver tudo bem, se não mandar mais informações.

Obrigado pela visita.

DarkDragon disse...

Olá Marcio tudo bem?

Estou com um erro quando vou rodar o aplicativo, da erro e fecha o aplicativo, quando utilizo o setContentView, ocorre o erro:

05-10 02:53:01.014: E/AndroidRuntime(507): Uncaught handler: thread main exiting due to uncaught exception
05-10 02:53:01.045: E/AndroidRuntime(507): java.lang.RuntimeException: Unable to start activity ComponentInfo{br.edu.utfpr.aa/br.edu.utfpr.aa.AndroidAFVActivity}: java.lang.RuntimeException: Your content must have a ListView whose id attribute is 'android.R.id.list'

tem idéia od que pode ser?

Marcio de Souza disse...

Olá DarkDragon,

Imagino que o ID do ListView que você definiu em seu arquivo .XML ficou diferente do ID que você está utilizando em sua classe .Java

Arthur A. GOmEs disse...

Olá Marcio, estou tentando rodar a aplicação no android mas ta dando erro... no emulador estava funcionando normalmente

Danilo Pinto da Silva disse...
Este comentário foi removido pelo autor.
Daniel Lima disse...

Olá eu gostaria de saber qual é o codigo para quando eu clicar no icone da list view abrir uma nova tela