sexta-feira, 15 de maio de 2015

Trabalhando com listViews (Caixas de listas)

Neste tutorial aprenderemos como utilizar as famosas "caixas de listas" (listViews). A ideia é apresentar ao usuário uma série de opções em uma tela, para sua escolha, dispostas na forma de linhas roláveis, conforme ilustrado na imagem:






Primeiro vamos criar um novo projeto em nosso ambiente de desenvolvimento, e nomeá-lo "projetoListView".

Depois, vamos abrir a pasta "res" (resources) e clicar com o botão direito do mouse sobre a pasta "layout", escolhendo a opção "New->Android XML File", ou seja, vamos criar um novo layout de tela.

Na janela que se abre, vamos digitar o nome da nova tela: "selecao_funcionario" e clicar no botão "OK".

Substitua, então, o código do novo arquivo pelo que se segue:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/listViewFuncionarios"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:cacheColorHint="#00000000"
        android:padding="0dp" >
    </ListView>

</LinearLayout>


Experimente alterar o modo de visualização do layout para "Graphical Layout" e perceba que já aparece uma prévia de como será disposta a lista. Mas falta ainda configurar a aparência individual das linhas.

Vamos, portanto, criar um novo arquivo xml, clicando com o botão direito do mouse sobre "layout" e escolhendo "New->Android XML File". Vamos nomeá-lo "linha_funcionario" e depois clicar em "OK".

Vamos agora substituir por completo o código do arquivo criado pelo código abaixo:

<?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
        android:id="@+id/linearLayoutLinha"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="5dp"
        android:paddingTop="5dp" >

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

            <ImageView
                android:id="@+id/imageViewFoto"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:padding="5dp"
                android:src="@drawable/ic_launcher" />
        </LinearLayout>

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

            <TextView
                android:id="@+id/textViewNome"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:padding="2dp"
                android:text="Nome do funcionário" />

            <TextView
                android:id="@+id/TextViewCargo"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:padding="2dp"
                android:text="Cargo" />
        </LinearLayout>
    </LinearLayout>

</LinearLayout>


Com isto definimos o layout de uma tela que conterá uma lista de funcionários. Também criamos o design da linha individual da lista, cada uma sendo composta pela foto do funcionário, nome e cargo.

Precisaremos agora criar uma classe "FuncionarioDTO", descrevendo os campos de um item "funcionário".  Ele será composto pela foto do funcionário, nome e cargo. Então, na pasta "src" (sources), clique sobre o nome do pacote ("com.example.projetolistview") e escolha "New->Class". Então, na nova classe  criada, substitua integralmente pelo código abaixo:

package com.example.projetolistview;

import android.graphics.Bitmap;

public class FuncionarioDTO
{

   private Bitmap foto;
   private String nome;
   private String cargo;
  
   public Bitmap getFoto()
   {
      return foto;
   }
   public void setFoto(Bitmap foto)
   {
      this.foto=foto;
   }
   public String getNome()
   {
      return nome;
   }
   public void setNome(String nome)
   {
      this.nome=nome;
   }
   public String getCargo()
   {
      return cargo;
   }
   public void setCargo(String cargo)
   {
      this.cargo=cargo;
   }
  
}


Vamos criar também a classe "ArrayListAdapter" (pelo mesmo procedimento apresentado) e substituir pelo código abaixo:


package com.example.projetolistview;

import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import com.example.projetolistview.R;

public class ArrayListAdapter extends ArrayAdapter<Object>
{

   protected Context context;
   protected ArrayList<?> list=null;
   public int count=20;
   protected ArrayListAdapter.Callback callback=null;
   private int layout=R.layout.linha_funcionario;

   public ArrayListAdapter(Context context, int layout, ArrayList<?> list)
   {
      super(context, 0);

      this.context=context;
      this.list=list;

   }

   public ArrayListAdapter(Context context, ArrayList<?> list)
   {
      super(context, 0);

      this.context=context;
      this.list=list;

   }

   public void setLayout(int resLayoutId)
   {
      this.layout=resLayoutId;
   }

   public int getLayout()
   {
      return this.layout;
   }

   public interface Callback
   {
      View execute(final int position, final View convertView, final ViewGroup parent);
   }

   public void setCallback(Callback callback2)
   {
      this.callback=callback2;
   }

   @Override
   public void notifyDataSetChanged()
   {
      super.notifyDataSetChanged();
   }

   @Override
   public int getCount()
   {
      return list.size();
   }

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

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

   @Override
   public View getView(int position, View convertView, ViewGroup parent)
   {

      LayoutInflater inflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      View view=inflater.inflate(getLayout(), null);

      if (list != null)
      {

         if (callback != null)
         {
            view=callback.execute(position, view, parent);
         }

      }

      return view;
   }

}

