Tutorial Android 4 #7 – Aprimorando a Listagem

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.

Continuar lendo

Tutorial Android #5 – Aprimorando a Lista

Olá pessoal! Prosseguindo com o tutorial sobre Android, vamos hoje aprimorar o nosso formulário. No último post, os Restaurantes, ao serem adicionados, eram listados na parte superior da tela. Com o post de hoje, eles passarão a ser listados com o endereço e um ícone identificando o tipo de restaurante que se trata.

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

package net.rafaeltoledo.restaurante;
import java.util.ArrayList;
import java.util.List;
import net.rafaeltoledo.restaurante.model.Restaurante;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioGroup;
public class ListaRestaurantes extends Activity {
List listaRestaurantes = new ArrayList();
ArrayAdapter adaptador = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button salvar = (Button) findViewById(R.id.salvar);
salvar.setOnClickListener(onSave);
ListView lista = (ListView) findViewById(R.id.restaurantes);
adaptador = new ArrayAdapter(this,
android.R.layout.simple_list_item_1, listaRestaurantes);
lista.setAdapter(adaptador);
}
private OnClickListener onSave = new OnClickListener() {
public void onClick(View arg0) {
Restaurante r = new Restaurante();
EditText nome = (EditText) findViewById(R.id.nome);
EditText endereco = (EditText) findViewById(R.id.end);
r.setNome(nome.getText().toString());
r.setEndereco(endereco.getText().toString());
RadioGroup tipos = (RadioGroup) findViewById(R.id.tipos);
switch (tipos.getCheckedRadioButtonId()) {
case R.id.rodizio:
r.setTipo("rodizio");
break;
case R.id.fast_food:
r.setTipo("fast_food");
break;
case R.id.a_domicilio:
r.setTipo("a_domicilio");
break;
}
adaptador.add(r);
}
};
class AdaptadorRestaurante extends ArrayAdapter {
AdaptadorRestaurante() {
super(ListaRestaurantes.this, android.R.layout.simple_list_item_1,
listaRestaurantes);
}
}
}

O próximo passo é ajustarmos nosso layout para a nossa nova lista, já que  nessa nova listagem teremos nome, endereço 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 linha.xml e digite o seguinte conteúdo para ele:

<?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="horizontal"
android:padding="4dip">
<ImageView android:id="@+id/icone"
android:layout_wi<dth="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="4dip" />
<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:gravity="center_vertical"
android:textStyle="bold"
android:singleLine="true"
android:ellipsize="end" />
<TextView android:id="@+id/endereco"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:singleLine="true"
android:ellipsize="end" />
</LinearLayout>
</LinearLayout>
view raw linha.xml hosted with ❤ by GitHub

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 restaurante e o endereço.

O próximo passo é colocar as imagens em res/drawable. As imagens você pode baixar aqui. Se seu projeto tem vários diretórios chamados drawable (drawable-ldpi, por exemplo), renomeie o diretório drawable-mdpi para drawable e exclua os outros. Agora, coloque as três imagens baixadas nessa pasta.

Agora, vamos sobrescrever o método getView() na classe AdaptadorRestaurante. Este método é o responsável por exibir os itens na tela. Assim, vamos através dele utilizar o layout definido em linha.xml. Dessa forma, o arquivo ListaRestaurantes fica assim:

