Ответ 1
Я обнаружил, что searchable.xml не должен содержать литералов, а только ресурсов. Я потратил около полудня на это, так как он заставил getSearchableInfo терпеть неудачу.
У меня возникли проблемы с настройкой вида поиска в панели действий.
Я следил за сайтом разработчика, но он не работает. У меня такое чувство, что я чего-то не хватает.
Когда я запускаю свой код, он всегда выводит "не удалось получить информацию для поиска" (MainActivity.setupSearchView()).
MainActivity.java
// package...
// imports...
public class MainActivity extends Activity {
private static String tag = "Main Activity";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater mi = getMenuInflater();
mi.inflate(R.menu.search_view, menu);
setupSearchView(menu);
return true;
}
private void setupSearchView(Menu menu) {
SearchManager sm = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchableInfo si = sm.getSearchableInfo(getComponentName());
if (si == null) {
Log.wtf(tag, "failed to get searchable info");
return;
}
SearchView sv = (SearchView) menu.findItem(R.id.menu_search).getActionView();
sv.setSearchableInfo(si);
// Do not iconify the widget; expand it by default
sv.setIconifiedByDefault(false);
}
}
SearchResultsActivity.java
// package...
// imports...
public class SearchResultsActivity extends ListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent queryIntent = getIntent();
doSearchQuery(queryIntent);
}
@Override
public void onNewIntent(final Intent newIntent) {
super.onNewIntent(newIntent);
final Intent queryIntent = getIntent();
doSearchQuery(queryIntent);
}
}
searchable.xml
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="@string/search_hint"
android:label="@string/search_label" >
</searchable>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="kpaek.examples"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".search.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SearchResultsActivity">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
</application>
</manifest>
Я обнаружил, что searchable.xml не должен содержать литералов, а только ресурсов. Я потратил около полудня на это, так как он заставил getSearchableInfo терпеть неудачу.
В моем случае для меня использовались пользовательские теги в res/menu/mymenu.xml
:
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"
Не использовать:
android:showAsAction="ifRoom|collapseActionView"
android:actionViewClass="android.support.v7.widget.SearchView"
Я обнаружил, что элементы-фильтры и элементы метаданных должны быть включены в элемент активности манифеста, с которого инициирован поиск (MainActivity с SearchView) для метода getSearchableInfo (getComponentName()), чтобы вернуть правильное конфигурации, а не null.
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
Интересно, если вместо этого (и решение, которое я собираюсь делать сейчас), следует оставить намерение и метаданные в объявлении активности результатов и изменить аргумент getSearchableInfo() следующим образом:
<activity android:name=".SearchResultsActivity">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
И изменения в MainActivity (обратите внимание на оператор присваивания для searchableInfo):
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_search, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView mySearchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
SearchableInfo searchableInfo = searchManager.getSearchableInfo(new ComponentName(getApplicationContext(), SearchResultsActivity.class));
mySearchView.setSearchableInfo(searchableInfo);
return true;
}
Это убило меня в течение дня - я думал, что это связано с ActionBarSherlock, но нет, это прекрасно работает с этим.
Проблема заключалась в том, что я пытался закоротить образец. По крайней мере, одно из ваших действий - того, из которого вы выполняете поиск, достаточно - в этом манифестах должен быть этот фильтр-замысел:
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
Если нет, то searchManager.getSearchableInfo(getComponentName())
всегда возвращает null, а ваша конфигурация игнорируется.
От разработчика:
Конфигурация с возможностью поиска определяет, как ведет себя SearchView и определенный в файле res/xml/searchable.xml. Как минимум, доступный для поиска конфигурация должна содержать атрибут android: label, который имеет то же значение, что и атрибут android: label в манифесте Android.
В качестве примера они показывают:
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:hint="@string/search_hint" />
app_name, как и в вашем манифесте, является меткой активности. Однако в вашей поисковой метке метка относится к search_label. Работает, возможно, если app_name и search_label равны, но это кажется мне хрупким.
Я столкнулся с этой проблемой, но приведенный выше совет не разрешил ее. Вместо этого оказалось, что значение параметра по умолчанию установлено в SearchResultActivity. Например, следующие разрывы:
<activity android:name=".SearchResultActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
Удаление android.intent.category.DEFAULT устраняет эту проблему.:
<activity android:name=".SearchResultActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
Также в предыдущих ответах на этот вопрос есть ошибка. MainActivity следует определить с помощью android.app.default_searchable. android.app.searchable предназначен только для вашей поисковой службы.
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<!-- other stuff-->
<meta-data android:name="android.app.default_searchable"
android:value=".SearchResultsActivity" />
</activity>
В заключение SearchManager является хрупким компонентом, подверженным молчащим сбоям, когда AndroidManifest.xml не идеален.
Я потратил 8 полных часов на это, потому что я проверил все вышеупомянутые решения, но одна вещь отсутствовала для меня.
В моем манифесте Android:
<meta-data
android:name="android.app.searchable"
android:value="@xml/searchable" />
Должно было:
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
Для меня это терпело неудачу. Лучше всего сначала сделать копию и вставить примеры. Просто убедитесь, что все ваши атрибуты точно такие же.