hguser
hguser

Reputation: 36028

SearchView method .setQuery does not work

I am using the Search interface in andriod, and folowing the android guide I have set up the the interface.

I create a SearchableActivity which will handle both the user input the search result.

Now I meet a problem in that when user input something in the SearchView and hit the search key, the Search requset will be submited, then I will receive the query string and do the search, but at this moment, the text in the SearchView was changed to the default SearchHit value while I want it to be the query string.

So I tried to use the searchView.setQuery(query, false);, but it does not work, what's the problem?

The core Activity codes:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.map_activity_layout);

    Log.d("map", "create");
    handleIntent(getIntent());
}

public void onNewIntent(Intent intent) {
    setIntent(intent);
    handleIntent(intent);
}

private void handleIntent(Intent intent) {
    Log.d("map", "handleIntent");
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        String query = intent.getStringExtra(SearchManager.QUERY);
        //try search
        Log.d("map", "search and set query:" + query);
        searchView.setQuery(query, false); // reset the value in of the SearchView
    }
}

The AndroidManifest.xml:

    <activity
        android:name=".ui.MapActivity"
        android:launchMode="singleTop">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
        <meta-data
            android:name="android.app.searchable"
            android:resource="@xml/searchable" />
    </activity>

Upvotes: 23

Views: 13161

Answers (6)

Martin Zeitler
Martin Zeitler

Reputation: 76639

Meanwhile this works slightly different. One does not need any Runnable or MenuCompat ...

 public class SomeMenuProvider implements MenuProvider {

    /** Setting up the SearchView. */
    @Override
    public void onCreateMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
        inflater.inflate(this.resId, menu);

        MenuItem searchItem = menu.findItem(R.id.menu_action_search_view);
        this.searchView = (SearchView) searchItem.getActionView();
        if (this.searchView != null) {
            
            this.searchView.setOnQueryTextListener(this.listener);

            SearchManager searchManager = (SearchManager) this.getMainActivity().getSystemService(Context.SEARCH_SERVICE);
            ComponentName component = new ComponentName(this.getMainActivity(), MainActivity.class);
            SearchableInfo searchableInfo = searchManager.getSearchableInfo(component);
            this.searchView.setSearchableInfo(searchableInfo);
            
            String searchTerm = this.getSearchTerm();
            if (searchTerm != null) {
                searchItem.expandActionView();
                searchView.setQuery(searchTerm, false);
            }
        }
    }
    ...
 }

One has to use one search-term previously extracted from the intent and stored.

@Nullable
private String getSearchTerm() {
    if (this.getMainActivity().getCurrentFragment() instanceof SomeFragment fragment) {
        return fragment.getSearchTerm();
    }
    return null;
}

Because else one might try to access a Menu, which had not been inflated yet.

Upvotes: 0

Oded
Oded

Reputation: 993

In my case, it wasn't working because the fragment I was in was no longer attached to the window. Moving it to above where I swapped in the new search results fragment fixed it.

Upvotes: 1

fikr4n
fikr4n

Reputation: 3420

I suggest you to delay the setting until the next event loop (add it to the message queue), so the code may looks like this:

private void handleIntent(Intent intent) {
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        final String query = intent.getStringExtra(SearchManager.QUERY);
        searchView.post(new Runnable() {

            @Override
            public void run() {
                // Important! Make sure searchView has been initialized
                // and referenced to the correct (current) SearchView.
                // Config changes (e.g. screen rotation) may make the
                // variable value null.
                searchView.setQuery(query, false);
            }
        };
    }
}

Upvotes: 19

JosephM
JosephM

Reputation: 2935

need to put code in post handler with MenuItemCompat

inflater.inflate(R.menu.menu_my_team, menu);
    // search manager integration for search widget
    SearchManager searchManager = (SearchManager) getActivity()
            .getSystemService(Context.SEARCH_SERVICE);
    final MenuItem searchMenuItem = menu.findItem(R.id.action_search);
    //    MenuItem helpTutorialMenuItem = menu.findItem(R.id.action_help);
    mSearchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);

    mSearchView.setSearchableInfo(searchManager
            .getSearchableInfo(getActivity().getComponentName()));

    mSearchView.setQueryHint("Search by");

    if (!TextUtils.isEmpty(queryText)) {
        mSearchView.post(new Runnable() {
            @Override
            public void run() {
                MenuItemCompat.expandActionView(searchMenuItem);
                mSearchView.setQuery(queryText, false);
            }
        });
    }
    mSearchView.clearFocus();

Upvotes: 4

Christophe Smet
Christophe Smet

Reputation: 870

This doesn't work

    mSearchView.setQuery(mKeyword, true);
    MenuItemCompat.expandActionView(mMenuSearch);

This does

    MenuItemCompat.expandActionView(mMenuSearch);
    mSearchView.setQuery(mKeyword, true);

It seems it only remembers it after you expanded the action view. I'm using MenuItemCompat just for backwards compatibility

Upvotes: 14

hguser
hguser

Reputation: 36028

It seems that when the intent with Action Intent.ACTION_SEARCH is received, the following method will be called:

handleIntent();

onCreateOptionsMenu();

And the handleIntent will run before the onCreateOptionsMenu.

At the same time, people used to setup the searchView at the onCreateOptionsMenu.

Which means that the option menu will be re-inflated, and the searchView will be re-build, then all the settings in the handleIntent will not work.

I think this is the reason.

Please feel free to fix me if I am wrong.

Upvotes: 2

Related Questions