package net.rafaeltoledo.restaurante;
import java.util.ArrayList;
import java.util.List;
import net.rafaeltoledo.restaurante.model.Restaurante;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RadioGroup;
import android.widget.TextView;
public class ListaRestaurantes extends Activity {
List listaRestaurantes = new ArrayList();
ArrayAdapter adaptador = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button salvar = (Button) findViewById(R.id.salvar);
salvar.setOnClickListener(onSave);
ListView lista = (ListView) findViewById(R.id.restaurantes);
adaptador = new ArrayAdapter(this,
android.R.layout.simple_list_item_1, listaRestaurantes);
lista.setAdapter(adaptador);
}
private OnClickListener onSave = new OnClickListener() {
public void onClick(View arg0) {
Restaurante r = new Restaurante();
EditText nome = (EditText) findViewById(R.id.nome);
EditText endereco = (EditText) findViewById(R.id.end);
r.setNome(nome.getText().toString());
r.setEndereco(endereco.getText().toString());
RadioGroup tipos = (RadioGroup) findViewById(R.id.tipos);
switch (tipos.getCheckedRadioButtonId()) {
case R.id.rodizio:
r.setTipo("rodizio");
break;
case R.id.fast_food:
r.setTipo("fast_food");
break;
case R.id.a_domicilio:
r.setTipo("a_domicilio");
break;
}
adaptador.add(r);
}
};
class AdaptadorRestaurante extends ArrayAdapter {
AdaptadorRestaurante() {
super(ListaRestaurantes.this, android.R.layout.simple_list_item_1,
listaRestaurantes);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View linha = convertView;
if (linha == null) {
LayoutInflater inflater = getLayoutInflater();
linha = inflater.inflate(R.layout.linha, null);
}
Restaurante r = listaRestaurantes.get(position);
((TextView) linha.findViewById(R.id.titulo)).setText(r.getNome());
((TextView) linha.findViewById(R.id.endereco)).setText(r.getEndereco());
ImageView icone = (ImageView) linha.findViewById(R.id.icone);
if (r.getTipo().equals("rodizio")) {
icone.setImageResource(R.drawable.rodizio);
} else if (r.getTipo().equals("fast_food")) {
icone.setImageResource(R.drawable.fast_food);
} else {
icone.setImageResource(R.drawable.entrega);
}
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, de forma que o nosso arquivo ListaRestaurantes.java fique assim:

package net.rafaeltoledo.restaurante;
import java.util.ArrayList;
import java.util.List;
import net.rafaeltoledo.restaurante.model.Restaurante;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RadioGroup;
import android.widget.TextView;
public class ListaRestaurantes extends Activity {
List listaRestaurantes = new ArrayList();
ArrayAdapter adaptador = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button salvar = (Button) findViewById(R.id.salvar);
salvar.setOnClickListener(onSave);
ListView lista = (ListView) findViewById(R.id.restaurantes);
adaptador = new ArrayAdapter(this,
android.R.layout.simple_list_item_1, listaRestaurantes);
lista.setAdapter(adaptador);
}
private OnClickListener onSave = new OnClickListener() {
public void onClick(View arg0) {
Restaurante r = new Restaurante();
EditText nome = (EditText) findViewById(R.id.nome);
EditText endereco = (EditText) findViewById(R.id.end);
r.setNome(nome.getText().toString());
r.setEndereco(endereco.getText().toString());
RadioGroup tipos = (RadioGroup) findViewById(R.id.tipos);
switch (tipos.getCheckedRadioButtonId()) {
case R.id.rodizio:
r.setTipo("rodizio");
break;
case R.id.fast_food:
r.setTipo("fast_food");
break;
case R.id.a_domicilio:
r.setTipo(";a_domicilio");
break;
}
adaptador.add(r);
}
};
class AdaptadorRestaurante extends ArrayAdapter {
AdaptadorRestaurante() {
super(ListaRestaurantes.this, android.R.layout.simple_list_item_1,
listaRestaurantes);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View linha = convertView;
if (linha == null) {
LayoutInflater inflater = getLayoutInflater();
linha = inflater.inflate(R.layout.linha, null);
}
Restaurante r = listaRestaurantes.get(position);
((TextView) linha.findViewById(R.id.titulo)).setText(r.getNome());
((TextView) linha.findViewById(R.id.endereco)).setText(r.getEndereco());
ImageView icone = (ImageView) linha.findViewById(R.id.icone);
if (r.getTipo().equals("rodizio")) {
icone.setImageResource(R.drawable.rodizio);
} else if (r.getTipo().equals("fast_food")) {
icone.setImageResource(R.drawable.fast_food);
} else {
icone.setImageResource(R.drawable.entrega);
}
return linha;
}
}
static class ArmazenadorRestaurante {
private TextView nome = null;
private TextView endereco = null;
private ImageView icone = null;
ArmazenadorRestaurante(View linha) {
nome = (TextView) linha.findViewById(R.id.titulo);
endereco = (TextView) linha.findViewById(R.id.endereco);
icone = (ImageView) linha.findViewById(R.id.icone);
}
void popularFormulario(Restaurante r) {
nome.setText(r.getNome());
endereco.setText(r.getEndereco());
if (r.getTipo().equals("rodizio")) {
icone.setImageResource(R.drawable.rodizio);
} else if (r.getTipo().equals("fast_food")) {
icone.setImageResource(R.drawable.fast_food);
} else {
icone.setImageResource(R.drawable.entrega);
}
}
}
}

Agora, vamos fazer o método getView utilizar a classe ArmazenadorRestaurante para montar os objetos na lista, e alteramos as referências ao ArrayAdapter para o nosso AdaptadorRestaurante, finalizando o nosso tutorial. Lembre-se de também alterar, no construtor do nosso restaurante, a referência passada para o construtor da super-classe do nosso arquivo linha.xml.

package net.rafaeltoledo.restaurante;
import java.util.ArrayList;
import java.util.List;
import net.rafaeltoledo.restaurante.model.Restaurante;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RadioGroup;
import android.widget.TextView;
public class ListaRestaurantes extends Activity {
List listaRestaurantes = new ArrayList();
AdaptadorRestaurante adaptador = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button salvar = (Button) findViewById(R.id.salvar);
salvar.setOnClickListener(onSave);
ListView lista = (ListView) findViewById(R.id.restaurantes);
adaptador = new AdaptadorRestaurante();
lista.setAdapter(adaptador);
}
private OnClickListener onSave = new OnClickListener() {
public void onClick(View arg0) {
Restaurante r = new Restaurante();
EditText nome = (EditText) findViewById(R.id.nome);
EditText endereco = (EditText) findViewById(R.id.end);
r.setNome(nome.getText().toString());
r.setEndereco(endereco.getText().toString());
RadioGroup tipos = (RadioGroup) findViewById(R.id.tipos);
switch (tipos.getCheckedRadioButtonId()) {
case R.id.rodizio:
r.setTipo("rodizio");
break;
case R.id.fast_food:
r.setTipo("fast_food");
break;
case R.id.a_domicilio:
r.setTipo("a_domicilio");
break;
}
adaptador.add(r);
}
};
class AdaptadorRestaurante extends ArrayAdapter {
AdaptadorRestaurante() {
super(ListaRestaurantes.this, R.layout.linha,
listaRestaurantes);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View linha = convertView;
ArmazenadorRestaurante armazenador = null;
if (linha == null) {
LayoutInflater inflater = getLayoutInflater();
linha = inflater.inflate(R.layout.linha, parent, false);
armazenador = new ArmazenadorRestaurante(linha);
linha.setTag(armazenador);
} else {
armazenador = (ArmazenadorRestaurante) linha.getTag();
}
armazenador.popularFormulario(listaRestaurantes.get(position));
return linha;
}
}
static class ArmazenadorRestaurante {
private TextView nome = null;
private TextView endereco = null;
private ImageView icone = null;
ArmazenadorRestaurante(View linha) {
nome = (TextView) linha.findViewById(R.id.titulo);
endereco = (TextView) linha.findViewById(R.id.endereco);
icone = (ImageView) linha.findViewById(R.id.icone);
}
void popularFormulario(Restaurante r) {
nome.setText(r.getNome());
endereco.setText(r.getEndereco());
if (r.getTipo().equals("rodizio")) {
icone.setImageResource(R.drawable.rodizio);
} else if (r.getTipo().equals("fast_food")) {
icone.setImageResource(R.drawable.fast_food);
} else {
icone.setImageResource(R.drawable.entrega);
}
}
}
}

