Comment utiliser SearchView dans la barre d'outils Android

124

Le code sur lequel je travaille utilise un Toolbaret gonfle un menu.

Voici le code

private Toolbar mToolbar;
mToolbar.inflateMenu(R.menu.chat_screen_menu);
setupMenu ();
private void setupMenu ()
   {
   mMenu = mToolbar.getMenu();
   if (mMenu != null)
      {
       if (mChatPager != null && mChatPager.getCurrentItem() > 0)
          {
          mMenu.setGroupVisible(R.id.menu_group_chats, true);
          mMenu.setGroupVisible(R.id.menu_group_contacts, false);
          }
       else
          {
           mMenu.setGroupVisible(R.id.menu_group_chats, false);
           mMenu.setGroupVisible(R.id.menu_group_contacts, true);
           mMenu.setGroupVisible(R.id.menu_group_otr_verified,false);
           mMenu.setGroupVisible(R.id.menu_group_otr_unverified,false);
           mMenu.setGroupVisible(R.id.menu_group_otr_off,false);
          }
    }
    mToolbar.setOnMenuItemClickListener(new OnMenuItemClickListener ()
    {
    ..........
    }
}

Mais maintenant, ils nécessitent un Searchbouton dans le tool_bar. J'ai réussi à le mettre, j'ai suivi un guide ici Quand j'essaye d'écrire quelque chose à rechercher, le toast que j'avais mis à tester le listenerjamais montré. ce qui indique listenerne fonctionne pas

@Override
    public boolean onCreateOptionsMenu(Menu menu) {

    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.chat_screen_menu, menu);

    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    mSearchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_menu_search));
    final Toast toast = new Toast(mApp);

    if (mSearchView != null )
    {
        mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        mSearchView.setIconifiedByDefault(false);

        SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener()
        {
            public boolean onQueryTextChange(String newText)
            {
                mSearchString = newText;
                //doFilterAsync(mSearchString);
                toast.makeText(getApplicationContext(), "Test1", Toast.LENGTH_LONG).show();
                return true;
            }

            public boolean onQueryTextSubmit(String query)
            {
                mSearchString = query;
                //doFilterAsync(mSearchString);
                toast.makeText(getApplicationContext(), "Test2", Toast.LENGTH_LONG).show();

                return true;
            }
        };

        mSearchView.setOnQueryTextListener(queryTextListener);
    }

    return true;

}
Timide
la source

Réponses:

205

Vous devez utiliser la Appcompatbibliothèque pour cela. Qui est utilisé comme ci-dessous:

dashboard.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android" 
      xmlns:tools="http://schemas.android.com/tools"
      xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/action_search"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="always|collapseActionView"
        app:actionViewClass="androidx.appcompat.widget.SearchView"
        android:title="Search"/>
</menu>

Fichier d'activité (en Java):

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater menuInflater = getMenuInflater();
    menuInflater.inflate(R.menu.dashboard, menu);

     MenuItem searchItem = menu.findItem(R.id.action_search);

    SearchManager searchManager = (SearchManager) MainActivity.this.getSystemService(Context.SEARCH_SERVICE);

    SearchView searchView = null;
    if (searchItem != null) {
        searchView = (SearchView) searchItem.getActionView();
    }
    if (searchView != null) {
        searchView.setSearchableInfo(searchManager.getSearchableInfo(MainActivity.this.getComponentName()));
    }
        return super.onCreateOptionsMenu(menu);
}

Fichier d'activité (à Kotlin):

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
    menuInflater.inflate(R.menu.menu_search, menu)

    val searchItem: MenuItem? = menu?.findItem(R.id.action_search)
    val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
    val searchView: SearchView? = searchItem?.actionView as SearchView

    searchView?.setSearchableInfo(searchManager.getSearchableInfo(componentName))
    return super.onCreateOptionsMenu(menu)
}

fichier manifeste:

<meta-data 
      android:name="android.app.default_searchable" 
      android:value="com.apkgetter.SearchResultsActivity" /> 

        <activity
            android:name="com.apkgetter.SearchResultsActivity"
            android:label="@string/app_name"
            android:launchMode="singleTop" >
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
            </intent-filter>

            <meta-data
                android:name="android.app.searchable"
                android:resource="@xml/searchable" />
        </activity>

fichier xml interrogeable:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:hint="@string/search_hint"
    android:label="@string/app_name" />

Et enfin, votre SearchResultsActivitycode de classe. pour afficher le résultat de votre recherche.

Sagar Maiyad
la source
18
Notez que maintenant vous devriezimport android.support.v7.widget.SearchView
Joaquin Iurchuk
Merci, une idée sur la façon de gérer le clic "Go"? ça aiderait
Bala Vishnu
2
Je vais juste lier la documentation officielle où vous pouvez également trouver comment réagir à la requête developer.android.com/training/search/setup.html
koesclem
2
Notez l'application: actionViewClass au lieu d'Android: actionViewClass
DragonT
1
Si vous avez migré vers androidX, utilisez:androidx.appcompat.widget.SearchView
Daniil
169

Si vous souhaitez configurer la fonction de recherche dans votre Fragment, ajoutez simplement ces quelques lignes:

Étape 1 - Ajoutez le champ de recherche à vous toolbar:

<item
    android:id="@+id/action_search"
    android:icon="@android:drawable/ic_menu_search"
    app:showAsAction="always|collapseActionView"
    app:actionViewClass="android.support.v7.widget.SearchView"
    android:title="Search"/>

