I have a search bar that should search my listview
, but it doesn't, it doesn't search for anything no matter how much I type. I click on the magnifying glass and it opens, I write but it doesn't search for anything.
Example:
Before, I looked for the titles of my ListView
, which I obtained from here:
String[] titulo = new String[]{
"Android Studio",
"Java",
"Xml",
"Otra Prueba",
};
But my ListView
no longer gets the titles from there, now I have modified my ListViewAdapter
so that it gets the titles from array
This is how my code works now:
ListViewAdapter
:
public class ListViewAdapter extends BaseAdapter {
// Declare Variables
Context context;
String[] titulos;
int[] imagenes;
LayoutInflater inflater;
int idListaTitulos;
public ListViewAdapter(Context context, String[] titulos, int[] imagenes, int idListaTitulos) {
this.context = context;
this.titulos = titulos;
this.imagenes = imagenes;
this.idListaTitulos = idListaTitulos;
}
@Override
public int getCount() {
return titulos.length;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
// Declare Variables
TextView txtTitle;
ImageView imgImg;
String[] titulos = context.getResources().getStringArray(idListaTitulos);
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.list_row, parent, false);
// Locate the TextViews in listview_item.xml
txtTitle = (TextView) itemView.findViewById(R.id.list_row_title);
imgImg = (ImageView) itemView.findViewById(R.id.list_row_image);
// Capture position and set to the TextViews
txtTitle.setText(titulos[position]);
imgImg.setImageResource(imagenes[position]);
return itemView;
}
}
And my clase
:
public class cocobuzz2 extends AppCompatActivity {
MaterialSearchView searchView;
ListViewAdapter adapter;
String[] titulo = new String[]{
"Android Studio",
"Java",
"Xml",
"Otra Prueba",
};
int[] imagenes = {
R.drawable.ic_launcher,
R.drawable.ic_launcher,
R.drawable.ic_launcher,
R.drawable.ic_launcher,
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cocobuzz2);
final ListView lista = (ListView) findViewById(R.id.listview_coco2);
adapter = new ListViewAdapter(this, titulo, imagenes, R.array.titulo1);
lista.setAdapter(adapter);
lista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView adapterView, View view, int posicion, long l) {
switch (posicion) {
case 0:
Intent a = new Intent(getApplicationContext(), cocobuzz2.class);
startActivity(a);
break;
case 1:
Intent b = new Intent(getApplicationContext(), cocobuzz2.class);
startActivity(b);
break;
case 2:
Intent c = new Intent(getApplicationContext(), cocobuzz2.class);
startActivity(c);
break;
case 3:
Intent d = new Intent(getApplicationContext(), cocobuzz2.class);
startActivity(d);
break;
}
}
});
searchView = (MaterialSearchView) findViewById(R.id.search_view);
searchView.setOnSearchViewListener(new MaterialSearchView.SearchViewListener() {
@Override
public void onSearchViewShown() {
}
@Override
public void onSearchViewClosed() {
//If closed Search View , lstView will return default
final ListView lista = (ListView) findViewById(R.id.listview_coco2);
adapter = new ListViewAdapter(cocobuzz2.this, titulo, imagenes, R.array.titulo1);
lista.setAdapter(adapter);
}
});
searchView.setOnQueryTextListener(new MaterialSearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if (newText != null && !newText.isEmpty()) {
List<String> lstFound = new ArrayList<String>();
for (String item : titulo) {
if (item.contains(newText))
lstFound.add(item);
}
String[] titulo = lstFound.toArray(new String[0]);
adapter = new ListViewAdapter(cocobuzz2.this, titulo, imagenes, R.array.titulo1);
lista.setAdapter(adapter);
} else {
//if search text is null
//return default
adapter = new ListViewAdapter(cocobuzz2.this, titulo, imagenes);
lista.setAdapter(adapter);
}
return true;
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_item,menu);
MenuItem item = menu.findItem(R.id.action_search);
searchView.setMenuItem(item);
return true;
}
}
And now having added that it obtain the titles of array (values-string) -titles1- and my search engine does not search for anything, so I imagine that my error is here:
@Override
public boolean onQueryTextChange(String newText) {
if (newText != null && !newText.isEmpty()) {
List<String> lstFound = new ArrayList<String>();
for (String item : titulo) {
if (item.contains(newText))
lstFound.add(item);
}
// Al añadir esta linea ya me buscaba, PERO, cuando cambie la forma de obtener los títulos, dejó de hacerlo.
String[] titulo = lstFound.toArray(new String[0]);
// ---
adapter = new ListViewAdapter(cocobuzz2.this, titulo, imagenes, R.array.titulo1);
My String with its array
<resources>
...
<string-array name="titulos1">
<item>Android Studio</item>
<item>Java</item>
<item>Xml</item>
<item>Otra Prueba</item>
</string-array>
</resources>
UPDATE 3: to @StefanNolde 02/07/2016
class
public class Cocobuzz2 extends AppCompatActivity {
MaterialSearchView searchView;
IndexAdapter adapter;
// elimina la declaración fija de los datos que ya implementaste como arreglo en los recursos
ArrayList<String> titulo;
ArrayList<Integer> imagenes;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cocobuzz2);
1.//////////// borrado <Integer> ya que no se utiliza
imagenes = new ArrayList<>();
for (Integer pos :
2.////////////////////// añado new int[]
new int[]
{
R.drawable.ic_launcher,
R.drawable.ic_launcher,
R.drawable.ic_launcher,
R.drawable.ic_launcher,
}) {
imagenes.add(pos);
}
final ListView lista = (ListView) findViewById(R.id.listview_coco2);
//agrega aqui el código para llenar 'titulo' con datos
3.//////////// borrado <String> ya que no se utiliza
titulo = new ArrayList<>();
for (String tit : getResources().getStringArray(R.array.titulos1)) {
titulo.add(tit);
}
// aqui es el UNICO lugar donde instamos un nuevo adapter
4.//////////////////////////// añado new int[]
adapter = new IndexAdapter(this, new int[]{0, 1, 2, 3});
lista.setAdapter(adapter);
lista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView adapterView, View view, int posicion, long l) {
// Como durante la búsqueda el contenido de tu arreglo va cambiando,
// eligir actividad por indice
// aquí quedo resto de código antiguo
switch ((Integer) adapter.getItem(posicion)) {
case 0:
Intent a = new Intent(getApplicationContext(), Cocobuzz2.class);
startActivity(a);
break;
case 1:
Intent b = new Intent(getApplicationContext(), Cocobuzz2.class);
startActivity(b);
break;
case 2:
Intent c = new Intent(getApplicationContext(), Cocobuzz2.class);
startActivity(c);
break;
case 3:
Intent d = new Intent(getApplicationContext(), Cocobuzz2.class);
startActivity(d);
break;
}
}
});
searchView = (MaterialSearchView) findViewById(R.id.search_view);
searchView.setOnSearchViewListener(new MaterialSearchView.SearchViewListener() {
@Override
public void onSearchViewShown() {
}
@Override
public void onSearchViewClosed() {
//If closed Search View , lstView will return default
adapter.clear();
adapter.set(titulo.toArray(new String[0]));
}
});
searchView.setOnQueryTextListener(new MaterialSearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if (newText != null && !newText.isEmpty()) {
5.//////////// borrado <String> ya que no se utiliza
List<String> lstFound = new ArrayList<>();
for (String item : titulo) {
if (item.contains(newText))
lstFound.add(item);
}
// usemos otro nombre de variable para mas claridad
// aun que diferenciemos entre this.titulo y titulo, así queda mas obvio
String[] subTitulo = lstFound.toArray(new String[0]);
// de nuevo, quedemos con el mismo adapter.
adapter.set(subTitulo);
} else {
//if search text is null
//return default
// y de nuevo ;)
adapter.set(titulo.toArray(new String[0]));
return true;
}
6.///////////////// he añadido return true;
return true;
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_buscar,menu);
MenuItem item = menu.findItem(R.id.action_search);
searchView.setMenuItem(item);
return true;
}
class IndexAdapter extends BaseAdapter {
Context context;
ArrayList<Integer> item;
LayoutInflater inflater;
//int idListaTitulos;
public IndexAdapter(Context context, int[] id) {
super();
this.context = context;
7.//////////// borrado <Integer> ya que no se utiliza
this.item=new ArrayList<>();
for (int i : id) item.add(i);
}
@Override
public int getCount() {
return item.size();
}
// con getItem devolvemos la posición en la lista original
@Override
public Object getItem(int position) {
return item.get(position);
}
// usemos itemId para el imageId
@Override
public long getItemId(int position) {
return imagenes.get(item.get(position));
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView txtTitle;
ImageView imgImg;
8.//////////////////////// he borrado esta línea -> String[] titulos = context.getResources().getStringArray(idListaTitulos);
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.list_row, parent, false);
// Locate the TextViews in listview_item.xml
txtTitle = (TextView) itemView.findViewById(R.id.list_row_title);
imgImg = (ImageView) itemView.findViewById(R.id.list_row_image);
// Capture position and set to the TextViews
txtTitle.setText(titulo.get(item.get(position)));
imgImg.setImageResource(imagenes.get(item.get(position)));
return itemView;
}
public void set(String[] items){
item.clear();
for(String it :items){
if (titulo.indexOf(it)>-1) item.add(titulo.indexOf(it));
}
notifyDataSetChanged();
}
public void clear() {
item.clear();
notifyDataSetChanged();
}
}
}
Cuando cambian tus resultados de búsqueda, tu agregas un nuevo Adapter. Así no puedes garantizar que la vista se da cuenta que hay un cambio en los datos.
Lo que tienes que hacer es actualizar los datos dentro del
Adapter
que agregaste enonCreate
y luego llamar anotifyDataSetChanged()
. No compartiste la implementacion de tu Adapter, pero imaginando que usaste ArrayAdapter como subclase, trata eso:Para cambiar el arreglo fijo a carga de títulos de los recursos tienes que cambiar algunas cosas. En el
Adapter
no tienesgetResources()
, así tienes que buscarlos desdeActivity
oFragnment
cuando construyes el adapter:Eso debería ser el unico lugar donde instas el adapter. Para cambiar el contenido de la lista luego siempre llamas a este adapter por ejemplo como:
o para borrar los valores:
actualizado
Tu adapter se ve bien a la vista (depurar en una pregunta no es tan seguro como en studio ;) ). En tu actividad hay problemas, como te dije, el adapter deberías instar una vez en
onCreate
y luego actualizarlo no mas con datos:Para hacer tu aplicación vamos a tener que trabajar más en equipo. Necesito que compruebes los resultados de tu búsqueda con un
Log.d("RESULTADO BUSCAR", ...)
donde recibes los resultados para asegurarse que eso esta fuera de problemas.actualizado Como el método
clear()
en elArrayAdapter
no esta implementado, implementamos un propio adapter basado en BaseAdapter (como lo hiciste originalmente). Esta vez aun lo creamos como "inner class", así puede acceder los campos de la actividad, eso nos facilita el trabajo y usamos puros indices en el adapter:Cuando usas esta clase, Studio te va reclamar que el
R
no esta importado, eso tienes que agregar dependiente del paquete que usas.He revisado los errores que marcaste, el principal es el
import
delListViewAdapter
. Actualmente hay una clase con este nombre declarado más la clase interna. Voy a cambiar el Nombre para desambiguear.updated I forgot you
Arrays.asList
have your problems on Android. I replaced it with more vintage code. On the switch a cast was needed.Lo que pasa es que no estás actualizando los valores del array de Strings "titulo", por lo tanto el Adapter está recibiendo siempre los mismos valores del comienzo.
Una solución podría ser crear otra variable que contenga los valores actualizados y pasarla al adaptador:
Como al adaptador hay que pasarle un objeto de tipo String[], hay que convertir la List en array mediante el método toArray.
Since I see that you have not received help, I will share the search engine that I use (it is implemented for ExpandableListView). In simple words, it is a FILTER, which hides-shows only some data from the list that matches the filter. In my application, I filter the list with checkboxes, but also from a "Magnifying glass" (as in your case) and I leave visible only what I write in the EditText. I'll try to leave only what you need, since I use models to structure each item on the list... and I'll answer any questions you ask.
1°.- Change your Adapter from:
for this, with the following libraries and variables:
donde ingresaAcaTuArray, es el modelo o componente, que define el cuerpo que tendrá cada item de la lista.
2°.- Creación del componente ingresaAcaTuArray
3°.- Agregar los métodos del BaseAdapter, esta bien si lo pegas en la penultima línea, entre los 2 corchetes que cierran.
4°.- Unir el editText(en mi caso materialEditText) con el adaptador (por limite de texto no agregaré el layout) y declarar adaptador (en tu caso ya lo hiciste y se llama adapter)
5°.- El método filtrarLista:
He quitado mucho codigo propio, por lo que me pude haber eliminado algo demas, avisame si falta algo