Как использовать SearchView на панели инструментов Android

124

Код, над которым я работаю, использует Toolbar и раздувает menu.

Вот код

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

Но теперь им требуется Searchкнопка в файле tool_bar. Мне удалось это поставить, я следовал руководству здесь. Когда я пытаюсь написать что-то для поиска, тост, который я поставил для проверки, listenerникогда не показывался. что указывает listenerна не работает

@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
источник

Ответы:

205

Для этого вам нужно использовать Appcompatбиблиотеку. Что используется, как показано ниже:

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>

Файл активности (на 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);
}

Файл активности (на Котлине):

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

файл манифеста:

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

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

И, наконец, SearchResultsActivityкод вашего класса. для отображения результата вашего поиска.

Сагар Майяд
источник
18
Обратите внимание, что теперь вы должныimport android.support.v7.widget.SearchView
Хоакин Иурчук
Спасибо, есть идеи, как обрабатывать щелчок "Go"? это поможет
Бала Вишну
2
Я просто свяжусь с официальной документацией, где вы также можете узнать, как реагировать на запрос developer.android.com/training/search/setup.html
koesclem 02
2
Обратите внимание на приложение: actionViewClass вместо android: actionViewClass
DragonT
1
Если вы перешли на androidX, используйте:androidx.appcompat.widget.SearchView
Даниил
169

Если вы хотите настроить средство поиска внутри себя Fragment, просто добавьте эти несколько строк:

Шаг 1 - Добавьте вам поле поиска 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"/>

Шаг 2 - Добавьте логику в свойonCreateOptionsMenu()

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
источник
29
Этот ответ гораздо полезнее, если вы не хотите создавать / переходить к новому действию, когда пользователь отправил поисковый запрос. Это позволит вам оставаться на одном и том же действии / фрагменте и просто обновлять представление на основе ввода пользователя. Отличный материал.
Nick.D
3
UserFeedback ... это мой метод, похожий на тост.
tm1701
Ввод с клавиатуры не
Сараванан
Что R.menu.main?
Alston
public void onCreateOptionsMenu (@NonNull Menu menu, @NonNull MenuInflater inflater) {} вы можете напрямую вызвать этот метод, здесь вы можете внедрить собственное меню и обрабатывать это напрямую из фрагмента без использования активности. хорошее спасибо
Амар Сингх
40

Если вы хотите добавить его прямо на панель инструментов.

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

Али
источник
2
Если вы используете поддержку SearchView, не забудьте также объявить ее как android.support.v7.widget.SearchViewв XML.
Брошенная тележка
не забудьте добавить в gradleimplementation 'com.android.support:design:$latest_version'
Али
Что значимо ?
IgorGanapolsky
¨Если вы хотите, чтобы поле поиска всегда было видно, вызовите setIconifiedByDefault (false) ¨ из документации
noe
16

Интеграция SearchView с RecyclerView

1) Добавить элемент SearchView в меню

SearchViewможно добавить как actionViewв меню, используя

приложение: 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) Реализуйте SearchView.OnQueryTextListener в своей деятельности

SearchView.OnQueryTextListenerимеет два абстрактных метода. Итак, ваш каркас активности теперь будет выглядеть так после реализации текстового прослушивателя SearchView.

YourActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{

   public boolean onQueryTextSubmit(String query)

   public boolean onQueryTextChange(String newText) 

}

3) Настройте текст подсказки SerchView, слушателя и т. Д.

@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) Реализуйте SearchView.OnQueryTextListener

Вот как вы можете реализовать абстрактные методы слушателя.

@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) Напишите метод фильтрации в вашем адаптере RecyclerView.

Вы можете придумать свою собственную логику, исходя из ваших требований. Вот пример фрагмента кода для отображения списка Name, который содержит текст, введенный в 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();
}

Полный образец рабочего кода можно найти> ЗДЕСЬ
Вы также можете проверить код в SearchView с базой данных SQLite в этом музыкальном приложении.

Рохит Сингх
источник
Зачем нужно меню?
IgorGanapolsky
1

Реализация SearchView без использования menu.xmlфайла и кнопки открытия

В вашем Activityнам нужно использовать метод onCreateOptionsMenuметода, в котором мы программно раздуваемSearchView

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

И в своем классе Activity вы можете открыть SearchViewлюбую кнопку, нажав на панели инструментов, как показано ниже

YOUR_BUTTON.setOnClickListener(view -> {

            searchMenu.expandActionView();

        });
Равиндра Кушваха
источник