Por último, vamos abrir o arquivo "MainActivity.java" e substituir o código por completo, pelo disposto abaixo:


package com.example.projetolistview;

import java.util.ArrayList;

import com.example.projetolistview.R;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.view.ContextMenu;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity
{

   Context ctx;
   private ListView listViewFuncionarios;
   private ArrayListAdapter adapter;

   // Define uma lista de funcionarios.
   private ArrayList<FuncionarioDTO> listaDeFuncionarios;

  
   @Override
   protected void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.selecao_funcionario);
     
      // Cria a lista de funcionarios e carrega.
      listaDeFuncionarios = new ArrayList<FuncionarioDTO>();
      listaDeFuncionarios = carregarFuncionarios();    
     
      // Obtém o contexto da tela.
      ctx=this;

      // Obtém o elemento ListView para manipulação.
      listViewFuncionarios=(ListView) findViewById(R.id.listViewFuncionarios);

      // Cria o ArrayListAdapter e o configura.
      adapter=new ArrayListAdapter(this, listaDeFuncionarios);
      adapter.setLayout(R.layout.linha_funcionario);
      adapter.notifyDataSetChanged();
      adapter.setCallback(new ArrayListAdapter.Callback()
      {

         @Override
         public View execute(final int position, final View view, final ViewGroup parent)
         {
            String nome="";
            String cargo="";
            Bitmap foto;
           
            if (position <= listaDeFuncionarios.size())
            {
               // Para cada elemento da lista, obtém os campos, para preenchimento posterior.
               nome=listaDeFuncionarios.get(position).getNome();
               cargo=listaDeFuncionarios.get(position).getCargo();
               foto=listaDeFuncionarios.get(position).getFoto();

               // Preenche o conteúdo dos campos do listView.
               final TextView textViewNome=(TextView) view.findViewById(R.id.textViewNome);
               textViewNome.setText(nome);

               final TextView textViewCargo=(TextView) view.findViewById(R.id.TextViewCargo);
               textViewCargo.setText(cargo);
              
               final ImageView imageViewFoto=(ImageView) view.findViewById(R.id.imageViewFoto);
               imageViewFoto.setImageBitmap(foto);
              
               final LinearLayout linha=(LinearLayout) view.findViewById(R.id.linearLayoutLinha);

               // Alterna as cores das linhas.
               if (position % 2 == 0)
               {
                  linha.setBackgroundColor(Color.LTGRAY);
               }
               else
               {
                  linha.setBackgroundColor(Color.WHITE);
               }
            }

            return view;
         }
      });

      listViewFuncionarios.setAdapter(adapter);
      listViewFuncionarios.setFastScrollEnabled(true);

      // Define o comportamento do clique sobre um dos itens.
      listViewFuncionarios.setOnItemClickListener(new ListView.OnItemClickListener()
      {
         @Override
         public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3)
         {
            // Recupera nome e cargo do item selecionado pelo usuário.
            String nome  = listaDeFuncionarios.get(pos).getNome();
            String cargo = listaDeFuncionarios.get(pos).getCargo();
           
            // Mostra mensagem na tela.
            Toast.makeText(getApplicationContext(), "Funcionário " + nome + " (" + cargo +  ") selecionado", Toast.LENGTH_SHORT).show();
           
         }
      });

      listViewFuncionarios.setOnScrollListener(new AbsListView.OnScrollListener()
      {

         int page=1;
         private int currentFirstVisibleItem;
         private int currentVisibleItemCount;
         private int currentScrollState;
         private boolean isLoading;
         private boolean mIsScrollingUp;
         private int mLastFirstVisibleItem;

         public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
         {
            this.currentFirstVisibleItem=firstVisibleItem;
            this.currentVisibleItemCount=visibleItemCount;
         }

         public void onScrollStateChanged(AbsListView view, int scrollState)
         {
            this.currentScrollState=scrollState;

            if (this.currentVisibleItemCount > 0 && this.currentScrollState == SCROLL_STATE_IDLE)
            {
              
               if (!isLoading)
               {
                  isLoading=true;
               }
            }
         }

      });

      registerForContextMenu(listViewFuncionarios);
   }

   public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
   {

      final AdapterView.AdapterContextMenuInfo info=(AdapterView.AdapterContextMenuInfo) menuInfo;

   }

  
   private ArrayList<FuncionarioDTO> carregarFuncionarios()
   {
           
      FuncionarioDTO funcionarioDTO;
     
      // Cria um objeto que armazenará a foto do funcionário.
      // Neste exemplo, utilizaremos a mesma foto para todos os funcionários.
      // Aqui estamos obtendo a imagem da foto a partir de um PNG (ic_laucher) da pasta drawable.
      Bitmap foto;
      foto=BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.ic_launcher);
     
      // Preenche os funcionários um a um e os acrescenta à lista.
      funcionarioDTO = new FuncionarioDTO();
      funcionarioDTO.setFoto(foto);
      funcionarioDTO.setNome("João Silva");
      funcionarioDTO.setCargo("Auxiliar administrativo");
      listaDeFuncionarios.add(funcionarioDTO);
     
      funcionarioDTO = new FuncionarioDTO();
      funcionarioDTO.setFoto(foto);
      funcionarioDTO.setNome("Maria Barbosa");
      funcionarioDTO.setCargo("Cozinheira");
      listaDeFuncionarios.add(funcionarioDTO);
     
      funcionarioDTO = new FuncionarioDTO();
      funcionarioDTO.setFoto(foto);
      funcionarioDTO.setNome("Helena Dias");
      funcionarioDTO.setCargo("Gerente");
      listaDeFuncionarios.add(funcionarioDTO);
     
      funcionarioDTO = new FuncionarioDTO();
      funcionarioDTO.setFoto(foto);
      funcionarioDTO.setNome("Pedro Salas");
      funcionarioDTO.setCargo("Diretor");
      listaDeFuncionarios.add(funcionarioDTO);
     
      funcionarioDTO = new FuncionarioDTO();
      funcionarioDTO.setFoto(foto);
      funcionarioDTO.setNome("Arnaldo Xavier");
      funcionarioDTO.setCargo("Ascensorista");
      listaDeFuncionarios.add(funcionarioDTO);
     
      funcionarioDTO = new FuncionarioDTO();
      funcionarioDTO.setFoto(foto);
      funcionarioDTO.setNome("Luiz Quintela");
      funcionarioDTO.setCargo("Programador");
      listaDeFuncionarios.add(funcionarioDTO);
     
      funcionarioDTO = new FuncionarioDTO();
      funcionarioDTO.setFoto(foto);
      funcionarioDTO.setNome("Ana Afonso");
      funcionarioDTO.setCargo("Analista de sistemas");  
      listaDeFuncionarios.add(funcionarioDTO);

      funcionarioDTO = new FuncionarioDTO();
      funcionarioDTO.setFoto(foto);
      funcionarioDTO.setNome("Manoela Farias");
      funcionarioDTO.setCargo("Advogada");  
      listaDeFuncionarios.add(funcionarioDTO);

      funcionarioDTO = new FuncionarioDTO();
      funcionarioDTO.setFoto(foto);
      funcionarioDTO.setNome("Cesar Alfredo");
      funcionarioDTO.setCargo("Contador");  
      listaDeFuncionarios.add(funcionarioDTO);

      funcionarioDTO = new FuncionarioDTO();
      funcionarioDTO.setFoto(foto);
      funcionarioDTO.setNome("Marcio Teixeira");
      funcionarioDTO.setCargo("Vendedor");  
      listaDeFuncionarios.add(funcionarioDTO);
     
      funcionarioDTO = new FuncionarioDTO();
      funcionarioDTO.setFoto(foto);
      funcionarioDTO.setNome("Daniela Dantas");
      funcionarioDTO.setCargo("Advogada");  
      listaDeFuncionarios.add(funcionarioDTO);

      funcionarioDTO = new FuncionarioDTO();
      funcionarioDTO.setFoto(foto);
      funcionarioDTO.setNome("Otavio Cintra");
      funcionarioDTO.setCargo("Programador");  
      listaDeFuncionarios.add(funcionarioDTO);

      funcionarioDTO = new FuncionarioDTO();
      funcionarioDTO.setFoto(foto);
      funcionarioDTO.setNome("Dhenis Pereira");
      funcionarioDTO.setCargo("Gerente");  
      listaDeFuncionarios.add(funcionarioDTO);
     
      funcionarioDTO = new FuncionarioDTO();
      funcionarioDTO.setFoto(foto);
      funcionarioDTO.setNome("Erica Montalvo");
      funcionarioDTO.setCargo("Vendedora");  
      listaDeFuncionarios.add(funcionarioDTO);

      // Retorna a lista de funcionários criada.
      return listaDeFuncionarios;
   }
  
}


O que fizemos no MainActivity foi um método que cria uma lista de funcionários fictícios. Esse método devolve a lista, que é então utilizada para configurar o ArrayListAdapter. O resultado é uma tela com uma lista de funcionários rolável. Ao clicar sobre o nome de um funcionário, o usuário verá uma mensagem informando o nome e cargo do item "funcionário" escolhido.

Para os que preferirem obter o código-fonte completo, disponibilizo-o para download. Quem quiser apenas instalar o aplicativo no celular, segue o APK.

Ficamos por aqui. Até a próxima!




Nenhum comentário:

Postar um comentário