Tutorial Android 4 #7 – Aprimorando a Listagem

Padrão

Olá pessoal! Hoje vamos prosseguir mais um pouco com o nosso tutorial sobre Android. No último post, criamos a listagem dos contatos que, ao serem adicionados, apareciam na parte superior da tela. Hoje, vamos melhorar a exibição deles, passando a ser exibidos com o respectivo e-mail e um ícone identificando qual tipo de contato que se trata.

O primeiro passo é criarmos o nosso próprio adaptador para exibir os itens na lista. Assim, na classe MeusContatos, vamos criar uma classe interna, chamada ContatoAdapter. Vai ficar assim:

private class ContatoAdapter extends ArrayAdapter {

	public ContatoAdapter() {
		super(MeusContatos.this, android.R.layout.simple_list_item_1,
				contatos);
	}
}

O próximo passo é ajustar nosso layout para a nossa nova lista, já que nessa nova listagem teremos nome, e-mail e tipo (representado por uma imagem). Vamos, primeiramente, criar um layout que represente cada um dos itens da nossa listagem de forma a abrigar os três elementos. Na pasta res/layout crie o arquivo elemento_lista.xml com o seguinte conteúdo:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="4dip" >

    <ImageView
        android:id="@+id/icone"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_marginRight="4dip"
        android:contentDescription="@string/desc_icone" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/titulo"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ellipsize="end"
            android:gravity="center_vertical"
            android:singleLine="true"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/subtitulo"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ellipsize="end"
            android:gravity="center_vertical"
            android:singleLine="true" />
    </LinearLayout>

</LinearLayout>

Resumidamente, este layout divide cada item de listagem em duas partes (dois itens LinearLayout), sendo a primeira divisão de forma horizontal, onde à esquerda ficará a nossa imagem e, à direita, teremos outro LinearLayout, dessa vez vertical, que exibirá o nome do contato e seu e-mail.

O próximo passo é colocar as imagens em res/drawable. Você deve perceber que na estrutura do projeto, temos as pastas drawable-hdpi, drawable-ldpi, drawable-mdpi e drawable-xhdpi. Esses sufixos indicam a densidade de pixel dos vários tipos de tela que um dispositivo Android pode ter. Ele está diretamente ligado ao tamanho e resolução da tela. Por exemplo, o emulador que estou utilizando tem densidade hdpi (alta densidade), enquanto que meu celular pessoal (LG Optimus One) tem densidade mdpi (média densidade). Mais informações sobre esse assunto podem ser encontradas na documentação oficial. Então, pra fecharmos esse assunto por hoje, as pastas servem para colocar imagens em diferentes resoluções, para deixá-las mais nítidas nas várias densidades e evitar problemas de exibição com o redimensionamento automático que o Android faz. No caso do nosso exemplo, vou colocar as imagens em drawable-hdpi (resolução do emulador). No final do post eu mostro como ficou também no meu celular. Então, baixe as imagens (academico.png, pessoal.png e profissional.png) aqui e coloque-as na pasta drawable-hdpi.

Agora, vamos sobrescrever o método getView() na classe ContatoAdapter. Este método é o responsável por exibir os itens na tela. Assim, vamos através dele utilizar o layout definido em elemento_lista.xml. A classe ContatoAdapter fica assim:

private class ContatoAdapter extends ArrayAdapter {

	public ContatoAdapter() {
		super(MeusContatos.this, android.R.layout.simple_list_item_1,
				contatos);
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		View linha = convertView;
		ArmazenadorDeContatos armazenador = null;

		if (linha == null) {
			LayoutInflater inflater = getLayoutInflater();
			linha = inflater.inflate(R.layout.elemento_lista, null);
		}

		Contato contato = contatos.get(position);

		((TextView) linha.findViewById(R.id.titulo)).setText(contato.getNome());
		((TextView) linha.findViewById(R.id.subtitulo)).setText(contato.getEmail());

		ImageView icone = (ImageView) linha.findViewById(R.id.icone);

		switch (contato.getTipo()) {
		case ACADEMICO:
			icone.setImageResource(R.drawable.academico);
			break;
		case PESSOAL:
			icone.setImageResource(R.drawable.pessoal);
			break;
		case PROFISSIONAL:
			icone.setImageResource(R.drawable.profissional);
			break;
		}

		return linha;
	}
}

Prosseguindo, precisamos agora vincular os itens da lista à nossa lista de restaurantes adicionados. Para isso, vamos criar uma classe estática que armazenará os valores para que sejam adicionados à lista exibida na tela. Adicione-a após a declaração do nosso adaptador a classe estática ArmazenadorDeContatos:

static class ArmazenadorDeContatos {
	private TextView nome = null;
	private TextView email = null;
	private ImageView icone = null;

