我对 java 和 android 开发还很陌生;我一直在开发一个应用程序,我想要一个带有
SearchView
的操作栏。我看过谷歌的例子,但我无法让它工作。我一定做错了什么,我即将放弃应用程序开发:D 我已经搜索过,但没有发现任何有用的东西。也许你们可以帮助我:)
问题:我让搜索视图按其应有的方式打开,但之后什么也没有发生,我注意到我的 searchManager.getSearchableInfo(getComponentName()) 返回 null。另外,我给出的提示没有显示在我的搜索框中,这让我相信应用程序可能找不到我的 searchable.xml?说够了:)
MainActivity.java
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
// Get the SearchView and set the searchable configuration
SearchManager searchManager =
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView =
(SearchView) menu.findItem(R.id.menu_search).getActionView();
searchView.setSearchableInfo(
searchManager.getSearchableInfo(getComponentName()));
return true;
}
}
可搜索.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/app_label">
</searchable>
Android清单
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.searchapp"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity android:name=".SearchableActivity" >
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data android:name="android.app.searchable"
android:resource="@xml/searchable"/>
</application>
</manifest>
SearchableActivity.java
package com.example.searchapp;
import android.app.ListActivity;
import android.app.SearchManager;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
public class SearchableActivity extends ListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
// Get the intent, verify the action and get the query
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
doMySearch(query);
}
}
private void doMySearch(String query) {
Log.d("Event",query);
}
}
这是所引用项目的链接,如果有人帮助我,我将永远感激不已!
您的问题出在您的 AndroidManifest 中。我的情况几乎和你一样,因为这就是我按照文档得到的。但不清楚或有误。
观看 API 演示源代码,我发现“android.app.searchable”元数据必须放入您的“结果”活动中,并且在主活动(或放置 SearchView 的活动)中,您指向另一个活动“android.app.default_searchable”。
您可以在以下文件中看到它,这是我的测试项目中的Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.default_searchable"
android:value=".SearchActivity" />
</activity>
<activity
android:name=".SearchActivity"
android:label="@string/app_name" >
<!-- 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/searchable" />
</activity>
</application>
同样重要的是,searchable.xml 中的提示和标签是引用,而不是硬编码的字符串。
我希望它能解决您的问题。我花了一整天才弄清楚:(
Android 指南明确指出:
// Assumes current activity is the searchable activity
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
您的情况是不正确的。因为您不想在 MainActivity 中搜索,而是在 SearchableActivity 中搜索。这意味着您应该使用此 ComponentName 而不是 getComponentName() 方法:
ComponentName cn = new ComponentName(this, SearchableActivity.class);
searchView.setSearchableInfo(searchManager.getSearchableInfo(cn));
而且 android:hint 和 android:label 属性必须都是对 strings.xml 中字符串的引用。偷懒并对字符串值进行硬编码似乎根本不起作用:)
即不要这样做:
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="Search for something..."
android:label="My App">
</searchable>
但一定要这样做(正如OP正确所做的那样):
<?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/app_label">
</searchable>
如果您使用的是 Android Studio,
<meta-data
android:name="android.app.default_searchable"
android:value=".SearchActivity" />
部分可能无法工作。
写出完整的包名称,例如
<meta-data
android:name="android.app.default_searchable"
android:value="com.example.test.SearchActivity" />
小心“xml/searchable.xml”。 如果您使用
android:hint
和 android:label
制作硬代码。它将不起作用。哈哈
应该是:
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="@string/app_name"
android:label="@string/search_lb"
android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"/>
实际上没有必要使用上面答案中描述的“缺失部分”。此方法(使用
SearchView
)的工作方式与官方文档完全相同,直到使用搜索小部件。这里需要稍作修改如下:
SearchableInfo
中的属性用于显示标签、提示、建议、创建启动搜索结果屏幕的意图以及控制其他功能,例如语音按钮(docs)。
因此,我们传递给
SearchableInfo
的 SearchView.setSearchableInfo(SearchableInfo s)
对象必须包含对目标活动的正确引用,应显示该目标活动以显示搜索结果。这是通过手动传递目标活动的 ComponentName
来完成的。用于创建 ComponentName
的一个构造函数是
public ComponentName (String pkg, String cls)
pkg
和cls
是要启动用于显示搜索结果的目标活动的包名称和类名称。请注意:
pkg
必须指向您项目的根包名称,并且,
cls
必须是类的完全限定名称(即整个事物)
例如:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
// Get the SearchView and set the searchable configuration
String pkg = "com.example.musicapp"
String cls = "com.example.musicapp.search.SearchActivity"
ComponentName mycomponent = new ComponentName(pkg,cls);
SearchManager searchManager =(SearchManager)getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(mycomponent));
searchView.setIconifiedByDefault(false); //if using on actionbar
return true;
}
根据您的要求,查看其他
ComponentName
构造函数。
确保您的
searchables.xml
文件位于正确的位置(即在您的 res/xml/
文件夹中)并且同一文件不包含任何错误 - 否则您会发现 (SearchManager)getSystemService(Context.SEARCH_SERVICE).getSearchableInfo(componentName)
将返回 null,从而破坏您的搜索功能.
(另外,请确保以适当的方式设置
componentName
,因为 Android 指南中显示的示例仅适用于您在同一 Activity 中进行搜索和显示搜索时。)
我在将这样的搜索意图过滤器添加到可搜索活动时遇到了同样的问题:
<activity
android:launchMode="singleTop"
android:name=".ui.activities.MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<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>
用于搜索位置,如果您从 APK 文件中收到返回行或空响应,并且您的代码是
if (actionId == EditorInfo.IME_ACTION_SEARCH
//EditorInfo.IME_ACTION_SEARCH
//over riding our enter key
|| actionId == EditorInfo.IME_ACTION_DONE
|| keyEvent.getAction() == KeyEvent.ACTION_DOWN
|| keyEvent.getAction() == KeyEvent.KEYCODE_ENTER) {
确保在您的 xml 文件中将资源设置为键入文本,否则上面的搜索功能将无法工作。
android:hint="Enter location"
android:inputType="text"
android:imeOptions="actionSearch"
仔细检查相应的条目(即search_hint和app_label)是否存在于values/strings.xml中
例如
<string name="app_label">FunApp</string>
<string name="search_hint">Caps Off</string>