Étape 2 - Ajoutez la logique à votreonCreateOptionsMenu()

import android.support.v7.widget.SearchView; // not the default !

@Override
public boolean onCreateOptionsMenu( Menu menu) {
    getMenuInflater().inflate( R.menu.main, menu);

    MenuItem myActionMenuItem = menu.findItem( R.id.action_search);
    searchView = (SearchView) myActionMenuItem.getActionView();
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            // Toast like print
            UserFeedback.show( "SearchOnQueryTextSubmit: " + query);
            if( ! searchView.isIconified()) {
                searchView.setIconified(true);
            }
            myActionMenuItem.collapseActionView();
            return false;
        }
        @Override
        public boolean onQueryTextChange(String s) {
            // UserFeedback.show( "SearchOnQueryTextChanged: " + s);
            return false;
        }
    });
    return true;
}
tm1701
la source
29
Cette réponse est beaucoup plus utile si vous ne souhaitez pas créer / passer à une nouvelle activité lorsqu'un utilisateur a soumis la requête de recherche. Cela vous permettra de rester sur la même activité / fragment et de simplement mettre à jour une vue en fonction de l'entrée des utilisateurs. Super truc.
Nick.D
3
UserFeedback ... est ma méthode Toast-alike.
tm1701
Entrée clavier non prise en vue de recherche
Saravanan
Quoi R.menu.main?
Alston le
public void onCreateOptionsMenu (menu @NonNull Menu, @NonNull MenuInflater inflater) {} vous pouvez appeler directement cette méthode ici, vous pouvez infiler votre propre menu et gérer ce directoly à partir d'un fragment sans utiliser d'activité. gentil merci
Amar Singh
40

Si vous souhaitez l'ajouter directement dans la barre d'outils.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.Toolbar
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <SearchView
            android:id="@+id/searchView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:iconifiedByDefault="false"
            android:queryHint="Search"
            android:layout_centerHorizontal="true" />

    </android.support.v7.widget.Toolbar>

</android.support.design.widget.AppBarLayout>

Ali
la source
2
Si vous utilisez le support SearchView, n'oubliez pas de le déclarer également comme android.support.v7.widget.SearchViewdans le XML.
Panier abandonné
n'oubliez pas d'ajouter gradleimplementation 'com.android.support:design:$latest_version'
Ali
Qu'est-ce qui est iconifié ?
IgorGanapolsky
¨Si vous souhaitez que le champ de recherche soit toujours visible, appelez setIconifiedByDefault (false) ¨ à partir de la documentation
noe
16

Intégration de SearchView avec RecyclerView

1) Ajouter un élément SearchView dans le menu

SearchViewpeut être ajouté comme actionViewdans 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) Implémentez SearchView.OnQueryTextListener dans votre activité

SearchView.OnQueryTextListenera deux méthodes abstraites. Ainsi, votre squelette d'activité ressemblerait maintenant à ceci après avoir implémenté l'écouteur de texte SearchView.

YourActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{

   public boolean onQueryTextSubmit(String query)

   public boolean onQueryTextChange(String newText) 

}

3) Configurer le texte de l'indice SerchView, l'auditeur, etc.

@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;
}

4) Implémenter SearchView.OnQueryTextListener

C'est ainsi que vous pouvez implémenter des méthodes abstraites de l'écouteur.

@Override
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.

Vous pouvez proposer votre propre logique en fonction de vos besoins. Voici l'exemple d'extrait de code pour afficher la liste de Name qui contient le texte tapé 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();
}

Un exemple de code de travail complet peut être trouvé> ICI
Vous pouvez également consulter le code sur SearchView avec une base de données SQLite dans cette application musicale

Rohit Singh
la source
Pourquoi le menu est-il nécessaire?
IgorGanapolsky
1

Implémentation de SearchView sans l'utilisation du menu.xmlfichier et ouverture via le bouton

Dans votre, Activitynous devons utiliser la méthode de la onCreateOptionsMenuméthode dans laquelle nous gonflerons par programme leSearchView

private MenuItem searchMenu;
private String mSearchString="";

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        SearchManager searchManager = (SearchManager) StoreActivity.this.getSystemService(Context.SEARCH_SERVICE);


        SearchView mSearchView = new SearchView(getSupportActionBar().getThemedContext());
        mSearchView.setQueryHint(getString(R.string.prompt_search)); /// YOUR HINT MESSAGE
        mSearchView.setMaxWidth(Integer.MAX_VALUE);

        searchMenu = menu.add("searchMenu").setVisible(false).setActionView(mSearchView);
        searchMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);


        assert searchManager != null;
        mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        mSearchView.setIconifiedByDefault(false);

        SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
            public boolean onQueryTextChange(String newText) {
                mSearchString = newText;

                return true;
            }

            public boolean onQueryTextSubmit(String query) {
                mSearchString = query;

                searchMenu.collapseActionView();


                return true;
            }
        };

        mSearchView.setOnQueryTextListener(queryTextListener);


        return true;
    }

Et dans votre classe d'activité, vous pouvez ouvrir le SearchViewsur n'importe quel bouton, cliquez sur la barre d'outils comme ci-dessous

YOUR_BUTTON.setOnClickListener(view -> {

            searchMenu.expandActionView();

        });
Ravindra Kushwaha
la source