如何将SearchWidget添加到ActionBar?

时间:2012-06-30 17:16:32

标签: android nullpointerexception android-actionbar searchview

我正在尝试将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)

7 个答案:

答案 0 :(得分:49)

由于这个问题经常被查询,我偶然发现了同样的问题,这里有一点跟进,跟踪创建SearchWidget的所有必要步骤。

SearchWidget有一个棘手的部分:如果你在searchable.xml中使用硬编码的字符串而不是资源,应用程序将崩溃并出现令人困惑的错误消息。这花了我太多时间我的生活...

  1. 创建一个活动来处理搜索结果

    public class Search extends Activity {}
    
  2. 添加文件&#34; searchable.xml&#34;到您的res / xml目录(使用资源提示&amp;标签!

    <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. 创建适当的菜单项&#34; main.xml&#34;在您的res /菜单目录

    <?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. 在应提供SearchWidget

    的每个活动中将SearchManager添加到ActionView
    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 );
        }
    }
    

答案 1 :(得分:24)

如果您使用 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));

答案 2 :(得分:20)

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

答案 3 :(得分:7)

SearchView getActionView returning null

在链接中,打开菜单xml文件并更改

android:actionViewClass="android.widget.SearchView"

进入

app:actionViewClass="android.widget.SearchView" 

这对我有用

答案 4 :(得分:2)

我也遇到了同样的问题。就我而言,将android:actionViewClass更改为app:actionViewClass可以解决问题 (xmlns:app="http://schemas.android.com/apk/res-auto"标记中的<menu>

答案 5 :(得分:1)

首先,创建一个包含SearchWidget到您的布局文件夹的XML文件

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

就是这样。

顺便说一下,您还可以使用我的search widget,它将字符串列表作为数组列表并根据输入的查询显示它们。一旦用户选择了特定结果,就返回所选结果,该结果可以在父活动的onActivityResult上检索。

答案 6 :(得分:0)

此问题由缺少的意图过滤器触发:

<intent-filter>
    <action android:name="android.intent.action.SEARCH" />
</intent-filter>