Android – Filtrando dados de um ListView com um EditText (How to Filter ListView through EditText)

filter_listview_edittext_android

Quando nos deparamos com vários conteúdos em uma lista, a pesquisa sempre fica mais difícil. O Android nos proporciona uma classe chamada Filter que se responsabiliza em tratar o filtro.
Operações de filtragem realizado pelo Filter são realizadas de forma assíncrona. Quando esses métodos são chamados, um pedido de filtragem é postado em uma fila de pedidos e processados ​​mais tarde. Qualquer chamada para um desses métodos irá cancelar qualquer pedido de filtragem não executada anterior.
Abaixo veremos a utilização desse recurso:

Neste exemplo, vamos utilizar um ListView com a implementação de um BaseAdapter.

O código de layout xml deste exemplo é bem simples, vejamos:

<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:orientation="vertical">

    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPersonName" >
        <requestFocus />
    </EditText>

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >
    </ListView>

</LinearLayout>

(arquivo: activity_main.xml)

Como vamos utilizar um ListView Customizado (Veja mais sobre), vamos criar nosso próprio item na mão:

<?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" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

(arquivo: listview_item.xml)

Agora que temos nosso layout, vamos implementar nosso adapter, ele vai ficar responsável pela filtragem dos itens. (Não vou explicar detalhamente sobre o adapter caso tenham duvidas vejam em ListView Customizado (Veja mais sobre))

public class ListViewAdapter extends BaseAdapter {

    //Itens de exibição / filtrados
    private List<ListViewObjetos> itens_exibicao;
    //Essa lista contem todos os itens.
    private List<ListViewObjetos> itens;
    //Utilizado no getView para carregar e construir um item.
    private LayoutInflater layoutInflater;

    public ListViewAdapter(Context context, List<ListViewObjetos> itens) {
        this.itens = itens;
        this.itens_exibicao = itens;
        layoutInflater = LayoutInflater.from(context);
    }

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

    @Override
    public Object getItem(int arg0) {
        return itens_exibicao.get(arg0);
    }

    @Override
    public long getItemId(int arg0) {
        return itens_exibicao.get(arg0).getId();
    }

    @Override
    public View getView(int arg0, View arg1, ViewGroup arg2) {
        ItemHelper itemHelper = new ItemHelper();
        ListViewObjetos objeto = itens_exibicao.get(arg0);

        if (arg1 == null) {
            arg1 = layoutInflater.inflate(R.layout.listview_item, null);
            itemHelper.descricao = (TextView) arg1.findViewById(R.id.textView1);
            itemHelper.valor = (TextView) arg1.findViewById(R.id.textView2);
            arg1.setTag(itemHelper);
        } else {
            itemHelper = (ItemHelper) arg1.getTag();
        }

        itemHelper.descricao.setText("-> " + objeto.getId() + " - " + objeto.getDescricao());
        itemHelper.valor.setText(objeto.getValor());

        return arg1;
    }

    private class ItemHelper {

        TextView descricao, valor;
    }

    /** Método responsável pelo filtro. Utilizaremos em um EditText
     * 
     * @return 
     */
    public Filter getFilter() {
        Filter filter = new Filter() {

            @Override
            protected FilterResults performFiltering(CharSequence filtro) {
                FilterResults results = new FilterResults();
                //se não foi realizado nenhum filtro insere todos os itens.
                if (filtro == null || filtro.length() == 0) {
                    results.count = itens.size();
                    results.values = itens;
                } else {
                    //cria um array para armazenar os objetos filtrados.
                    List<ListViewObjetos> itens_filtrados = new ArrayList<ListViewObjetos>();

                    //percorre toda lista verificando se contem a palavra do filtro na descricao do objeto.
                    for (int i = 0; i < itens.size(); i++) {
                        ListViewObjetos data = itens.get(i);

                        filtro = filtro.toString().toLowerCase();
                        String condicao = data.getDescricao().toLowerCase();

                        if (condicao.contains(filtro)) {
                            //se conter adiciona na lista de itens filtrados.
                            itens_filtrados.add(data);
                        }
                    }
                    // Define o resultado do filtro na variavel FilterResults
                    results.count = itens_filtrados.size();
                    results.values = itens_filtrados;
                }
                return results;
            }

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
                itens_exibicao = (List<ListViewObjetos>) results.values; // Valores filtrados.
                notifyDataSetChanged();  // Notifica a lista de alteração
            }

        };
        return filter;
    }
}

Como vimos acima, o método responsável pelo filtro está bem comentado, não é complicado de entender. Quando utilizado ele vai pegar a palavra passada pelo filtro comparar com o item que queremos filtrar, criar uma lista de exibição e chamar o método do adapter que notifica mudanças na lista. Não vou implementar o “ListViewObjetos” pois é um objeto de dados simples, você pode colocar o que quiser lá, assim como o xml de item.

Abaixo vamos ver como criar o adapter e utilizar o getFilter();

public class MainActivity extends Activity {

    private ListViewAdapter adapter;

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

        // Cria uma lista de 100 objetos para usar no exemplo.
        ArrayList<ListViewObjetos> itens = new ArrayList<ListViewObjetos>();
        for (int i = 0; i < 100; i++) {
            itens.add(new ListViewObjetos(i, "descricao+" + i, "R$" + i + ",00"));
        }

        // constroi o adapter passando os itens.
        adapter = new ListViewAdapter(this, itens);
        ListView lista = (ListView) findViewById(R.id.listView1);
        lista.setAdapter(adapter);

        //Aqui é aonde adicionamos nosso filtro no edittext.
        EditText editText = (EditText) findViewById(R.id.editText1);
        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before,
                    int count) {
                //quando o texto é alterado chamamos o filtro.
                adapter.getFilter().filter(s.toString());
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                    int after) {
            }

            @Override
            public void afterTextChanged(Editable s) {
            }
        });

    }
}

Acima adicionamos um listener no editText que vai nos dizer quando o texto é alterado, quando ele for alterado o método onTextChanged() é chamado, nele vamos chamar o getFilter() do adapter e utilizar o filter() passando a string de filtro. Seu texto será tratado e sua lista FILTRADA!.

Segue o Link do projeto: (DROPBOX)

(Lembre-se de nos ajudar clicando nos anúncios em nossa página.)

Help DEV – Analista desenvolvedor Java / Android

http://helpdev.com.br/zarelli

12 thoughts on “Android – Filtrando dados de um ListView com um EditText (How to Filter ListView through EditText)

  1. Muito bom!
    Sou iniciante e seu post ajudou muito, mais estou com uma duvida, como trato um evento de clique nessa lista?
    Por exemplo se fosse uma lista de cliente onde ao clicar abre o cadastro desse cliente.

    Se puder ajudar agradeço.

    • Consegui:

      lista.setOnItemClickListener(new OnItemClickListener() {
      @Override
      public void onItemClick(AdapterView parent, View view, int position,long id) {

      }
      });

  2. Caso eu queira fazer uma busca que seja feita pelo searchview da actionbar procurando os dados vindos de uma banco de dados. Com esse seu codigo pode fazer isso ?

Deixe uma resposta

O seu endereço de email não será publicado Campos obrigatórios são marcados *

Você pode usar estas tags e atributos de HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>