Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 片段中最近的查询建议_Android_Android Fragments_Searchview - Fatal编程技术网

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字段的路径相同)

  • 就是这样,在片段中有一个搜索栏,可以控制查询结果如何处理搜索和最近的建议