Tuesday, November 21, 2017

Implementing SearchView in Toolbar with Fragments managed by your MainActivity

Google the above and you will get multiple ways that people have taken to implement search results as a fragment. One of the other pickles is passing the "results" of the search, back to the main activity.

Android wants you to use an Activity to handle the search results, but in my current app, I am using the "navigation drawer" pattern and to me it made sense to have my main activity manage the search and use fragments to display the results.

Now, I could have done this by taking control of the Search Widget and SearchView's setOnQueryTextListener. Although this works well and in some ways would be easier,  I wanted to take advantage of some of the more interesting possibilities provided by using a ContentProvider and letting the Android do the search management.

So, to implement Fragment support for the results, I did the following....


in the AndriodManifest.xml I added the following to my MainActivity:

<activity    
  android:name=".MainActivity"    
  android:launchMode="singleTask"

 <intent-filter>
        ...
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>
    <meta-data android:name="android.app.searchable"        
              android:resource="@xml/searchconfig"/>
</activity>

The android:launchMode="singleTask" causes the activity to remain the root task and more importantly the system does not recreate it if it already exists. The System routes the intent to existing instance through a call to its onNewIntent() method. The MainActivity can now handle the creating the fragment and displaying the search results

Now, inside MainActivity:

@Overrideprotected void onNewIntent(Intent intent) {
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        String query = intent.getStringExtra(SearchManager.QUERY);
         if(null!=query&&query.length()>0){
            // Manage search fragment here...        }
    }
}

And to set up the search bar:

 @Override   public boolean onCreateOptionsMenu(Menu menu) {
       // Inflate the menu; this adds items to the action bar if it is present.      
       getMenuInflater().inflate(R.menu.main, menu);
       MenuItem searchItem = menu.findItem(R.id.action_search);
       SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
       final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
       searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); // We are the searchable activity

       return true;
   }

Hope this helps!