11

Does anybody knows how to set android search dialog hint dynamically? T have try to do something like:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
 android:label="@string/search_label"
 android:hint="@string/search_hint"
 android:id="@+id/search_dialog_text">
</searchable>

Somewhere:

@Override
public boolean onSearchRequested() {
  Bundle appSearchData = new Bundle();
  appSearchData.putString("SomeSpecificParam", SomeClass.class.getName());
  startSearch("", false, appSearchData, false);
  EditText  text = (EditText )findViewById(R.id.search_dialog_text);
  text.setHint("Search something else");
  return true;
}

but text is equal null.

So looking forward you suggestions. Thanks.

Cristian
  • 191,931
  • 60
  • 351
  • 260
Boris
  • 111
  • 1
  • 3

7 Answers7

5

This feels pretty hacky but worked for me - not truly dynamic but worked for alternating between the two search hints I needed:

  1. I created a second searchable.xml (as described in the Android search docs), called searchable2.xml, with my second search hint defined.
  2. I created a dummy activity extended from my original activity and overriding nothing.
  3. In the manifest the dummy activity was associated with the new searchable2.xml:

    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
        <meta-data android:name="android.app.searchable"
            android:resource="@xml/searchable"/>
    </activity>
    
    <activity android:name=".DummyActivity">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
        <meta-data android:name="android.app.searchable"
            android:resource="@xml/searchable2"/>
    </activity>
    
  4. In 'MainActivity' I overrode 'onSearchRequested()' to reference the appropriate searchable activity:

    
    public boolean onSearchRequested()
     {
           SearchManager searchManager = (SearchManager)getSystemService(Context.SEARCH_SERVICE);
    if(searchManager!=null) { // start the search with the appropriate searchable activity // so we get the correct search hint in the search dialog if(/* your condition here */) searchManager.startSearch(null, false,new ComponentName(this, MainActivity.class), null, false); else searchManager.startSearch(null, false,new ComponentName(this, DummyActivity.class), null, false); return true; } return false; }

Nasty. But desperate times call for desperate measures...

AFAIK, and from looking at the Android source the class is only used to look up the metadata, but if anybody knows differently then please let me know.

  • Very interesting hack. Messy, but it seems effective. Can you think of a way to allow this to happen dynamically? i.e. update the search hint at runtime? e.g. format a hint string with a live count of how many items are being searched – ohhorob Dec 14 '10 at 20:06
2

I managed to do this with ABS using the OnActionExpandListener and a custom actionView, e.g.:

menu.add("Search")
.setActionView(R.layout.collapsible_edittext)
.setOnActionExpandListener(new MenuItem.OnActionExpandListener()
{
    @Override
    public boolean onMenuItemActionExpand(MenuItem item) {
        ((EditText) item.getActionView()).setHint("Your custom text here");
        return true;
    }

    @Override
    public boolean onMenuItemActionCollapse(MenuItem item) {
        return true;
    }
});

with collapsible_edittext.xml:

<EditText
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textColor="@color/search_fg"
    android:background="@drawable/textfield_default_holo_light"
    android:hint="[will be replaced at runtime]"/>
Elroid
  • 456
  • 4
  • 11
2

If you are using the Toolbar and SearchView widgets, you can easily set the search query hint by calling:

SearchView.setQueryHint(CharSequence hint)
TheIT
  • 10,803
  • 3
  • 59
  • 53
2

They've added a note at http://developer.android.com/guide/topics/search/search-dialog.html#SearchableConfiguration stating that

Note: The system uses this file to instantiate a SearchableInfo object, but you cannot create this object yourself at runtime—you must declare the searchable configuration in XML.

So it seems that the answer to your question is that you cannot set the search dialog hint dynamically.

Roy Solberg
  • 14,329
  • 9
  • 39
  • 68
1

There is a much simpler answer than any of the above. It loads the default searchable.xml for your activity, and then uses java reflection to update the private mHintId field inside the SearchableInfo instance:

@Override
public void onPrepareOptionsMenu(Menu menu) {
    SearchManager searchManager = (SearchManager)getActivity().getSystemService(Context.SEARCH_SERVICE);
    SearchableInfo si = searchManager.getSearchableInfo( getActivity().getComponentName() );

    try {
        Field mHintId = si.getClass().getDeclaredField("mHintId");
        mHintId.setAccessible(true);
        mHintId.setInt(si, R.string.your_custom_hint);
    } catch (Exception e) {
    }

    MenuItem mi = menu.findItem(R.id.menu_search);
    SearchView searchView = (SearchView)mi.getActionView();
    searchView.setSearchableInfo( si );
}
zyamys
  • 1,479
  • 1
  • 19
  • 22
  • The above is the best, simplest method. Forget about all the other complex suggestions ! – Mario S May 12 '14 at 05:49
  • @zyamys from which class and what method are you calling invalidateLayout() so that this onPrepareOptionsMenu() override is called? Thanks! – Rachael Jul 25 '16 at 21:27
  • It is called by the framework, you don't need to call Activity. invalidateOptionsMenu() unless you need to for some unrelated reason. – zyamys Jul 25 '16 at 21:31
1

It looks like you're almost there.

The SearchDialog source does this to get the auto complete editable.

mSearchAutoComplete = (SearchAutoComplete) findViewById(com.android.internal.R.id.search_src_text);

(note that the SearchAutoComplete class is a subclass of AutoCompleteTextView)

ohhorob
  • 11,465
  • 7
  • 37
  • 50
0

Thanks Mister Murakami for the idea, i have implemented the same concept to perform toggle search and as per my view its not a hack but its beauty of OOPs. Below program having a toggle icon in the action bar to switch between search hint.

  1. RestaurantListingActivity.java

    public class RestaurantListingActivity extends BaseMainActivity implements
    TabListener {
    private boolean isRestaurantSearch = true;
    private SearchManager searchManager;
    private SearchView searchView;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActionBar aBar = getActionBar();
        aBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        aBar.addTab(aBar.newTab().setText("Place Order").setTabListener(this));
        aBar.addTab(aBar.newTab().setText("My Account").setTabListener(this));
        aBar.addTab(aBar.newTab().setText("Favorite").setTabListener(this));
        aBar.addTab(aBar.newTab().setText("Vendor Portal").setTabListener(this));
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.restaturant_listing_menu, menu);
        searchManager = (SearchManager) getSystemService(SEARCH_SERVICE);
        searchView = (SearchView) menu.findItem(R.id.rlm_search)
                .getActionView();
        searchView.setSearchableInfo(searchManager
                .getSearchableInfo(new ComponentName(this,
                        RestaurantListingActivity.class)));
        return super.onCreateOptionsMenu(menu);
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.rlm_toggle:
    isRestaurantSearch = !isRestaurantSearch;
        if (isRestaurantSearch)
            searchView.setSearchableInfo(searchManager
                    .getSearchableInfo(new ComponentName(this,
                            RestaurantListingActivity.class)));
        else
            searchView.setSearchableInfo(searchManager
                    .getSearchableInfo(new ComponentName(this,
                            RestaurantFoodSwitcherActivity.class)));
    
    
        break;
    case R.id.rlm_change_loc:
    
        break;
    case R.id.rlm_filter_search:
    
        break;
    }
    
        return super.onOptionsItemSelected(item);
    }
    
    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // TODO Auto-generated method stub
    
    }
    
    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
    // TODO Auto-generated method stub
    }
    
    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        // TODO Auto-generated method stub
    
    }
    
    @Override
    public void setScreenData(Object screenData, int event, long time) {
        // TODO Auto-generated method stub
    
    }
    
    @Override
    public Activity getMyActivityReference() {
        // TODO Auto-generated method stub
        return null;
    }
    
    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
    
    }
    }
    
  2. restaurant_listing_menu

