Fragment 中的最近查询建议

hor*_*319 3 android android-fragments searchview

我按照@David在本主题中建议的SearchView方式实现了。有谁知道如何将最近的查询建议添加到 Fragment 中的 SearchView 中? Fragment

Soo*_*tos 6

来自安卓文档

第 1 步 - 创建内容提供商

创建 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

第 2 步 - 将提供商添加到清单中

在应用程序级别的清单中添加以下代码行

<application...>
        <provider
            android:name=".utils.MySuggestionProvider"
            android:authorities="com.soon.karat.searchviewpager.utils.MySuggestionProvider" />
Run Code Online (Sandbox Code Playgroud)

android:name:是你的SuggestionProvider类所在的路径。我的位于 searchviewpager/utils/MySuggestionProvider --> 因此名称将为 .utils.MySuggestionProvider

android:authorities:它与您在 SuggestionProvider 中放入的字符串 AUTHORITY 相同,它应该是相同的名称。

第 3 步 - 将搜索添加到您的 searchable.xml

将最后两行(searchSuggestAuthority 和 searchSuggestSelection)添加到您的 searchable.xml 中

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_name"
    android:hint="@string/search_for_anything"
    android:searchSuggestAuthority="com.soon.karat.searchviewpager.utils.MySuggestionProvider"
    android:searchSuggestSelection=" ?"/>
Run Code Online (Sandbox Code Playgroud)

android:searchSuggestAuthority:它与您在 MySuggestionProvider 类中放入的字符串 AUTHORITY 相同。

android:searchSuggestSelection:它只是一个空格和一个问号。

第 4 步 - 保存查询

每当用户提交查询时,您都应该将其保存在您的 SuggestionProvider 中,假设您将其保存在 onQueryTextSubmit 中

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            Log.i(TAG, "onQueryTextSubmit: Query was submitted");

            // -------------------------------------------------------
            //           Lines responsible to save the query 
            // -------------------------------------------------------
            SearchRecentSuggestions suggestions = new SearchRecentSuggestions(MainActivity.this,
                    MySuggestionProvider.AUTHORITY,
                    MySuggestionProvider.MODE);
            suggestions.saveRecentQuery(query, null);
            // -------------------------------------------------------

            displaySearchResults(query);

            // The listener can override the standard behavior by returning true to indicate that it has
            // handled the submit request. Otherwise return false to let the SearchView handle the
            // submission by launching any associated intent.
            return true;
        }
Run Code Online (Sandbox Code Playgroud)

附加内容

隐藏键盘并关闭 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

searchMenuItem 是一个MenuItem,它与您在 onCreateOptionsMenu 中创建 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) {
Run Code Online (Sandbox Code Playgroud)

隐藏键盘位于 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);
}
Run Code Online (Sandbox Code Playgroud)

}

当用户点击建议时进行处理

您可能会注意到,当用户单击建议时,不会发生任何事情,因为未调用 onQueryTextSubmit。Android 只需重新启动 Activity 并向其发送查询即可。然后,要处理建议中的点击,您应该添加以下代码:

假设进行搜索的活动与接收搜索的活动相同:

步骤 1 - 将 launchMode 设置为 singleTop

在清单中将 Activity launchMode 设置为 singleTop,以防止用户多次搜索时系统多次重新创建 Activity。

<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>
Run Code Online (Sandbox Code Playgroud)

第 2 步 - 处理 onCreate 和 onNewIntent 中的意图

您应该在 onCreate 和 onNewItent 中处理搜索意图。onNewIntent 是必要的,因为您将 Activity 设置为 singleTop,当应用程序收到搜索时,它不会重新创建 Activity 并调用 onCreate,而只会调用 onNewIntent。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    handleIntent(getIntent());
}


@Override
protected void onNewIntent(Intent intent) {
    setIntent(intent);
    handleIntent(intent);
}
Run Code Online (Sandbox Code Playgroud)

自定义您最近的查询建议布局

也许,您不喜欢最近查询建议的显示方式,那么您可以通过简单的方式更改其布局。

<!-- 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>
Run Code Online (Sandbox Code Playgroud)

my_search_drodown_item_icons:这是您创建并自定义的布局。

警告:您应该使用与之前布局相同的 android id 才能正常工作。然后,转到此文件 @layout/abc_search_dropdown_item_icons_2line 并复制相同的 id。

如果你很难找到这个 abc 文件,你可以将 @layout/my_search_dropdown_item_icons 替换为 --> @layout/abc_search_dropdown_item_icons_2line --> 然后将光标放入“abc_search...”并按 Ctrl+B。您将被重定向到该文件,您可以在其中获取相同的 ID。