web-dev-qa-db-fra.com

Implémentation de SearchView dans la barre d'action

J'ai besoin de créer SearchView à partir de mon arrayList<String> et d'afficher les suggestions dans la liste déroulante, même ceci

enter image description here

Je cherche des tutoriels qui expliquent, étape par étape, comment construire une SearchView dans une barre d’action.

J'ai lu la documentation et en suivant l'exemple de Google mais cela ne m'a pas été utile.

J'ai créé la recherche

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

Mais je ne sais pas comment définir les paramètres du tableau de chaînes. J'ai essayé de récupérer le résultat dans une activité différente mais sans succès.

79
Matteo

Il a fallu un certain temps pour trouver une solution à ce problème, mais nous avons constaté que c’était le moyen le plus simple de la faire fonctionner de la manière que vous décrivez. Il pourrait y avoir de meilleures façons de le faire, mais comme vous n'avez pas posté votre code d'activité, je vais devoir improviser et supposer que vous avez une liste comme celle-ci au début de votre activité:

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);replaced s with i as s not used anywhere.

            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));

    }

}

Vous devez maintenant créer un adaptateur étendu à partir de 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;

    }

}

Une meilleure façon de le faire est que si vos données de liste proviennent d'une base de données, vous pouvez transmettre le Cursor renvoyé par les fonctions de base de données directement à ExampleAdapter et utiliser le sélecteur de colonne approprié pour afficher le texte de la colonne dans le fichier TextView référencé dans l'adaptateur.

Remarque: lorsque vous importez CursorAdapter, n'importez pas la version de support Android, mais importez plutôt le Android.widget.CursorAdapter standard.

L'adaptateur nécessitera également une disposition personnalisée:

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>

Vous pouvez maintenant personnaliser les éléments de la liste en ajoutant des vues de texte ou d'image à la présentation et en les renseignant avec les données de l'adaptateur.

Cela devrait être tout, mais si vous ne l'avez pas déjà fait, vous avez besoin d'un élément de menu 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>

Créez ensuite une configuration interrogeable:

res/xml/searchable.xml

<searchable xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:label="@string/search"
    Android:hint="@string/search" >
</searchable>

Enfin, ajoutez ceci à l'intérieur de la balise d'activité correspondante dans le fichier manifeste:

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

Remarque: la chaîne @string/search utilisée dans les exemples doit être définie dans values ​​/ strings.xml, n'oubliez pas également de mettre à jour la référence à com.example pour votre projet.

125
tpbapp

Si quelqu'un d'autre a un nullptr sur la variable searchview, j'ai découvert que la configuration de l'élément est un tout petit peu différente:

vieux:

Android:showAsAction="ifRoom"
Android:actionViewClass="Android.widget.SearchView"

nouveau:

app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="androidx.appcompat.widget.SearchView"

pré-Android x:

app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="Android.support.v7.widget.SearchView"

Pour plus d'informations, la documentation mise à jour est situé ici .

49
Grease

SearchDialog ou SearchWidget?

Lorsqu'il s'agit d'implémenter une fonctionnalité de recherche, il existe approche suggérée par la documentation officielle du développeur Android.
Vous pouvez utiliser un SearchDialog ou un SearchWidget .
Je vais expliquer la mise en oeuvre de la fonctionnalité de recherche à l'aide de SearchWidget.

Comment le faire avec le widget de recherche?

Je vais expliquer la fonctionnalité de recherche dans RecyclerView à l'aide de SearchWidget. C'est assez simple.

Suivez juste ces 5 étapes simples

1) Ajouter un objet searchView dans le menu

Vous pouvez ajouter SearchView peut être ajouté en tant que actionView dans le menu en utilisant

app: useActionClass = "Android.support.v7.widget.SearchView".

<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) Configurer le texte Hint SerchView, auditeur, etc.

Vous devez initialiser SearchView dans la méthode onCreateOptionsMenu(Menu menu).

  @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) Implémentez SearchView.OnQueryTextListener dans votre activité

OnQueryTextListener a deux méthodes abstraites

  1. onQueryTextSubmit(String query)
  2. onQueryTextChange(String newText

Donc, votre squelette d'activité ressemblerait à ceci

YourActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{

     public boolean onQueryTextSubmit(String query)

     public boolean onQueryTextChange(String newText) 

}

4) implémenter SearchView.OnQueryTextListener

Vous pouvez fournir l'implémentation pour les méthodes abstraites comme ceci

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) Écrivez une méthode de filtrage dans votre adaptateur RecyclerView.

Partie la plus importante. Vous pouvez écrire votre propre logique pour effectuer une recherche.
Voici le mien. Cet extrait montre la liste de Nom qui contient le texte saisi dans le 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();
}

Lien pertinent:

Code de travail complet sur SearchView avec une base de données SQLite dans cette Music App

3
Rohit Singh

Pour Searchview utilisez ces codes

  1. Pour 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>
    

  2. Dans votre fragment ou activité

    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;
       }
    }
    
  3. En classe adaptateur

     public void setFilter(List<ProductDetailPojo> newList){
        arrayList=new ArrayList<>();
        arrayList.addAll(newList);
        notifyDataSetChanged();
    }
    
1
Neeraj Gupta