<item
    android:id="@+id/rlm_toggle"
    android:showAsAction="always"
    android:title="Toggle Search"
    android:icon="@drawable/ic_action_refresh"
    >
</item>
<item
    android:id="@+id/rlm_search"
    android:showAsAction="always|collapseActionView"
    android:title="Search"
    android:icon="@drawable/ic_action_search"
    android:actionViewClass="android.widget.SearchView"
    >
</item>
<item
    android:id="@+id/rlm_filter_search"
    android:showAsAction="ifRoom"
    android:title="Filter Search"
    android:icon="@drawable/ic_action_settings"
    >
</item>
<item
    android:id="@+id/rlm_change_loc"
    android:showAsAction="ifRoom"
    android:title="Change Location"
    android:icon="@drawable/ic_action_location_off"
    >
</item>

  1. searchablerestra.xml inside res>xml

    <?xml version="1.0" encoding="utf-8"?>
    <searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:hint="@string/search_hint_restra"
    android:label="@string/app_name">
    </searchable>
    
  2. RestaurantFoodSwitcherActivity.java

    public class RestaurantFoodSwitcherActivity extends RestaurantListingActivity {
    }
    
  3. searchablefood.xml

    <?xml version="1.0" encoding="utf-8"?>
    <searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:hint="@string/search_hint_food"
        android:label="@string/app_name">
    </searchable>
    
  4. manifest.xml

    <activity         android:name="com.example.app.ui.activity.RestaurantListingActivity" >
        <!-- This intent-filter identifies this activity as "searchable" -->
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
    
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        <!-- This metadata entry provides further configuration details for searches -->
        <!-- that are handled by this activity. -->
        <meta-data
            android:name="android.app.searchable"
            android:resource="@xml/searchablerestra"
    
             />
    </activity>
    <activity android:name="com.example.app.ui.activity.RestaurantFoodSwitcherActivity">
        <!-- This intent-filter identifies this activity as "searchable" -->
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
    
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        <!-- This metadata entry provides further configuration details for searches -->
        <!-- that are handled by this activity. -->
         <meta-data
            android:name="android.app.searchable"
            android:resource="@xml/searchablefood"
             />
    </activity>
    
RQube
  • 854
  • 2
  • 11
  • 27