Necesito crear SearchView
desde mi arrayList<String>
y mostrar las sugerencias en la lista desplegable igual que esto
Busco tutoriales que expliquen paso a paso cómo construir una SearchView
barra de acciones.
He leído la documentación y siguiendo el ejemplo de google pero no me ha resultado útil.
He creado la búsqueda
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_search"
android:title="Search"
android:icon="@android:drawable/ic_menu_search"
android:showAsAction="always"
android:actionViewClass="android.widget.SearchView" />
</menu>`
Pero no sé cómo configurar los parámetros de la matriz de cadenas. Intenté recuperar el resultado en una actividad diferente pero no funcionó.
Respuestas:
Me tomó un tiempo armar una solución para esto, pero he descubierto que esta es la forma más fácil de hacer que funcione de la manera que usted describe. Podría haber mejores formas de hacer esto, pero como no ha publicado su código de actividad, tendré que improvisar y asumir que tiene una lista como esta al comienzo de su actividad:
private List<String> items = db.getItems();
ExampleActivity.java
private List<String> items; private Menu menu; @Override @TargetApi(Build.VERSION_CODES.HONEYCOMB) public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.example, menu); this.menu = menu; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); SearchView search = (SearchView) menu.findItem(R.id.search).getActionView(); search.setSearchableInfo(manager.getSearchableInfo(getComponentName())); search.setOnQueryTextListener(new OnQueryTextListener() { @Override public boolean onQueryTextChange(String query) { loadHistory(query); return true; } }); } return true; } // History @TargetApi(Build.VERSION_CODES.HONEYCOMB) private void loadHistory(String query) { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // Cursor String[] columns = new String[] { "_id", "text" }; Object[] temp = new Object[] { 0, "default" }; MatrixCursor cursor = new MatrixCursor(columns); for(int i = 0; i < items.size(); i++) { temp[0] = i; temp[1] = items.get(i); cursor.addRow(temp); } // SearchView SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); final SearchView search = (SearchView) menu.findItem(R.id.search).getActionView(); search.setSuggestionsAdapter(new ExampleAdapter(this, cursor, items)); } }
Ahora necesita crear un adaptador extendido desde
CursorAdapter
:ExampleAdapter.java
public class ExampleAdapter extends CursorAdapter { private List<String> items; private TextView text; public ExampleAdapter(Context context, Cursor cursor, List<String> items) { super(context, cursor, false); this.items = items; } @Override public void bindView(View view, Context context, Cursor cursor) { text.setText(items.get(cursor.getPosition())); } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(R.layout.item, parent, false); text = (TextView) view.findViewById(R.id.text); return view; } }
Una mejor manera de hacerlo es si los datos de su lista provienen de una base de datos, puede pasar las
Cursor
funciones devueltas por la base de datos directamenteExampleAdapter
y usar el selector de columna correspondiente para mostrar el texto de la columna en el que se haceTextView
referencia en el adaptador.Tenga en cuenta: cuando importe
CursorAdapter
, no importe la versión de soporte de Android, importe el estándar en suandroid.widget.CursorAdapter
lugar.El adaptador también requerirá un diseño personalizado:
res / layout / item.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/item" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
Ahora puede personalizar los elementos de la lista agregando texto o vistas de imágenes adicionales al diseño y llenándolos con datos en el adaptador.
Esto debería ser todo, pero si aún no lo ha hecho, necesita un elemento de menú SearchView:
res / menu / example.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/search" android:title="@string/search" android:showAsAction="ifRoom" android:actionViewClass="android.widget.SearchView" /> </menu>
Luego, cree una configuración de búsqueda:
res / xml / seek.xml
<searchable xmlns:android="http://schemas.android.com/apk/res/android" android:label="@string/search" android:hint="@string/search" > </searchable>
Finalmente, agregue esto dentro de la etiqueta de actividad relevante en el archivo de manifiesto:
AndroidManifest.xml
<intent-filter> <action android:name="android.intent.action.SEARCH" /> </intent-filter> <meta-data android:name="android.app.default_searchable" android:value="com.example.ExampleActivity" /> <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" />
Tenga en cuenta: La
@string/search
cadena utilizada en los ejemplos debe definirse en values / strings.xml , también no olvide actualizar la referencia acom.example
para su proyecto.fuente
search.setSearchableInfo(manager.getSearchableInfo(getComponentName()));
llamado dos veces en los métodosonCreateOptionsMenu()
yloadHistory()
. Así que hago la variable global SearchView y SearchManager, y solo llamogetSearchableInfo()
una vez enonCreateOptionsMenu()
. Y mi lista de sugerencias ahora funciona perfectamente. Le sugiero que revise su código.Si alguien más tiene un nullptr en la variable de vista de búsqueda, descubrí que la configuración del elemento es un poco diferente:
antiguo:
android:showAsAction="ifRoom" android:actionViewClass="android.widget.SearchView"
nuevo:
app:showAsAction="ifRoom|collapseActionView" app:actionViewClass="androidx.appcompat.widget.SearchView"
pre-android x:
app:showAsAction="ifRoom|collapseActionView" app:actionViewClass="android.support.v7.widget.SearchView"
Para obtener más información, su documentación actualizada se encuentra aquí .
fuente
app:actionViewClass="androidx.appcompat.widget.SearchView"
para androidxSearchDialog o SearchWidget?
Cuando se trata de implementar una función de búsqueda, hay dos enfoques sugeridos por la documentación oficial para desarrolladores de Android.
Puede utilizar un SearchDialog o un SearchWidget .
Voy a explicar la implementación de la funcionalidad de búsqueda usando SearchWidget.
¿Cómo hacerlo con el widget de búsqueda?
Explicaré la funcionalidad de búsqueda en un RecyclerView usando SearchWidget. Es bastante sencillo.
Solo sigue estos 5 sencillos pasos
1) Agregar elemento searchView en el menú
Puede agregar
SearchView
se puede agregar comoactionView
en el menú usando<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" tools:context="rohksin.com.searchviewdemo.MainActivity"> <item android:id="@+id/searchBar" app:showAsAction="always" app:actionViewClass="android.support.v7.widget.SearchView" /> </menu>
2) Configure el texto de la sugerencia de SerchView, el oyente, etc.
Debe inicializar SearchView en el
onCreateOptionsMenu(Menu menu)
método.@Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); MenuItem searchItem = menu.findItem(R.id.searchBar); SearchView searchView = (SearchView) searchItem.getActionView(); searchView.setQueryHint("Search People"); searchView.setOnQueryTextListener(this); searchView.setIconified(false); return true; }
3) Implemente SearchView.OnQueryTextListener en su actividad
OnQueryTextListener
tiene dos métodos abstractosonQueryTextSubmit(String query)
onQueryTextChange(String newText
Entonces tu esqueleto de actividad se vería así
YourActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{ public boolean onQueryTextSubmit(String query) public boolean onQueryTextChange(String newText) }
4) Implementar SearchView.OnQueryTextListener
Puede proporcionar la implementación para los métodos abstractos como este
public boolean onQueryTextSubmit(String query) { // This method can be used when a query is submitted eg. creating search history using SQLite DB Toast.makeText(this, "Query Inserted", Toast.LENGTH_SHORT).show(); return true; } @Override public boolean onQueryTextChange(String newText) { adapter.filter(newText); return true; }
5) Escriba un método de filtro en su adaptador RecyclerView.
Parte más importante. Puede escribir su propia lógica para realizar la búsqueda.
Aquí esta el mio. Este fragmento muestra la lista de Nombre que contiene el texto escrito en el
SearchView
public void filter(String queryText) { list.clear(); if(queryText.isEmpty()) { list.addAll(copyList); } else { for(String name: copyList) { if(name.toLowerCase().contains(queryText.toLowerCase())) { list.add(name); } } } notifyDataSetChanged(); }
Enlace relevante:
Código de trabajo completo en SearchView con una base de datos SQLite en esta aplicación de música
fuente
Para
Searchview
usar este códigoPara XML
<android.support.v7.widget.SearchView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/searchView"> </android.support.v7.widget.SearchView>
En tu Fragmento o Actividad
package com.example.user.salaryin; import android.app.ProgressDialog; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.view.MenuItemCompat; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SearchView; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import com.example.user.salaryin.Adapter.BusinessModuleAdapter; import com.example.user.salaryin.Network.ApiClient; import com.example.user.salaryin.POJO.ProductDetailPojo; import com.example.user.salaryin.Service.ServiceAPI; import java.util.ArrayList; import java.util.List; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; public class OneFragment extends Fragment implements SearchView.OnQueryTextListener { RecyclerView recyclerView; RecyclerView.LayoutManager layoutManager; ArrayList<ProductDetailPojo> arrayList; BusinessModuleAdapter adapter; private ProgressDialog pDialog; GridLayoutManager gridLayoutManager; SearchView searchView; public OneFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.one_fragment,container,false); pDialog = new ProgressDialog(getActivity()); pDialog.setMessage("Please wait..."); searchView=(SearchView)rootView.findViewById(R.id.searchView); searchView.setQueryHint("Search BY Brand"); searchView.setOnQueryTextListener(this); recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView); layoutManager = new LinearLayoutManager(this.getActivity()); recyclerView.setLayoutManager(layoutManager); gridLayoutManager = new GridLayoutManager(this.getActivity().getApplicationContext(), 2); recyclerView.setLayoutManager(gridLayoutManager); recyclerView.setHasFixedSize(true); getImageData(); // Inflate the layout for this fragment //return inflater.inflate(R.layout.one_fragment, container, false); return rootView; } private void getImageData() { pDialog.show(); ServiceAPI service = ApiClient.getRetrofit().create(ServiceAPI.class); Call<List<ProductDetailPojo>> call = service.getBusinessImage(); call.enqueue(new Callback<List<ProductDetailPojo>>() { @Override public void onResponse(Call<List<ProductDetailPojo>> call, Response<List<ProductDetailPojo>> response) { if (response.isSuccessful()) { arrayList = (ArrayList<ProductDetailPojo>) response.body(); adapter = new BusinessModuleAdapter(arrayList, getActivity()); recyclerView.setAdapter(adapter); pDialog.dismiss(); } else if (response.code() == 401) { pDialog.dismiss(); Toast.makeText(getActivity(), "Data is not found", Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<List<ProductDetailPojo>> call, Throwable t) { Toast.makeText(getActivity(), t.getMessage(), Toast.LENGTH_SHORT).show(); pDialog.dismiss(); } }); } /* @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { getActivity().getMenuInflater().inflate(R.menu.menu_search, menu); MenuItem menuItem = menu.findItem(R.id.action_search); SearchView searchView = (SearchView) MenuItemCompat.getActionView(menuItem); searchView.setQueryHint("Search Product"); searchView.setOnQueryTextListener(this); }*/ @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { newText = newText.toLowerCase(); ArrayList<ProductDetailPojo> newList = new ArrayList<>(); for (ProductDetailPojo productDetailPojo : arrayList) { String name = productDetailPojo.getDetails().toLowerCase(); if (name.contains(newText) ) newList.add(productDetailPojo); } adapter.setFilter(newList); return true; } }
En clase de adaptador
public void setFilter(List<ProductDetailPojo> newList){ arrayList=new ArrayList<>(); arrayList.addAll(newList); notifyDataSetChanged(); }
fuente