Jak korzystać z SearchView w pasku narzędzi Toolbar dla systemu Android

124

Kod, nad którym pracuję, używa a Toolbari pompuje a menu.

Oto kod

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 ()
    {
    ..........
    }
}

Ale teraz wymagają Searchprzycisku w tool_bar. Udało mi się to ująć, podążałem za przewodnikiem tutaj Kiedy próbuję napisać coś do wyszukiwania, toast, który wzniosłem, aby przetestować listenernigdy nie pokazany. co wskazuje, że listenernie działa

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

}
Shudy
źródło

Odpowiedzi:

205

Musisz do tego użyć Appcompatbiblioteki. Który jest używany jak poniżej:

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>

Plik aktywności (w Javie):

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

Plik aktywności (w Kotlinie):

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

plik manifestu:

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

przeszukiwalny plik xml:

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

I wreszcie SearchResultsActivitykod twojej klasy. za wyświetlanie wyników wyszukiwania.

Sagar Maiyad
źródło
18
Zauważ, że teraz powinieneśimport android.support.v7.widget.SearchView
Joaquin Iurchuk
Dzięki, masz jakiś pomysł, jak obsłużyć kliknięcie „Go”? to by pomogło
Bala Vishnu
2
Podlinkuję
2
Zwróć uwagę na aplikację: actionViewClass zamiast android: actionViewClass
DragonT
1
Jeśli przeprowadziłeś migrację do androidX, użyj:androidx.appcompat.widget.SearchView
Daniil
169

Jeśli chcesz skonfigurować funkcję wyszukiwania w swoim Fragment, po prostu dodaj te kilka wierszy:

Krok 1 - Dodaj pole wyszukiwania do siebie 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"/>

Krok 2 - Dodaj logikę do plikuonCreateOptionsMenu()

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
źródło
29
Ta odpowiedź jest znacznie bardziej przydatna, jeśli nie chcesz tworzyć / przenosić się do nowego działania, gdy użytkownik przesłał zapytanie. Pozwoli ci to pozostać przy tej samej aktywności / fragmencie i po prostu zaktualizować widok na podstawie danych wejściowych użytkowników. Świetne rzeczy.
Nick D.
3
UserFeedback ... to moja metoda na toast.
tm1701
Wprowadzanie z klawiatury nie jest wykonywane w widoku wyszukiwania
Saravanan
Co R.menu.main?
Alston
public void onCreateOptionsMenu (menu @NonNull Menu, @NonNull MenuInflater inflater) {} możesz bezpośrednio wywołać tę metodę tutaj, możesz infilować własne menu i obsłużyć to bezpośrednio z fragmentu bez użycia aktywności. miłe dzięki
Amar Singh
40

Jeśli chcesz dodać go bezpośrednio na pasku narzędzi.

<?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
źródło
2
Jeśli używasz wsparcia SearchView, nie zapomnij zadeklarować go również jako android.support.v7.widget.SearchViewXML.
Opuszczony
nie zapomnij dodać w gradleimplementation 'com.android.support:design:$latest_version'
Ali
Co jest ikonizowane ?
IgorGanapolsky
¨Jeśli chcesz, aby pole wyszukiwania było zawsze widoczne, wywołaj setIconifiedByDefault (false) ¨ z dokumentacji
noe
16

Integracja SearchView z RecyclerView

1) Dodaj element SearchView w menu

SearchViewmożna dodać jak actionVieww menu za pomocą

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) Zaimplementuj SearchView.OnQueryTextListener w swojej aktywności

SearchView.OnQueryTextListenerma dwie abstrakcyjne metody. Twój szkielet aktywności wyglądałby teraz tak po zaimplementowaniu nasłuchiwania tekstu SearchView.

YourActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{

   public boolean onQueryTextSubmit(String query)

   public boolean onQueryTextChange(String newText) 

}

3) Skonfiguruj tekst podpowiedzi SerchView, odbiornik itp

@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) Zaimplementuj SearchView.OnQueryTextListener

W ten sposób możesz zaimplementować abstrakcyjne metody słuchacza.

@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) Napisz metodę filtru w adapterze RecyclerView.

Możesz wymyślić własną logikę w oparciu o swoje wymagania. Oto przykładowy fragment kodu pokazujący listę Name, która zawiera tekst wpisany w 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();
}

Pełną działającą próbkę kodu można znaleźć> TUTAJ
Możesz również sprawdzić kod w SearchView z bazą danych SQLite w tej aplikacji muzycznej

Rohit Singh
źródło
Dlaczego menu jest potrzebne?
IgorGanapolsky
1

Implementacja SearchView bez użycia menu.xmlpliku i przycisku Otwórz za pomocą

W Twoim Activitymusimy użyć metody onCreateOptionsMenumetody, w której programowo zawyżamy plikSearchView

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

A w klasie Activity możesz otworzyć przycisk SearchViewna dowolnym przycisku, klikając pasek narzędzi, jak poniżej

YOUR_BUTTON.setOnClickListener(view -> {

            searchMenu.expandActionView();

        });
Ravindra Kushwaha
źródło