Agora, se executarmos nosso aplicativo, teremos os itens adicionados à lista com seus respectivos ícones, de acordo com a categoria selecionada. O aplicativo em execução ficará assim:

Pra quem perdeu alguma parte, ou quiser baixar os resources utilizados, o projeto pode ser baixado aqui.

É isso pessoal! Espero que estejam gostando do tutorial 🙂

Tutorial Android #4 – Adicionando uma Lista

Olá pessoal! No tutorial de hoje da série sobre Android, vamos começar a adicionar funcionalidade ao nosso aplicativo. Com o post de hoje, conseguiremos adicionar os restaurantes, que serão listados no aplicativo.

Começando a colocar a mão na massa, o primeiro passo é trocarmos a instância única da classe Restaurante por uma lista de objetos. Porém, a simples mudança acarretará alguns erros no código. Assim, também precisaremos montar o objeto no método onClick e o adicionarmos na lista. Com essas alterações, o nosso arquivo ListaRestaurantes.java vai ficar assim:

package net.rafaeltoledo.restaurante;
import java.util.ArrayList;
import java.util.List;
import net.rafaeltoledo.restaurante.model.Restaurante;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;
public class ListaRestaurantes extends Activity {
List<Restaurante> listaRestaurantes = new ArrayList<Restaurante>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button salvar = (Button) findViewById(R.id.salvar);
salvar.setOnClickListener(onSave);
}
private OnClickListener onSave = new OnClickListener() {
public void onClick(View arg0) {
Restaurante r = new Restaurante();
EditText nome = (EditText) findViewById(R.id.nome);
EditText endereco = (EditText) findViewById(R.id.end);
r.setNome(nome.getText().toString());
r.setEndereco(endereco.getText().toString());
RadioGroup tipos = (RadioGroup) findViewById(R.id.tipos);
switch (tipos.getCheckedRadioButtonId()) {
case R.id.rodizio:
r.setTipo("rodizio");
break;
case R.id.fast_food:
r.setTipo("fast_food");
break;
case R.id.a_domicilio:
r.setTipo("a_domicilio");
break;
}
listaRestaurantes.add(r);
}
};
}

