Установить подсказку поиска динамически
Кто-нибудь знает, как динамически настроить подсказку для поиска в Android? Я должен попытаться сделать что-то вроде:
<?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>
Где-то:
@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;
}
но текст равен нулю.
Ждем ваших предложений. Благодарю.
7 ответов
Это выглядит довольно странно, но сработало для меня - не совсем динамично, но сработало для чередования двух нужных мне подсказок:
- Я создал второй файл searchable.xml (как описано в поисковой документации Android), который называется searchable2.xml, с моим вторым поиском подсказки.
- Я создал фиктивную деятельность, расширенную от моей первоначальной деятельности и ничего не перекрывающую.
В манифесте фиктивная активность была связана с новым 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>
В 'MainActivity' я переопределил 'onSearchRequested()' для ссылки на соответствующую активность поиска:
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; }
Насти. Но отчаянные времена требуют отчаянных мер...
AFAIK, и при просмотре исходного кода Android класс используется только для поиска метаданных, но если кто-то знает по-другому, пожалуйста, дайте мне знать.
Если вы используете Toolbar
а также SearchView
виджеты, вы можете легко установить подсказку поискового запроса, вызвав:
SearchView.setQueryHint(CharSequence hint)
Они добавили заметку по адресу http://developer.android.com/guide/topics/search/search-dialog.html которой говорится, что
Примечание. Система использует этот файл для создания экземпляра объекта SearchableInfo, но вы не можете создать этот объект самостоятельно во время выполнения - вы должны объявить конфигурацию с возможностью поиска в XML.
Таким образом, кажется, что ответ на ваш вопрос заключается в том, что вы не можете установить подсказку в диалоговом окне поиска динамически.
Мне удалось сделать это с ABS, используя OnActionExpandListener и пользовательский actionView, например:
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;
}
});
с 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]"/>
Существует гораздо более простой ответ, чем любой из вышеперечисленных. Он загружает по умолчанию searchable.xml для вашей деятельности, а затем использует java-отражение для обновления частного поля mHintId внутри экземпляра SearchableInfo:
@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 );
}
Похоже, ты почти там.
SearchDialog
источник делает это, чтобы получить автоматическое редактирование.
mSearchAutoComplete = (SearchAutoComplete) findViewById(com.android.internal.R.id.search_src_text);
(обратите внимание, что SearchAutoComplete
класс является подклассом AutoCompleteTextView
)
Спасибо мистеру Мураками за идею, я реализовал ту же концепцию для выполнения поиска с переключением, и, на мой взгляд, это не хак, а красота ООП. Внизу программы есть значок переключения на панели действий для переключения между подсказками поиска.
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 } }
- 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>
searchablerestra.xml внутри 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>
RestaurantFoodSwitcherActivity.java
public class RestaurantFoodSwitcherActivity extends RestaurantListingActivity { }
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>
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>