Как добавить SearchWidget в ActionBar?

Я пытаюсь добавить Search-ActionView в свое приложение (как описано здесь http://developer.android.com/guide/topics/search/search-dialog.html#UsingSearchWidget). К сожалению, я продолжаю получать NullPointerException, и мне трудно определить, что на самом деле происходит не так.

Я создал конфигурацию с возможностью поиска и действие с возможностью поиска, как показано на странице Android. Мой XML-файл меню выглядит так:

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    ...
    <item
        android:id="@+id/menu_item_search"
        android:actionViewClass="android.widget.SearchView"
        android:icon="@drawable/icon_search"
        android:showAsAction="always"
        android:title="@string/action_bar_button_search">
    </item>

</menu>

Это метод, в котором выдается исключение:

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

    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    SearchView searchView = (SearchView) menu.findItem(R.id.menu_item_search).getActionView();

    // NullPointerException thrown here; searchView is null.
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
    searchView.setIconifiedByDefault(false);

    return super.onCreateOptionsMenu( menu );
}

Полная трассировка стека:

FATAL EXCEPTION: main
java.lang.NullPointerException
at com.example.activities.Test.onCreateOptionsMenu(Test.java:41)
at android.app.Activity.onCreatePanelMenu(Activity.java:2444)
at com.android.internal.policy.impl.PhoneWindow.preparePanel(PhoneWindow.java:408)
at com.android.internal.policy.impl.PhoneWindow.invalidatePanelMenu(PhoneWindow.java:759)
at com.android.internal.policy.impl.PhoneWindow$1.run(PhoneWindow.java:2997)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4507)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
at dalvik.system.NativeStart.main(Native Method)

person Taig    schedule 30.06.2012    source источник
comment
можешь опубликовать весь код? Реализовали ли вы конфигурацию с возможностью поиска и активность с возможностью поиска, как описано в документе?   -  person rajpara    schedule 30.06.2012
comment
Как написано выше: поисковый xml и поисковая активность устанавливаются и добавляются в манифест. Строка 41 — это та, которую я прокомментировал с выброшенным здесь NullPointerException; searchView имеет значение null.   -  person Taig    schedule 30.06.2012
comment
Таким образом, проблема в том, что menu.findItem(R.id.menu_item_search).getActionView() продолжает возвращать значение null.   -  person Taig    schedule 30.06.2012
comment
как называется файл меню, согласно коду R.menu.action_bar и согласно описанию Мой файл menu .xml выглядит так   -  person Dheeresh Singh    schedule 01.07.2012
comment
просто подтверждаю, так как все остальное выглядит нормально.....   -  person Dheeresh Singh    schedule 01.07.2012


Ответы (7)


используйте этот способ, как в link

public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.action_bar, menu);
        MenuItem searchItem = menu.findItem(R.id.menu_item_search);
        SearchView searchView = (SearchView) searchItem.getActionView();


        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        if(null!=searchManager ) {   
         searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        }
        searchView.setIconifiedByDefault(false);

        return true;
    }
