Android 片段中最近的查询建议
我在Android 片段中最近的查询建议,android,android-fragments,searchview,Android,Android Fragments,Searchview,我在Fragment中实现了SearchView,正如@David中建议的那样。有人知道如何在片段中向SearchView添加最近的查询建议吗 来自 步骤1-创建内容提供商 <TextView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tool="http://schemas.androi
Fragment
中实现了SearchView
,正如@David中建议的那样。有人知道如何在片段中向SearchView添加最近的查询建议吗 来自
步骤1-创建内容提供商
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tool="http://schemas.android.com/tools"
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:fontFamily="@font/poppins_bold"
android:textColor="@color/colorPrimary"
android:gravity="start|center"
android:paddingStart="30dp"
android:paddingEnd="30dp"
tool:text="hello" />
private var mSuggestionAdapter: SearchAdapter? = null
private lateinit var searchView: SearchView
private var queryTextListener: SearchView.OnQueryTextListener? = null
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_search ->
return false
}
searchView.setOnQueryTextListener(queryTextListener)
return super.onOptionsItemSelected(item)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu, menu)
val searchItem = menu.findItem(R.id.action_search)
val searchManager =
activity!!.getSystemService(Context.SEARCH_SERVICE) as SearchManager
mSuggestionAdapter = SearchAdapter(activity, null, 0)
if (searchItem != null) {
searchView = searchItem.actionView as SearchView
}
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(activity!!.componentName))
searchView.suggestionsAdapter = mSuggestionAdapter;
queryTextListener = object : SearchView.OnQueryTextListener {
override fun onQueryTextChange(newText: String): Boolean {
// Update Cursor With Each Query Text Change
val cursor = getRecentSuggestions(newText)
if (cursor != null) {
mSuggestionAdapter?.swapCursor(cursor)
}
return false
}
override fun onQueryTextSubmit(query: String): Boolean {
// Save Submitted Query To Adapter
val suggestions = SearchRecentSuggestions(
activity,
SuggestionProvider.AUTHORITY, SuggestionProvider.MODE
)
suggestions.saveRecentQuery(query, null)
// Do Your Search Stuff Here With Query
return true
}
}
searchView.setOnSuggestionListener(object : SearchView.OnSuggestionListener {
override fun onSuggestionSelect(position: Int): Boolean {
return false
}
override fun onSuggestionClick(position: Int): Boolean {
// On Clicking Suggestion Load It To Submit Query Listener
searchView.setQuery(mSuggestionAdapter?.getSuggestionText(position), true)
return true
}
})
searchView.setOnQueryTextListener(queryTextListener)
}
super.onCreateOptionsMenu(menu, inflater)
}
// Function To Retrieve Suggestion From Content Resolver
fun getRecentSuggestions(query: String): Cursor? {
val uriBuilder = Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SuggestionProvider.AUTHORITY)
uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY)
val selection = " ?"
val selArgs = arrayOf(query)
val uri = uriBuilder.build()
return activity?.contentResolver?.query(uri, null, selection, selArgs, null)
}
创建MySuggestionProvider类,我的类位于searchviewpager/utils/MySuggestionProvider
package com.soon.karat.searchviewpager.utils;
import android.content.SearchRecentSuggestionsProvider;
public class MySuggestionProvider extends SearchRecentSuggestionsProvider {
// AUTHORITY is a unique name, but it is recommended to use the name of the
// package followed by the name of the class.
public final static String AUTHORITY = "com.soon.karat.searchviewpager.utils.MySuggestionProvider";
// Uncomment line below, if you want to provide two lines in each suggestion:
// public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;
public final static int MODE = DATABASE_MODE_QUERIES;
public MySuggestionProvider() {
setupSuggestions(AUTHORITY, MODE);
}
}
步骤2-将提供者添加到清单中
class SuggestionProvider : SearchRecentSuggestionsProvider() {
init {
setupSuggestions(AUTHORITY, MODE)
}
companion object {
// Set As Path To This File
const val AUTHORITY = "com.your_package_name.SuggestionProvider"
const val MODE: Int = DATABASE_MODE_QUERIES
}
}
在应用程序级别的清单中添加以下代码行
<application...>
<provider
android:name=".utils.MySuggestionProvider"
android:authorities="com.soon.karat.searchviewpager.utils.MySuggestionProvider" />
常规
隐藏键盘并关闭SearchView
当用户完成向应用程序提交查询时,您可能希望隐藏键盘并关闭searchview。为此,请使用以下代码行
private void dismissKeyBoardAndSearchView() {
Helpers.hideKeyBoard(this);
// You should check if MenuItem is not null, otherwise the app would crash when rotating the screen
if (searchMenuItem != null) {
searchMenuItem.collapseActionView();
}
}
searchMenuItem是一个MenuItem,它与您在OnCreateOptions菜单中创建SearchView时使用的相同,您只需全局声明它以在另一个方法中访问,或者将它解析为方法:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
// -----------------------------------------------
// This is the MenuItem you will collapse
// -----------------------------------------------
searchMenuItem = menu.findItem(R.id.menu_search);
// -----------------------------------------------
SearchView searchView = (SearchView) searchMenuItem.getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setQueryRefinementEnabled(true);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
隐藏键盘在Helpers类中
public class Helpers {
public static void hideKeyBoard(Activity activity) {
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
View view = activity.getCurrentFocus();
if (view == null) {
view = new View(activity);
}
assert inputMethodManager != null;
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
在用户单击建议时进行处理
您可能会注意到,当用户单击建议时,不会发生任何事情,因为没有调用onQueryTextSubmit。Android只需重新启动活动并向其发送查询。然后,要处理建议中的单击,应添加以下代码:
假设进行搜索的活动与接收搜索的活动相同:
步骤1-将启动模式设置为singleTop
在清单中将activity launchMode设置为singleTop,以防止用户进行多次搜索时系统多次重新创建活动
<application...>
<provider
android:name=".utils.MySuggestionProvider"
android:authorities="com.soon.karat.searchviewpager.utils.MySuggestionProvider" />
<activity android:name=".SearchableActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
自定义最近的查询建议布局
class SuggestionProvider : SearchRecentSuggestionsProvider() {
init {
setupSuggestions(AUTHORITY, MODE)
}
companion object {
// Set As Path To This File
const val AUTHORITY = "com.your_package_name.SuggestionProvider"
const val MODE: Int = DATABASE_MODE_QUERIES
}
}
也许,您不喜欢最近查询建议的显示方式,那么您可以通过简单的方式更改其布局
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<!-- Add this line -->
<item name="searchViewStyle">@style/MySearchViewStyle</item>
</style>
<style name="MySearchViewStyle" parent="Widget.AppCompat.SearchView" >
<item name="suggestionRowLayout">@layout/my_search_dropdown_item_icons</item>
</style>
@颜色/原色
@颜色/原色暗
@颜色/颜色重音
@样式/MySearchViewStyle
@布局/我的搜索\下拉菜单\项目\图标
我的搜索\u下拉\u项目\u图标:这是您创建和自定义的布局
警告:您应该使用android在上一个布局中使用的相同ID,以使其正常工作。然后,转到这个文件@layout/abc\u search\u dropdown\u item\u icons\u 2line并复制相同的ID
如果您很难找到此abc文件,可以将@layout/my\u search\u dropdown\u item\u图标替换为-->@layout/abc\u search\u dropdown\u item\u icons\u 2line-->然后将光标置于“abc\u search…”并按Ctrl+B。您将被重定向到该文件,在该文件中可以使用相同的ID 来自
步骤1-创建内容提供商
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tool="http://schemas.android.com/tools"
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:fontFamily="@font/poppins_bold"
android:textColor="@color/colorPrimary"
android:gravity="start|center"
android:paddingStart="30dp"
android:paddingEnd="30dp"
tool:text="hello" />
private var mSuggestionAdapter: SearchAdapter? = null
private lateinit var searchView: SearchView
private var queryTextListener: SearchView.OnQueryTextListener? = null
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_search ->
return false
}
searchView.setOnQueryTextListener(queryTextListener)
return super.onOptionsItemSelected(item)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu, menu)
val searchItem = menu.findItem(R.id.action_search)
val searchManager =
activity!!.getSystemService(Context.SEARCH_SERVICE) as SearchManager
mSuggestionAdapter = SearchAdapter(activity, null, 0)
if (searchItem != null) {
searchView = searchItem.actionView as SearchView
}
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(activity!!.componentName))
searchView.suggestionsAdapter = mSuggestionAdapter;
queryTextListener = object : SearchView.OnQueryTextListener {
override fun onQueryTextChange(newText: String): Boolean {
// Update Cursor With Each Query Text Change
val cursor = getRecentSuggestions(newText)
if (cursor != null) {
mSuggestionAdapter?.swapCursor(cursor)
}
return false
}
override fun onQueryTextSubmit(query: String): Boolean {
// Save Submitted Query To Adapter
val suggestions = SearchRecentSuggestions(
activity,
SuggestionProvider.AUTHORITY, SuggestionProvider.MODE
)
suggestions.saveRecentQuery(query, null)
// Do Your Search Stuff Here With Query
return true
}
}
searchView.setOnSuggestionListener(object : SearchView.OnSuggestionListener {
override fun onSuggestionSelect(position: Int): Boolean {
return false
}
override fun onSuggestionClick(position: Int): Boolean {
// On Clicking Suggestion Load It To Submit Query Listener
searchView.setQuery(mSuggestionAdapter?.getSuggestionText(position), true)
return true
}
})
searchView.setOnQueryTextListener(queryTextListener)
}
super.onCreateOptionsMenu(menu, inflater)
}
// Function To Retrieve Suggestion From Content Resolver
fun getRecentSuggestions(query: String): Cursor? {
val uriBuilder = Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SuggestionProvider.AUTHORITY)
uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY)
val selection = " ?"
val selArgs = arrayOf(query)
val uri = uriBuilder.build()
return activity?.contentResolver?.query(uri, null, selection, selArgs, null)
}
创建MySuggestionProvider类,我的类位于searchviewpager/utils/MySuggestionProvider
package com.soon.karat.searchviewpager.utils;
import android.content.SearchRecentSuggestionsProvider;
public class MySuggestionProvider extends SearchRecentSuggestionsProvider {
// AUTHORITY is a unique name, but it is recommended to use the name of the
// package followed by the name of the class.
public final static String AUTHORITY = "com.soon.karat.searchviewpager.utils.MySuggestionProvider";
// Uncomment line below, if you want to provide two lines in each suggestion:
// public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;
public final static int MODE = DATABASE_MODE_QUERIES;
public MySuggestionProvider() {
setupSuggestions(AUTHORITY, MODE);
}
}
步骤2-将提供者添加到清单中
class SuggestionProvider : SearchRecentSuggestionsProvider() {
init {
setupSuggestions(AUTHORITY, MODE)
}
companion object {
// Set As Path To This File
const val AUTHORITY = "com.your_package_name.SuggestionProvider"
const val MODE: Int = DATABASE_MODE_QUERIES
}
}
在应用程序级别的清单中添加以下代码行
<application...>
<provider
android:name=".utils.MySuggestionProvider"
android:authorities="com.soon.karat.searchviewpager.utils.MySuggestionProvider" />
常规
隐藏键盘并关闭SearchView
当用户完成向应用程序提交查询时,您可能希望隐藏键盘并关闭searchview。为此,请使用以下代码行
private void dismissKeyBoardAndSearchView() {
Helpers.hideKeyBoard(this);
// You should check if MenuItem is not null, otherwise the app would crash when rotating the screen
if (searchMenuItem != null) {
searchMenuItem.collapseActionView();
}
}
searchMenuItem是一个MenuItem,它与您在OnCreateOptions菜单中创建SearchView时使用的相同,您只需全局声明它以在另一个方法中访问,或者将它解析为方法:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
// -----------------------------------------------
// This is the MenuItem you will collapse
// -----------------------------------------------
searchMenuItem = menu.findItem(R.id.menu_search);
// -----------------------------------------------
SearchView searchView = (SearchView) searchMenuItem.getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setQueryRefinementEnabled(true);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
隐藏键盘在Helpers类中
public class Helpers {
public static void hideKeyBoard(Activity activity) {
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
View view = activity.getCurrentFocus();
if (view == null) {
view = new View(activity);
}
assert inputMethodManager != null;
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
在用户单击建议时进行处理
您可能会注意到,当用户单击建议时,不会发生任何事情,因为没有调用onQueryTextSubmit。Android只需重新启动活动并向其发送查询。然后,要处理建议中的单击,应添加以下代码:
假设进行搜索的活动与接收搜索的活动相同:
步骤1-将启动模式设置为singleTop
在清单中将activity launchMode设置为singleTop,以防止用户进行多次搜索时系统多次重新创建活动
<application...>
<provider
android:name=".utils.MySuggestionProvider"
android:authorities="com.soon.karat.searchviewpager.utils.MySuggestionProvider" />
<activity android:name=".SearchableActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
自定义最近的查询建议布局
class SuggestionProvider : SearchRecentSuggestionsProvider() {
init {
setupSuggestions(AUTHORITY, MODE)
}
companion object {
// Set As Path To This File
const val AUTHORITY = "com.your_package_name.SuggestionProvider"
const val MODE: Int = DATABASE_MODE_QUERIES
}
}
也许,您不喜欢最近查询建议的显示方式,那么您可以通过简单的方式更改其布局
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<!-- Add this line -->
<item name="searchViewStyle">@style/MySearchViewStyle</item>
</style>
<style name="MySearchViewStyle" parent="Widget.AppCompat.SearchView" >
<item name="suggestionRowLayout">@layout/my_search_dropdown_item_icons</item>
</style>
@颜色/原色
@颜色/原色暗
@颜色/颜色重音
@样式/MySearchViewStyle
@布局/我的搜索\下拉菜单\项目\图标
我的搜索\u下拉\u项目\u图标:这是您创建和自定义的布局
警告:您应该使用android在上一个布局中使用的相同ID,以使其正常工作。然后,转到这个文件@layout/abc\u search\u dropdown\u item\u icons\u 2line并复制相同的ID
如果您很难找到此abc文件,可以将@layout/my\u search\u dropdown\u item\u图标替换为-->@layout/abc\u search\u dropdown\u item\u icons\u 2line-->然后将光标置于“abc\u search…”并按Ctrl+B。您将被重定向到该文件,在该文件中可以使用相同的ID 好的,我在github上的这个特定存储库的帮助下找到了这个解决方案,感谢他 下面是一个示例实现,介绍了如何在Kotlin-
class SuggestionProvider : SearchRecentSuggestionsProvider() {
init {
setupSuggestions(AUTHORITY, MODE)
}
companion object {
// Set As Path To This File
const val AUTHORITY = "com.your_package_name.SuggestionProvider"
const val MODE: Int = DATABASE_MODE_QUERIES
}
}
SearchAdapter.java
public class SearchAdapter extends CursorAdapter {
private static final String LOG_TAG =
SearchAdapter.class.getSimpleName();
public SearchAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = LayoutInflater.from(context).inflate(
R.layout.search_item, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
view.setTag(viewHolder);
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder viewHolder = (ViewHolder) view.getTag();
viewHolder.mTitle.setText(
cursor.getString(cursor.
getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1)));
}
public String getSuggestionText(int position) {
if (position >= 0 && position < getCursor().getCount()) {
Cursor cursor = getCursor();
cursor.moveToPosition(position);
return cursor.getString(cursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1));
}
return null;
}
public static class ViewHolder {
public TextView mTitle;
public ViewHolder(View view) {
// view of your custom layout
mTitle = (TextView) view.findViewById(R.id.text);
}
}
}
AndroidManifest.xml(确保android:authorities字段的路径与SuggestionProvider.kt AUTHORITY字段的路径相同)