Search code examples
androidsearchviewandroid-searchsearch-suggestion

How to open list of search suggestions programatically?


I have a SearchView in my Android application which can show suggestions to the given input. Now I want the following behaviour: If I finish the keyboard input and press the "enter" button on the softkeyboard, then I want the keyboard to disappear but the list with the search suggestions should remain. The behaviour right now is, that if I enter some letters, the suggestions appear (good!) but if I am done and press enter, the list disappears (bad!). So how can I reopen the list but leave the keyboard hidden?

Usually, the intent ACTION_SEARCH is fired and is handled in a way that a new activity opens and shows the search results. I only want the list with suggestions to be opened.

Some of the source code:

In the onCreate() of the AddTeam Class:

    SearchView searchView= (SearchView) findViewById(R.id.searchView);
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){

        @Override
        public boolean onQueryTextSubmit(String s) {
            InputMethodManager inputManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
            return false;
        }

        @Override
        public boolean onQueryTextChange(String s) {
            return false;
        }
    });


    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));

Intent Handling:

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    handleIntent(intent);
}

private void handleIntent(Intent intent) {
    if (Intent.ACTION_VIEW.equals(intent.getAction())) {
        // handles a click on a search suggestion; launches activity to show word
        Uri uri = intent.getData();
        Cursor cursor = managedQuery(uri, null, null, null, null);

        if (cursor == null) {
            finish();
        } else {
            cursor.moveToFirst();
            doMoreCode();
        }
    } else if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        // handles a search query
        String query = intent.getStringExtra(SearchManager.QUERY);
        //////////////////////////////////////////////////////
        //WANTED FEATURE!
        OpenSearchSuggestionsList();
        //WANTED FEATURE!
        //////////////////////////////////////////////////////



    }
}

Manifest:

    <activity
        android:name=".AddTeam"
        android:configChanges="keyboard|screenSize|orientation"
        android:label="@string/title_activity_teamchooser"
        android:launchMode="singleTop" >

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

Searchable:

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/title_activity_settings"
        android:hint="@string/search_hint"
        android:searchSettingsDescription="Enter Word"
        android:searchSuggestAuthority="com.mypackage.DataProvider"
        android:searchSuggestIntentAction="android.intent.action.VIEW"
        android:searchSuggestIntentData="content://com.mypackage.DataProvider/teamdaten"
        android:searchSuggestSelection=" ?"
        android:searchSuggestThreshold="1"
        android:includeInGlobalSearch="true"
        >
 </searchable>

Part of AddTeam Layout xml:

<android.support.v7.widget.SearchView
    android:id="@+id/searchView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:textColor="#000000"
    volleyballinfo:iconifiedByDefault="false"
    volleyballinfo:queryHint="@string/search_hint"/>

Solution

  • Note: My answer is only based on source code inspection, and may not produce positive/favorable results. Also, the code below is written from memory - it may contain typos.

    Ok. Internally, SearchView uses a custom AutoCompleteTextView to display suggestions. This custom AutoCompleteTextView listens for the submit event through multiple channels: View.OnKeyListener, overridden SearchView#onKeyDown(int, KeyEvent) and OnEditorActionListener.

    On a submit event (when the ENTER key is pressed - in your case), the suggestions-popup is dismissed using SearchView#dismissSuggestions:

    private void dismissSuggestions() {
        mSearchSrcTextView.dismissDropDown();
    }
    

    As you can see, SearchView#dismissSuggestions() calls to AutoCompleteTextView#dismissDropDown(). So, to show the dropdown, we should be able to call AutoCompleteTextView#showDropDown().

    But, the custom AutoCompleteTextView instance used by the SearchView is private with no accessors defined. In this case, we can try to find this View, cast it to AutoCompleteTextView, and call showDropDown() on it.

    ....
    // Your snippet
    else if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        // handles a search query
        String query = intent.getStringExtra(SearchManager.QUERY);
        OpenSearchSuggestionsList(searchView);
    }
    ....
    
    // Edited
    // This method will accept the `SearchView` and traverse through 
    // all of its children. If an `AutoCompleteTextView` is found,
    // `showDropDown()` will be called on it.
    private void OpenSearchSuggestionsList(ViewGroup viewGroup) {
        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            View child = viewGroup.getChildAt(i);
    
            if (child instanceof ViewGroup) {
                OpenSearchSuggestionsList((ViewGroup)child);
            } else if (child instanceof AutoCompleteTextView) {
                // Found the right child - show dropdown
                ((AutoCompleteTextView)child).showDropDown();
                break; // We're done
            }
        }
    }
    

    Looking forward to your comment(s) on this.