Basicamente, o que fizemos foi retirar o objeto r que estava no escopo da classe e o colocamos no método onClick. Além disso, criamos a lista chamada listaRestaurantes como um atributo da classe, e ao final do método onClick, adicionamos o objeto à lista.

O próximo passo é implementarmos o método toString() da classe Restaurante, já que ele será chamado quando os restaurantes forem listados. Para o nosso objetivo, nos interessa apenas o nome do restaurante, de forma que o método toString() pode retornar o método getNome(). Dessa forma, nossa classe Restaurante fica assim:

package net.rafaeltoledo.restaurante.model;
public class Restaurante {
private String nome = "";
private String endereco = "";
private String tipo = "";
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getEndereco() {
return endereco;
}
public void setEndereco(String endereco) {
this.endereco = endereco;
}
public String getTipo() {
return tipo;
}
public void setTipo(String tipo) {
this.tipo = tipo;
}
@Override
public String toString() {
return getNome();
}
}
view raw Restaurante.java hosted with ❤ by GitHub

Agora temos a parte mais desafiadora, que é exatamente mostrar a lista de restaurantes na tela de acordo que formos adicionando-os. Uma forma de fazer isso é utilizando o RelativeLayout, de forma que o formulário permaneça na parte de baixo da tela e os restaurantes adicionados sejam listados na parte superior. Vamos alterar o arquivo main.xml para que fique com esse aspecto:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TableLayout
android:id="@+id/detalhes"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:stretchColumns="1">
<TableRow>
<TextView android:text="Nome:" />
<EditText android:id="@+id/nome" />
</TableRow>
<TableRow>
<TextView android:text="Endereço:" />
<EditText android:id="@+id/end" />
</TableRow>
<TableRow>
<TextView android:text="Tipo:" />
<RadioGroup android:id="@+id/tipos">
<RadioButton
android:id="@+id/rodizio"
android:text="Rodízio" />
<RadioButton
android:id="@+id/fast_food"
android:text="Fast Food" />
<RadioButton
android:id="@+id/a_domicilio"
android:text="A Domicílio" />
</RadioGroup>
</TableRow>
<Button
android:id="@+id/salvar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Salvar" />
</TableLayout>
<ListView
android:id="@+id/restaurantes"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_above="@id/detalhes" />
</RelativeLayout>
view raw main.xml hosted with ❤ by GitHub

