Neste mês irei
compartilhar uma dúvida que me surgiu no transcorrer do desenvolvimento de um
projeto: como implementar o uso do componente ListView existindo uma interação
de dados, melhor dizendo, como embutir um componente EditText dentro do
ListView. Precisei deste recurso em meu projeto para criar uma tela de pesquisa
de Produtos mais ágil, podendo interagir com o campo quantidade
automaticamente. É importante lembrar que neste artigo terei como base o artigo
“Android - Aprendendo a utilizar o ListView” do mês de Novembro de 2012 e mais
outros pequenos trechos de códigos pesquisados na internet e modificados
conforme a necessidade no momento.
Para quem nunca trabalhou com o componente “ListView” recomendo antes fazer uma leitura de nosso artigo citado acima, o qual aborda mais detalhadamente o funcionamento do mesmo.
Teremos também como base a implementação da classe “ArrayAdapter”, servindo para personalizar e montar o lay-out desejado.
Para quem nunca trabalhou com o componente “ListView” recomendo antes fazer uma leitura de nosso artigo citado acima, o qual aborda mais detalhadamente o funcionamento do mesmo.
Teremos também como base a implementação da classe “ArrayAdapter”, servindo para personalizar e montar o lay-out desejado.
Criando o Projeto
No primeiro
momento deveremos inicializar um projeto Android padrão, clicando em
“File/New/Android Application Project”, recomendo estar utilizando a versão “4”
em diante. Este projeto irá conter os arquivos “MainActivity.java” e
“activity_main.xml” (ambos criados automaticamente), até aqui não vimos nada de
novo. Ver Imagem 01.
![]() |
Figura 01: Exemplo Inicial.
|
Criando a Classe Produtos
Esta classe
será responsável por atribuir e obter todos os produtos existentes. Iremos
alimentá-la manualmente para facilitar o aprendizado (Ressalto que poderemos
alimentá-la de qualquer fonte de dados).
Ver abaixo a Listagem 01 comentada.
Ver abaixo a Listagem 01 comentada.
package
com.example.android_listviewinteracao;
import java.util.ArrayList;
import java.util.List;
Importaremos algumas
bibliotecas, sendo a “java.util.ArrayList” e a “java.util.List” para utilizar o
método ArrayList e List respectivamente, ambos para trabalhar com a classe
“Produtos” mais adiante.
public class Produtos
{
private static final long
serialVersionUID = 1L;
public int Id_Produto;
public String Descricao;
public Number Preco_Venda;
public int Qtd;
Teremos os atributos
Id_Produto (inteiro), Descricao (Texto), Preco_venda (Numérico) e Qtd
(inteiro). Todos terão os métodos “Get” e “Set” implementados a seguir.
public Produtos()
{
}
No
Construtor não colocaremos nenhuma codificação.
public int getId_Produto()
{
{
return Id_Produto;
}
public void setId_Produto(int id_produto)
{
{
Id_Produto = id_produto;
}
public String getDescricao()
{
{
return Descricao;
}
public void setDescricao(String descricao)
{
{
Descricao = descricao;
}
public Number getPreco_Venda()
{
{
return Preco_Venda;
}
public void setPreco_Venda(Number preco_Venda)
{
{
Preco_Venda = preco_Venda;
}
public int getQtd()
{
{
return Qtd;
}
public void setQtd(int qtd)
{
{
Qtd = qtd;
}
Já no método
“ListarProdutos” iremos retornar dados do tipo “List<Produtos>”, ou seja,
uma Lista de todos os produtos cadastrados. Veremos abaixo mais detalhadamente
a inserção manual de alguns objetos nesta lista. Esta função irá nos servir
para alimentar o ListView.
public
List<Produtos> ListarProdutos()
{
List<Produtos> lista_produto = new
ArrayList<Produtos>();
Produtos
produto = new Produtos();
produto.setId_Produto(1);
produto.setDescricao("Arroz
Prato Fino 5Kg");
produto.setPreco_Venda(9.80);
lista_produto.add(produto);
Produtos
produto2 = new Produtos();
produto2.setId_Produto(2);
produto2.setDescricao("Feijão
Carioquinha 1 kg");
produto2.setPreco_Venda(4.30);
lista_produto.add(produto2);
Produtos
produto3 = new Produtos();
produto3.setId_Produto(3);
produto3.setDescricao("Batata Elma Chips - Tamanho Família");
produto3.setPreco_Venda(2.99);
lista_produto.add(produto3);
Produtos
produto4 = new Produtos();
produto4.setId_Produto(4);
produto4.setDescricao("Macarrão
Orsi Espaguete");
produto4.setPreco_Venda(1.98);
lista_produto.add(produto4);
Produtos
produto5 = new Produtos();
produto5.setId_Produto(5);
produto5.setDescricao("Azeite
de Oliva 450 ml");
produto5.setPreco_Venda(7.56);
lista_produto.add(produto5);
Produtos
produto6 = new Produtos();
produto6.setId_Produto(6);
produto6.setDescricao("Refrigerante Coca Cola 2 Litros
Retornável");
produto6.setPreco_Venda(3.80);
lista_produto.add(produto6);
Produtos
produto7 = new Produtos();
produto7.setId_Produto(7);
produto7.setDescricao("Água
Mineral 1,5 litros");
produto7.setPreco_Venda(2.09);
lista_produto.add(produto7);
return lista_produto;
}
}
Listagem 01: Classe Produtos.
Listagem 01: Classe Produtos.
Criando o Lay-out do ListView
“theclubadapter.xml”
Na Figura 02
teremos o lay-out proposto contendo os elementos: 3 componentes TextView, sendo
“txtProd”, “txtId_Produto” e “txtPreco” servindo para listar a Descrição, Id e
Preço de Venda do Produto. Teremos também um EditText “edtQtd” para atribuir a
quantidade do Produto.
![]() |
Figura 02: Lay-Out ListView. |
Com base no
lay-out criado anteriormente teremos o código XML correspondente na Listagem
02.
<?xml version="1.0"
encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="90dip"
android:gravity="right"
android:orientation="vertical"
android:paddingBottom="5dip"
android:paddingTop="5dip"
tools:ignore="InvalidId" >
<LinearLayout
android:id="@+id/linearLayout02"
android:layout_width="match_parent"
android:layout_height="100dp"
android:gravity="right"
android:orientation="horizontal" >
<LinearLayout
android:id="@+id/LinearLayout03"
android:layout_width="135dp"
android:layout_height="84dp"
android:layout_weight="0.99"
android:orientation="vertical" >
<TextView
android:id="@+id/txtProduto"
android:layout_width="match_parent"
android:layout_height="30dp"
android:text="@string/txtprod"android:textAppearance="?android:attr/textAppearanceLarge"
/>
<LinearLayout
android:id="@+id/linearLayout06"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/txtId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="top"
android:text="@string/id_"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="15dp"
android:typeface="sans" />
<TextView
android:id="@+id/txtIdProduto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:text="@string/txtid_produto"
android:textAppearance= "?android:attr/textAppearanceSmall"
android:textSize="15dp"
android:typeface="sans" />
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout07"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:id="@+id/linearLayout08"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
<TextView
android:id="@+id/txtp1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="top"
android:text="P1:"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="15dp"
android:typeface="sans" />
<TextView
android:id="@+id/txtPreco1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:text="txtPreco1"
android:textAppearance= "?android:attr/textAppearanceSmall"
android:textSize="15dp"
android:typeface="sans" />
<TextView
android:id="@+id/txtEspaco1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" "
android:textAppearance="?android:attr/textAppearanceSmall"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout09"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
<TextView
android:id="@+id/txtEspaco2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" "
android:textAppearance="?android:attr/textAppearanceSmall"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/LinearLayout05"
android:layout_width="82dp"
android:layout_height="90dp"
android:orientation="vertical" >
<TextView
android:id="@+id/txtQtd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Qtd:"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="20dp" />
<EditText
android:id="@+id/edtQuantidade"
android:layout_width="79dp"
android:layout_height="40dp"
android:layout_margin="2dp"
android:inputType="numberDecimal"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:typeface="sans" >
</EditText>
</LinearLayout>
</LinearLayout>
</LinearLayout>
Listagem 02. Código XML do ListView.
Listagem 02. Código XML do ListView.
Criando e Codificando a Activity
“theclubadapter.java”
Na
atividade “theclubadapter.java” iremos concentrar todo o comportamento do
componente criado anteriormente. Iremos herdar da classe “ArrayAdapter” e
sobrescreveremos o método “getView”, necessário para atribuirmos os dados. Ver
Listagem 03 comentada.
package
com.example.android_listviewinteracao;
import java.util.List;
import android.annotation.SuppressLint;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import
android.widget.TextView;
Faremos o uso de algumas
bibliotecas citadas no bloco de código acima.
public class theclubadapter extends
ArrayAdapter<Produtos>
{
Como foi dito, esta classe
irá herdar da classe ArrayAdapter, tendo como objeto “Produtos” (Classe criada
para esta ocasião).
private final LayoutInflater inflater;
private final int resourceId;
private List<Produtos>
produtoitems;
O atributo do tipo
“LayoutInflater” chamado “inflater” será responsável por “inflar” nosso
listview com os dados do Contexto. Já o atributo inteiro “resourceId” receberá
o próprio lay-out “theclubadaper”. Por último temos um List<Produtos>,
variável responsável por armazenar todos os objetos do tipo Produto.
public theclubadapter(Context context, int resource, List<Produtos> produtos)
{
super(context, resource, produtos);
this.inflater = LayoutInflater.from(context);
this.resourceId = resource;
this.produtoitems = produtos;
}
Serão todos atribuídos no
Construtor de nossa classe. Lembrando que com o método “super” estamos chamado
o método de nossa classe pai. Antes de partirmos para os comentários referentes
ao método “getView”, será necessário descrever a classe estática
“ProdutosRepositorio” e mais outros dois métodos chamados “setupItem” e
“setVal1TextChangeListener”.
public static class ProdutosRepositorio
{
Produtos produtos;
TextView txtProduto;
TextView txtIdProduto;
TextView txtPreco1;
EditText edtQtd;
}
A classe pública estática “ProdutosRepositório”
será composta por todos os membros do ListView mais a classe Produtos. Faremos
o uso desta classe para ter um maior controle sobre a indexação dos registros
localizados no ListView.
private void
setupItem(ProdutosRepositorio repositorio)
{
repositorio.txtProduto.setText(repositorio.produtos.Descricao);
repositorio.txtIdProduto.setText(String.valueOf(repositorio.produtos.Id_Produto));
repositorio.txtPreco1.setText(String.valueOf(repositorio.produtos.Preco_Venda));
String Qtd = String.valueOf(repositorio.produtos.getQtd());
if (Qtd.equals("0"))
repositorio.edtQtd.setText("");
else
repositorio.edtQtd.setText(String.valueOf(repositorio.produtos.getQtd()));
}
Neste método atribuimos todos
os dados com origem da classe “ProdutosRepositorio”.
private void setVal1TextChangeListener(final ProdutosRepositorio
repositorio)
{
repositorio.edtQtd.addTextChangedListener(new TextWatcher()
{
@Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after)
{
{
}
@Override
public void onTextChanged(CharSequence s, int start,
int before, int count)
{
if(s.toString().length()>0)
repositorio.produtos.setQtd(Integer.parseInt(s.toString());
}
@Override
public void afterTextChanged(Editable s)
{
}
});
}
}
No método “setVal1TextChangeListener”
do componente EditText “Quantidade”, comparamos se o mesmo possui algum valor
para logo em seguida alimentarmos com o valor corrente. Utilizamos para isto o
método sobrescrito “OntextChanged”.
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ProdutosRepositorio repositorio = null;
convertView = inflater.inflate(resourceId, parent, false);
repositorio = new
ProdutosRepositorio();
repositorio.produtos = produtoitems.get(position);
repositorio.txtProduto = (TextView) convertView.findViewById(R.id.txtProduto);
repositorio.txtIdProduto = (TextView) convertView.findViewById(R.id.txtIdProduto);
repositorio.txtPreco1 = (TextView) convertView.findViewById(R.id.txtPreco1);
repositorio.edtQtd = (EditText)
convertView.findViewById(R.id.edtQuantidade);
setVal1TextChangeListener(repositorio);
convertView.setTag(repositorio);
setupItem(repositorio);
return convertView;
}
Após uma abordagem da classe
e das funções utilizadas, podemos finalizar com o método sobrescrito “getView”,
o qual fará todo o trabalho “pesado” de nossa classe. Ele será invocado toda
vez que atualizarmos nosso Listview, obtendo uma visão (view) para os dados na posição especificada no conjunto de
dados. Importante salientar que podemos criar um modo de exibição manualmente
ou inflá-lo a partir de um arquivo de layout XML. Teremos como parâmetro a
variável “Position” para nos retornar um valor inteiro da posição do item do
Listview, a “ConvertView” do tipo “View” para retornamos com as modificações
necessárias e por fim a “ViewGroup” chamada “Parent” que será recuperada como
parâmetro o tipo de “Layout”, por exemplo o “LinearLayout”.
1º Passo – Alimentaremos nossa
“View” através do método já comentado “inflate”.
2º Passo - Vamos criar uma
variável “repositorio” do tipo “ProdutosRepositorio” para atribuirmos todos os
componentes utilizados.
3º Passo – Disparamos o
método “setVal1TextChangeListener(repositorio)”.
4º Passo – Utilizamos o
método “convertView.setTag(repositorio)” para salvar o “ProdutosReposito” como
uma View.
5º Passo – Setamos os valores
e retornamos a view para ser utilizada.
Criando o Lay-out “activity_main.xml”
Este
será o “lay-out” principal, o qual irá fazer referência ao nosso “Listview”
personalizado. Devemos inserir um ListView e um Button (o qual irá listar e
carregar os produtos com quantidade maior que zero). Ver Imagem 03.
![]() |
Figura 03: Lay-out principal. |
O
código XML é bem simples, podendo ser conferido na listagem 03.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
>
<ListView
android:id="@+id/listViewProdutos"
android:layout_width="match_parent"
android:layout_height="600dp"
>
</ListView>
<Button
android:id="@+id/btnConfirmar"
android:layout_width="120dp"
android:layout_height="50dp"
android:onClick="Confirmar"
android:text="Confirmar"
/>
</LinearLayout>
Listagem
03: Tela Principal.
Codificando a Activity “MainActivity.java”
Para
entendermos um pouco mais, esta atividade ficará responsável por atribuir ao
ListView o “theclubAdapter.xml” e alimentá-lo através da classe “Produtos.java”.
Ao clicar no botão confirmar faremos uma varredura no mesmo para identificarmos
os itens que possuem o valor maior que zero para o campo quantidade. Atribuiremos
na classe “Produtos” com auxílio dos métodos “Sets” e em seguida
disponibilizaremos através de uma Lista podendo ser obtidos através dos métodos
“Gets”. (Neste caso poderíamos tanto utilizar estes dados nesta mesma Atividade
quanto em uma outra qualquer passando o objeto por parâmetro).
package
com.example.android_listviewinteracao;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.view.View;
import
android.widget.ArrayAdapter;
import android.widget.Button;
import
android.widget.ListView;
Importaremos algumas bibliotecas
necessárias para o bom funcionamento.
public class MainActivity extends Activity
{
Button btnConfirmar;
ListView listViewProdutos;
ArrayAdapter<Produtos> adapter;
Teremos três variáveis,
as duas primeiras são: uma do tipo “Button” e outra “ListView” (ambas fazem
referências aos componentes visíveis em nosso XML). A variável
“ArrayAdapter<Produtos>” irá armazenar toda a nossa classe personalizada.
@Override
protected void onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InicializaListeners();
ListarTheClubAdapter();
}
public void
InicializaListeners()
{
listViewProdutos = (ListView)
findViewById(R.id.listViewProdutos);
btnConfirmar =
(Button) findViewById(R.id.btnConfirmar);
}
public void
ListarTheClubAdapter()
{
Produtos produtos = new Produtos();
List<Produtos> lista_produtos =
produtos.ListarProdutos();
adapter = new theclubadapter(this, R.layout.theclubadapter, lista_produtos);
listViewProdutos.setAdapter(adapter);
}
No método “Oncreate”
apenas inicializaremos nossos Componentes e através do “ListarTheClubAdapter”
instanciaremos a classe “Produtos” para disparar o método “ListarProdutos”. A
variável “adapter” irá receber a classe “theclubadapter” com os parâmetros de
entrada: Contexto, tipo de layout e todos os dados em forma de lista.
private void MensagemInformativa(String mensagen) {
new AlertDialog.Builder(this)
.setTitle("The Club")
.setMessage(mensagen)
.setPositiveButton("OK", null)
.setCancelable(false)
.show();
}
Achei mais didádico
criar uma função chamada “MensagemInformativa” com o auxílio da classe
“Builder” para informar ao usuário todos os registros com quantidade maior que
zero.
public void Confirmar(View view)
{
ArrayList<Produtos> produtosporquantidade = new
ArrayList<Produtos>();
for(int i=0;i<adapter.getCount();i++)
{
int qtd = adapter.getItem(i).Qtd;
if (qtd > 0)
{
Produtos pro = new Produtos();
pro.setId_Produto(adapter.getItem(i).Id_Produto);
pro.setDescricao(adapter.getItem(i).Descricao);
pro.setPreco_Venda(adapter.getItem(i).Preco_Venda);
pro.setQtd(adapter.getItem(i).Qtd);
produtosporquantidade.add(pro);
}
}
for (int i = 0; i < produtosporquantidade.size();
i++)
{
MensagemInformativa("Id:
"+ String.valueOf(produtosporquantidade.get(i).getId_Produto())
+ "
Descrição: "+ String.valueOf(produtosporquantidade.get(i).getDescricao())
+ "
Preço Venda: "+ String.valueOf(produtosporquantidade.get(i).getPreco_Venda())
+ "
Quantidade: "+ String.valueOf(produtosporquantidade.get(i).getQtd()));
}
}
}
Por
fim o método “Confirmar” será disparado no evento “OnClick” do botão.
Possuiremos duas etapas, sendo: um laço para alimentar nossa classe e o outro
para carregar todos os dados atribuídos na mesma.
Teremos
uma ideia geral de nosso aplicativo conferindo a Figura 04.
![]() |
Figura 04: Exemplo funcionando. |
Caros
programadores, a ideia geral desta dica transformada em artigo foi de poder
demonstrar como devemos proceder com o desenvolvimento de um componente
específico para a plataforma Android, no nosso caso um ListView. O detalhe que
não podemos esquecer é que este ListView poderá tanto “listar” informações de
uma classe ou Banco de Dados quanto atribuir novos valores para o mesmo.
Podemos utilizar exemplos deste tipo em um Pedido de Venda, agilizando no
processo de escolha de um ou mais produtos. Poderíamos ter implementado também
um “EditText” para o Preço de Venda sem muito trabalho. Fica aí a dica, um
abraço e até o mês que vem!