person Dheeresh Singh    schedule 30.06.2012
comment
хорошо, просто измените идентификатор на menu_item_search_1, чтобы разместить его, затем очистить и построить проект и запустить его... - person Dheeresh Singh; 01.07.2012
comment
java2s.com/Code/Android/UI/ - person Dheeresh Singh; 01.07.2012
comment
Я не понял, что именно пошло не так, но еще несколько попыток переименования, сборки и очистки каким-то образом решили проблему. У меня, наверное, где-то были какие-то глупые промахи.. - person Taig; 01.07.2012
comment
Я пробовал это решение, но все же searchView в строке searchView.setSearchableInfo(searchManager... имеет значение null. Как я могу получить фактический SearchView, как определено в файле menu.xml? - person David Miler; 03.10.2012
comment
Это, кажется, не решает проблему, и форматирование кода странное... - person Aubtin Samai; 18.12.2016

Поскольку этот вопрос просматривается довольно часто, и я снова и снова сталкивался с одной и той же проблемой, вот небольшое продолжение, в котором отслеживаются все необходимые шаги для создания SearchWidget.

Однако в SearchWidget есть одна непростая деталь: Если вы используете жестко закодированные строки в searchable.xml вместо ресурсов, приложение вылетит со сбивающим с толку сообщением об ошибке. Это отняло у меня слишком много часов моей жизни. ...

  1. Создайте действие для обработки результатов поиска

    public class Search extends Activity {}
    
  2. Добавьте файл searchable.xml в каталог res/xml (используйте ресурсы для подсказки и метки!)

    <searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:hint="@string/search_hint"
        android:includeInGlobalSearch="false"
        android:label="@string/search_label"
        android:searchSettingsDescription="@string/search_global_description" />
    
  3. Создайте правильный пункт меню «main.xml» в вашем каталоге res/menu.

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android" >
    
        <item
           android:id="@+id/options_menu_main_search"
           android:actionViewClass="android.widget.SearchView"
           android:icon="@drawable/icon_magnifier"
           android:showAsAction="always"
           android:title="Search"/>
    
    </menu>
    
  4. Обновите файл Manifest.xml: добавьте действие поиска и укажите, какие действия могут получать намерения поиска. Добавление <meta-data android:name="android.app.default_searchable" android:value=".app.Search" /> к узлу activity делает его доступным для поиска. Добавление его к узлу application делает все действия доступными для поиска.

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
        <application>
            <meta-data
                android:name="android.app.default_searchable"
                android:value=".app.Search" />
    
            <activity android:name=".activities.Search" >
                <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
    
            <meta-data
                android:name="android.app.searchable"
                android:resource="@xml/searchable" />
        </activity>
    </application>
    

  5. Add the SearchManager to your ActionView in every activity that should provide the SearchWidget

    public class Activity extends android.app.Activity
    {
        @Override
        public boolean onCreateOptionsMenu( Menu menu )
        {
            getMenuInflater().inflate( R.menu.main, menu );
    
            // Add SearchWidget.
            SearchManager searchManager = (SearchManager) getSystemService( Context.SEARCH_SERVICE );
            SearchView searchView = (SearchView) menu.findItem( R.id.options_menu_main_search ).getActionView();
    
            searchView.setSearchableInfo( searchManager.getSearchableInfo( getComponentName() ) );
    
            return super.onCreateOptionsMenu( menu );
        }
    }
    
person Taig    schedule 29.01.2013
comment
Спасибо! Действительно полезный ответ - person blganesh101; 17.06.2013
comment
Самый яркий пример, который я видел - person Tom Kincaid; 07.04.2014
comment
Мне бы помогло, если бы шаг 1 был разработан; это та часть, с которой у меня проблемы. - person Rock Lee; 11.06.2014

Если вы ориентируетесь на Android 2.x и используете android.support.v7.widget.SearchView, убедитесь, что файл menu.xml выглядит следующим образом (обратите внимание на yourapp пространство имен)

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:yourapp="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/search"
        android:title="@string/search"
        android:icon="@drawable/ic_search"
        yourapp:showAsAction="always"
        yourapp:actionViewClass="android.support.v7.widget.SearchView" />
</menu>

И в действии, где вы раздуваете меню, используйте:

android.support.v7.widget.SearchView searchView = (android.support.v7.widget.SearchView) 
MenuItemCompat.getActionView(menu.findItem(R.id.search));
person peceps    schedule 13.03.2014
comment
Это должно быть помечено как правильный ответ, первый ответ не имеет смысла, это searchView, который имеет значение null, а не searchManager. - person Saher Ahwal; 08.09.2014
comment
Спасибо за совет. Вы исправили мой нынешний характер. - person bmeulmeester; 16.07.2015

SearchView getActionView возвращает null

Как и в ссылке, откройте XML-файл меню и измените

android:actionViewClass="android.widget.SearchView"

в

app:actionViewClass="android.widget.SearchView" 

это сработало для меня

person QuinnX    schedule 21.07.2016

У меня тоже такая же проблема. В моем случае замена android:actionViewClass на app:actionViewClass решила проблему (с xmlns:app="http://schemas.android.com/apk/res-auto" в теге <menu>).

person stenlytw    schedule 02.06.2016

Прежде всего, создайте файл XML, содержащий SearchWidget, в папку макета.

<?xml version="1.0" encoding="utf-8"?>
<SearchView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/edit_query"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:inputType="textFilter"
    >

</SearchView>

Затем в своей деятельности извлеките панель действий

android.support.v7.app.ActionBar actionBar = getSupportActionBar();

Затем добавьте ссылку в представление поиска.

 actionBar.setCustomView(R.layout.custom_action_bar);
    search = (EditText) actionBar.getCustomView().findViewById(
            R.id.edit_query);

Затем установите параметр отображения для панели действий.

actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_HOME_AS_UP);

Вот и все.

Кстати, вы также можете использовать мой виджет поиска, который принимает список строк в виде списка массивов и отображает их, по введенному запросу. Как только пользователь выбирает конкретный результат, возвращается выбранный результат, который можно получить в onActivityResult родительского действия.

person Riya Gayasen    schedule 03.09.2016

Эта проблема вызвана отсутствующим фильтром намерений:

<intent-filter>
    <action android:name="android.intent.action.SEARCH" />
</intent-filter>
person tpbapp    schedule 27.01.2014