Basicamente o que fizemos foi englobar o TableLayout que tínhamos dentro do RelativeLayout, ajustando suas dimensões. Além disso, tivemos também um item chamado ListView, definido pelo nome restaurantes, que será quem armazenará a nossa lista de restaurantes. Um importante parâmetro é o android:layout_above que indicará que nosso TableLayout, agora nomeado como detalhes, será exibido logo em seguida ao nosso RelativeLayout.

Se executarmos nosso aplicativo agora, ele deverá ter essa aparência:

Agora, precisamos fazer alguns ajustes na nossa Activity para que os elementos sejam adicionados e listados. Abra o arquivo ListaRestaurantes.java novamente e edite-o:

package net.rafaeltoledo.restaurante;
import java.util.ArrayList;
import java.util.List;
import net.rafaeltoledo.restaurante.model.Restaurante;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioGroup;
public class ListaRestaurantes extends Activity {
List<Restaurante> listaRestaurantes = new ArrayList<Restaurante>();
ArrayAdapter<Restaurante> adaptador = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button salvar = (Button) findViewById(R.id.salvar);
salvar.setOnClickListener(onSave);
ListView lista = (ListView) findViewById(R.id.restaurantes);
adaptador = new ArrayAdapter<Restaurante>(this,
android.R.layout.simple_list_item_1, listaRestaurantes);
lista.setAdapter(adaptador);
}
private OnClickListener onSave = new OnClickListener() {
public void onClick(View arg0) {
Restaurante r = new Restaurante();
EditText nome = (EditText) findViewById(R.id.nome);
EditText endereco = (EditText) findViewById(R.id.end);
r.setNome(nome.getText().toString());
r.setEndereco(endereco.getText().toString());
RadioGroup tipos = (RadioGroup) findViewById(R.id.tipos);
switch (tipos.getCheckedRadioButtonId()) {
case R.id.rodizio:
r.setTipo("rodizio");
break;
case R.id.fast_food:
r.setTipo("fast_food");
break;
case R.id.a_domicilio:
r.setTipo("a_domicilio");
break;
}
adaptador.add(r);
}
};
}

O que fizemos foi adicionar o elemento adaptador, do tipo ArrayAdapter. É ele quem fará a montagem dos restaurantes adicionados na tela. Definimos a forma como ele funcionará em seu construtor, na linha 31, indicando o segundo parâmetro android.R.layout.simple_list_item_1, dizendo que será uma lista da classe Restaurante, e passando o parâmetro listaRestaurantes. Vinculamos o adaptador, então, ao item ListView que foi declarado no main.xml, e que o obtemos através do método findViewById(). Assim, chamamos seu método setAdapter e passamos o nosso adaptador.

Ao final, no método onClick, ao invés de adicionarmos o restaurante à lista, adicionamos ao adaptador. O resultado será a lista de restaurantes sendo criada em nosso aplicativo:

Bom, por hoje é isso! Pra quem teve problemas, pode baixar o projeto aqui.

Até a próxima!