	public ArmazenadorDeContatos(View linha) {
		nome = (TextView) linha.findViewById(R.id.titulo);
		email = (TextView) linha.findViewById(R.id.subtitulo);
		icone = (ImageView) linha.findViewById(R.id.icone);
	}

	void popularFormulario(Contato contato) {
		nome.setText(contato.getNome());
		email.setText(contato.getEmail());

		switch (contato.getTipo()) {
		case ACADEMICO:
			icone.setImageResource(R.drawable.academico);
			break;
		case PESSOAL:
			icone.setImageResource(R.drawable.pessoal);
			break;
		case PROFISSIONAL:
			icone.setImageResource(R.drawable.profissional);
			break;
		}
	}
}

Por fim, vamos fazer o método getView utilizar a classe ArmazenadorDeContatos para montar os objetos na lista, e alteramos as referências ao ArrayAdapter para o nosso ContatoAdapter, finalizando o nosso tutorial. Corrija a chamada ao construtor do adaptador no método onCreate() da activity também. A listagem completa da classe MeusContatos fica assim:

public class MeusContatos extends Activity implements OnClickListener {

	private List contatos = new ArrayList();
	private ContatoAdapter adaptador = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_meus_contatos);

		Button salvar = (Button) findViewById(R.id.salvar);
		salvar.setOnClickListener(this);

		ListView lista = (ListView) findViewById(R.id.contatos);
		adaptador = new ContatoAdapter();
		lista.setAdapter(adaptador);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_meus_contatos, menu);
		return true;
	}

	@Override
	public void onClick(View v) {
		EditText nome = (EditText) findViewById(R.id.nome);
		EditText email = (EditText) findViewById(R.id.email);

		Contato contato = new Contato();
		contato.setNome(nome.getText().toString());
		contato.setEmail(email.getText().toString());

		RadioGroup tipoContato = (RadioGroup) findViewById(R.id.tipo_contato);

		switch (tipoContato.getCheckedRadioButtonId()) {
		case R.id.pessoal:
			contato.setTipo(Contato.Tipo.PESSOAL);
			break;
		case R.id.profissional:
			contato.setTipo(Contato.Tipo.PROFISSIONAL);
			break;
		case R.id.academico:
			contato.setTipo(Contato.Tipo.ACADEMICO);
			break;
		}

		adaptador.add(contato);
	}

	private class ContatoAdapter extends ArrayAdapter {

		public ContatoAdapter() {
			super(MeusContatos.this, android.R.layout.simple_list_item_1,
					contatos);
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View linha = convertView;
			ArmazenadorDeContatos armazenador = null;

			if (linha == null) {
				LayoutInflater inflater = getLayoutInflater();
				linha = inflater.inflate(R.layout.elemento_lista, null);
				armazenador = new ArmazenadorDeContatos(linha);
				linha.setTag(armazenador);
			} else {
				armazenador = (ArmazenadorDeContatos) linha.getTag();
			}

			armazenador.popularFormulario(contatos.get(position));

			return linha;
		}
	}

	static class ArmazenadorDeContatos {
		private TextView nome = null;
		private TextView email = null;
		private ImageView icone = null;

		public ArmazenadorDeContatos(View linha) {
			nome = (TextView) linha.findViewById(R.id.titulo);
			email = (TextView) linha.findViewById(R.id.subtitulo);
			icone = (ImageView) linha.findViewById(R.id.icone);
		}

		void popularFormulario(Contato contato) {
			nome.setText(contato.getNome());
			email.setText(contato.getEmail());

			switch (contato.getTipo()) {
			case ACADEMICO:
				icone.setImageResource(R.drawable.academico);
				break;
			case PESSOAL:
				icone.setImageResource(R.drawable.pessoal);
				break;
			case PROFISSIONAL:
				icone.setImageResource(R.drawable.profissional);
				break;
			}
		}
	}
}

E ao rodar, temos o seguinte:

rodando no emulador… (clique para ampliar)

… e rodando no meu celular (mdpi)

Deu pra perceber que o redimensionamento automático não ficou ruim. No caso, quando for fazer seus aplicativos, é sempre bom verificar como fica a visualização em diversas resoluções pra não ter problemas 🙂

Ah, pra baixar o projeto é só clicar aqui. Até a próxima!

5 comentários sobre “Tutorial Android 4 #7 – Aprimorando a Listagem

  1. Thiago

    Olá Rafael, parabéns pelos posts sobre Android. Você tem ideia de quando será o será o seu próximo post? Ou seja, a continuação do tutorial.

  2. Flavio

    Olá.. to começando agora e gostaria muito da sua ajuda.. Como faria isso exibindo a foto de cada amigo? Por exemplo. eu salvo a minha foto e meus amigos passam a ve-la.. Como no Whats app por exemplo

Deixe uma resposta