Hoy vamos a analizar el widget Android SearchView y desarrollar una aplicación que filtre un ListView por el texto consultado. Utilizaremos DataBinding para conectar los diseños en las actividades y adaptadores. Si aún no has leído sobre DataBinding, consulta primero este tutorial para entenderlo mejor.
Android SearchView
Android nos permite utilizar la funcionalidad de búsqueda en nuestra aplicación mostrando el widget SearchView ya sea en la Barra de herramientas/ActionBar o insertándolo en un diseño. El widget Android SearchView está disponible desde Android 3.0 en adelante. El SearchView se define en el diseño XML como se muestra a continuación.
<android.support.v7.widget.SearchView
android:id="@+id/search"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Existen muchas formas de búsqueda en Android, como la búsqueda por voz, sugerencias, etc. En este tutorial utilizaremos las interfaces SearchView.OnQueryTextListener
y Filterable
. La interfaz Filterable filtra el texto consultado sobre un ListView y muestra las filas resultantes del ListView. La interfaz OnQueryTextListener
puede detectar dos eventos.
onQueryTextChange
se llama cuando el usuario escribe cada carácter en el campo de textoonQueryTextSubmit
se activa cuando se presiona la búsqueda
Ejemplo de SearchView en Android
La siguiente imagen muestra el proyecto final de ejemplo de SearchView en Android. El proyecto consta de una Actividad y un Adaptador para el ListView.
Código de ejemplo de SearchView en Android
El archivo activity_main.xml se muestra a continuación. Consiste en un ListView con un SearchView en la parte superior. activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="https://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<android.support.v7.widget.SearchView
android:id="@+id/search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true" />
<ListView
android:id="@+id/list_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/search" />
</RelativeLayout>
</layout>
El archivo MainActivity.java se muestra a continuación.
package com.journaldev.searchview;
import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.SearchView;
import com.journaldev.searchview.databinding.ActivityMainBinding;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
ActivityMainBinding activityMainBinding;
ListAdapter adapter;
List<String> arrayList= new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
arrayList.add("January");
arrayList.add("February");
arrayList.add("March");
arrayList.add("April");
arrayList.add("May");
arrayList.add("June");
arrayList.add("July");
arrayList.add("August");
arrayList.add("September");
arrayList.add("October");
arrayList.add("November");
arrayList.add("December");
adapter= new ListAdapter(arrayList);
activityMainBinding.listView.setAdapter(adapter);
activityMainBinding.search.setActivated(true);
activityMainBinding.search.setQueryHint("Type your keyword here");
activityMainBinding.search.onActionViewExpanded();
activityMainBinding.search.setIconified(false);
activityMainBinding.search.clearFocus();
activityMainBinding.search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
});
}
}
En el código anterior, estamos pasando un ArrayList de meses al Adaptador de Lista. Estamos invocando el método de filtro que está definido en la clase del adaptador cada vez que cambia el texto de la consulta de búsqueda. La clase ListAdapter.java se ve así.
package com.journaldev.searchview;
import android.content.Context;
import android.databinding.DataBindingUtil;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import com.journaldev.searchview.databinding.RowItemBinding;
import java.util.ArrayList;
import java.util.List;
public class ListAdapter extends BaseAdapter implements Filterable {
List<String> mData;
List<String> mStringFilterList;
ValueFilter valueFilter;
private LayoutInflater inflater;
public ListAdapter(List<String> cancel_type) {
mData=cancel_type;
mStringFilterList = cancel_type;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public String getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, final ViewGroup parent) {
if (inflater == null) {
inflater = (LayoutInflater) parent.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
RowItemBinding rowItemBinding = DataBindingUtil.inflate(inflater, R.layout.row_item, parent, false);
rowItemBinding.stringName.setText(mData.get(position));
return rowItemBinding.getRoot();
}
@Override
public Filter getFilter() {
if (valueFilter == null) {
valueFilter = new ValueFilter();
}
return valueFilter;
}
private class ValueFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
List<String> filterList = new ArrayList<>();
for (int i = 0; i < mStringFilterList.size(); i++) {
if ((mStringFilterList.get(i).toUpperCase()).contains(constraint.toString().toUpperCase())) {
filterList.add(mStringFilterList.get(i));
}
}
results.count = filterList.size();
results.values = filterList;
} else {
results.count = mStringFilterList.size();
results.values = mStringFilterList;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
mData = (List<String>) results.values;
notifyDataSetChanged();
}
}
}
Como puede ver en el código anterior, estamos realizando filtrado usando una clase interna ValueFilter
que extiende la clase Filter. Filtra la lista comprobando si el texto de la consulta de búsqueda coincide con las cadenas dadas en el ArrayList. El diseño XML para la fila del ListView se muestra a continuación. row_item.xml
<layout xmlns:android="https://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/stringName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:padding="@dimen/activity_horizontal_margin"
android:textAllCaps="false"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
</layout>
La salida de la aplicación Android SearchView en acción se muestra a continuación. El SearchView mostrado anteriormente requiere que presionemos el ícono de búsqueda para activar el campo de texto. Además, no contiene ningún texto de pista/placeholder. Agregue el siguiente código en MainActivity para habilitar el SearchView por defecto y mostrar una pista.
activityMainBinding.search.setActivated(true);
activityMainBinding.search.setQueryHint("Type your keyword here");
activityMainBinding.search.onActionViewExpanded();
activityMainBinding.search.setIconified(false);
activityMainBinding.search.clearFocus();
El SearchView después de personalizarlo como se describe se ve así. Esto concluye el tutorial de Android SearchView. Nos sumergiremos en las funciones avanzadas de SearchView en un tutorial posterior. Puedes descargar el Proyecto Android SearchView desde el enlace proporcionado a continuación.
Source:
https://www.digitalocean.com/community/tutorials/android-searchview-example-tutorial