JakeP JakeP - 4 months ago 20
Android Question

Android - NullPointerException on SearchView in Action Bar

I've got a problem trying to add a SearchView widget to the ActionBar in my activity - I get a null value when calling getActionView to get my SearchView object.

I've been following the Android Developer guide and also went through a ton of SO questions as well as some other links on the Internet; all to no avail. It could be something simple but I wasn't able to figure it out - it seems to me my code is basically the same as that from google (apart from changing some names etc.) but it still won't work.

Any help would be appreciated.

Included below are relevant bits of the code. Please let me know if anything's unclear of if you have any idea as to what could possibly be wrong.

Activity code:

private ListView workflowListView;
private DrawerLayout drawerLayout;
private ListView drawerList;
private ActionBarDrawerToggle drawerToggle;

@Override
protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
setContentView(R.layout.activity_workflow_list);

workflowListView = (ListView) findViewById(R.id.workflowListView);
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerList = (ListView) findViewById(R.id.drawer_list);

drawerToggle = new ActionBarDrawerToggle(
this, /* host Activity */
drawerLayout, /* DrawerLayout object */
R.drawable.ic_launcher, /* nav drawer icon to replace 'Up' caret */
R.string.app_name, /* "open drawer" description */
R.string.app_name /* "close drawer" description */
) {

/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
// getActionBar().setTitle("Closed drawer");
}

/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
// getActionBar().setTitle("Open drawer");
}
};

drawerLayout.setDrawerListener(drawerToggle);
ActionBar actionBar = getActionBar();
actionBar.setDisplayShowTitleEnabled(false);

actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
actionBar.setIcon(android.R.color.transparent);

String[] testData = {"a", "b", "c", "d"};
ArrayList<String> workflowList = new ArrayList<String>();
for (String s : testData) {

workflowList.add(s);
}

ArrayAdapter<String> workflowAdapter = new ArrayAdapter<String>(this.getApplicationContext(), R.layout.workflow_list_item, workflowList);

workflowListView.setAdapter(workflowAdapter);
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
MenuInflater inflater = getMenuInflater();

inflater.inflate(R.menu.workflow_list, menu);
inflater.inflate(R.menu.options_menu, menu);

// Associate searchable configuration with the SearchView
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);

// The below line returned null even though it was used in Google sample code
SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();

searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));

return super.onCreateOptionsMenu(menu);
}


xml/searchable.xml:

<?xml version="1.0" encoding="utf-8"?>

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:hint="@string/search_hint"
android:includeInGlobalSearch="false" />


menu/options_menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >

<item android:id="@+id/search"
android:title="@string/search_title"
android:icon="@drawable/ic_action_search"
android:showAsAction="always|collapseActionView"
android:actionViewClass="android.support.v7.widget.SearchView" />
</menu>

Answer

Try to replace the failing line with:

mSearchMenuItem = menu.findItem(R.id.action_search);
mSearchView = (EnglishVerbSearchView) MenuItemCompat.getActionView(mSearchMenuItem);

Where R.id.action_search is the id of your search item in the menu.

EDIT

Your manifest should look like that:

<activity
       android:name="com.bronzelabs.twc.activities.WorkflowListActivity"
       android:label="@string/app_name"
       android:theme="@style/Theme.AppCompat.Light" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>
<activity 
        android:name=".activities.SearchResultActivity"
        android:theme="@style/Theme.AppCompat.Light"
        android:launchMode="singleTop">
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
        <meta-data android:name="android.app.searchable" android:resource="@xml/searchable"
            android:value=".activities.SearchResultActivity" />
    </activity>

The way you call setSearchableInfo is:

mSearchView.setSearchableInfo(searchManager.getSearchableInfo(
            new ComponentName(getApplicationContext(), SearchResultActivity.class)));

EDIT 2

Make sure your menu xml file is like that (pay attention to those 2 attributes with yourapp namespace - this is needed when you use the compat library):

<menu xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
    <item android:id="@+id/action_search"
      android:title="@string/action_search"
      android:icon="@drawable/action_search"
      yourapp:showAsAction="always|collapseActionView"
      yourapp:actionViewClass="android.support.v7.widget.SearchView" />
</menu>
Comments