新增自訂搜尋建議

試試 Compose
Jetpack Compose 是 Android 推薦的 UI 工具包。瞭解如何在 Compose 中新增搜尋功能。

您可以根據 Android 搜尋對話方塊或搜尋小工具中的近期搜尋查詢,提供搜尋建議。舉例來說,如果使用者查詢「小狗」,當他們再次輸入相同查詢時,系統就會顯示建議。圖 1 顯示搜尋對話方塊範例,其中包含最近查詢建議。

開始前,請先在應用程式中導入搜尋對話方塊或搜尋小工具,以進行基本搜尋。如需操作說明,請參閱「建立搜尋介面」。

基本概念

圖 1. 螢幕截圖:搜尋對話方塊,顯示最近的查詢建議。

近期搜尋建議是已儲存的搜尋查詢。使用者選取建議後,可搜尋的活動會收到 ACTION_SEARCH 意圖,建議會做為可搜尋活動已處理的搜尋查詢。

如要提供近期查詢建議,請按照下列步驟操作:

  • 實作可搜尋的活動。
  • 建立擴充 SearchRecentSuggestionsProvider 的內容供應器,並在應用程式資訊清單中宣告。
  • 修改可搜尋的設定,加入提供搜尋建議的內容供應商資訊。
  • 每次執行搜尋時,將查詢儲存至內容供應商。

Android 系統會顯示搜尋對話方塊,並在對話方塊或搜尋小工具下方顯示搜尋建議。您提供來源,系統會從中擷取建議。

當系統判斷您的活動可供搜尋並提供搜尋建議時,使用者輸入查詢內容時會發生下列情況:

  1. 系統會擷取搜尋查詢文字 (使用者開始輸入的任何內容),並對含有建議的內容供應程式執行查詢。
  2. 內容供應商會傳回 Cursor,指向與搜尋查詢文字相符的所有建議。
  3. 系統會顯示 Cursor 提供的建議清單。

顯示最近的查詢建議後,可能會發生下列情況:

  • 如果使用者輸入其他鍵或以任何方式變更查詢,系統會重複上述步驟,並更新建議清單。
  • 如果使用者執行搜尋,系統會忽略建議,並使用正常的 ACTION_SEARCH 意圖,將搜尋結果傳送至可搜尋的活動。
  • 如果使用者選取建議,系統會將 ACTION_SEARCH 意圖傳送至可搜尋的活動,並以建議的文字做為查詢。

您為內容供應器擴充的 SearchRecentSuggestionsProvider 類別會自動執行上述步驟中的工作,因此您幾乎不需要編寫程式碼。

建立內容供應器

您需要內容供應器 (實作 SearchRecentSuggestionsProvider),才能提供近期查詢建議。這個類別會為您處理所有事項。您只需要編寫類別建構函式,執行一行程式碼即可。

舉例來說,以下是最近查詢建議的內容供應器完整實作項目:

Kotlin

class MySuggestionProvider : SearchRecentSuggestionsProvider() {
    init {
        setupSuggestions(AUTHORITY, MODE)
    }

    companion object {
        const val AUTHORITY = "com.example.MySuggestionProvider"
        const val MODE: Int = SearchRecentSuggestionsProvider.DATABASE_MODE_QUERIES
    }
}

Java

public class MySuggestionProvider extends SearchRecentSuggestionsProvider {
    public final static String AUTHORITY = "com.example.MySuggestionProvider";
    public final static int MODE = DATABASE_MODE_QUERIES;

    public MySuggestionProvider() {
        setupSuggestions(AUTHORITY, MODE);
    }
}

setupSuggestions() 的呼叫會傳遞搜尋授權單位名稱和資料庫模式。搜尋授權可以是任何不重複的字串,但最佳做法是使用內容供應器的完整名稱,例如套件名稱,後面加上供應器的類別名稱。例如 "com.example.MySuggestionProvider"

資料庫模式必須包含 DATABASE_MODE_QUERIES,且可視需要包含 DATABASE_MODE_2LINES,這會在建議表格中新增資料欄,方便您為每項建議提供第二行文字。如要在每個建議中提供兩行文字,請參閱下列範例:

Kotlin

const val MODE: Int = DATABASE_MODE_QUERIES or DATABASE_MODE_2LINES

Java

public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;

在應用程式資訊清單中宣告內容供應器,並使用與 SearchRecentSuggestionsProvider 類別和可搜尋設定中相同的授權字串。例如:

<application>
    <provider android:name=".MySuggestionProvider"
              android:authorities="com.example.MySuggestionProvider" />
    ...
</application>

修改可供搜尋的設定

如要設定系統使用建議提供者,請在可搜尋的設定檔中,將 android:searchSuggestAuthorityandroid:searchSuggestSelection 屬性新增至 <searchable> 元素。例如:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_label"
    android:hint="@string/search_hint"
    android:searchSuggestAuthority="com.example.MySuggestionProvider"
    android:searchSuggestSelection=" ?" >
</searchable>

android:searchSuggestAuthority 的值必須是內容供應商的完整名稱,且與內容供應商中使用的授權完全一致,例如上述範例中的 "com.example.MySuggestionProvider"

android:searchSuggestSelection 的值必須是單一問號,且前面要加上空格:" ?"。這是 SQLite 選取引數的預留位置,系統會自動將其替換為使用者輸入的查詢文字。

儲存查詢

如要填入近期查詢的集合,請將可搜尋活動收到的每項查詢新增至 SearchRecentSuggestionsProvider。如要執行這項操作,請建立 SearchRecentSuggestions 的例項,並在可搜尋活動每次收到查詢時呼叫 saveRecentQuery()。舉例來說,以下說明如何在活動的 onCreate() 方法中儲存查詢:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main)

    if (Intent.ACTION_SEARCH == intent.action) {
        intent.getStringExtra(SearchManager.QUERY)?.also { query ->
            SearchRecentSuggestions(this, MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE)
                    .saveRecentQuery(query, null)
        }
    }
}

Java

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Intent intent  = getIntent();

    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        String query = intent.getStringExtra(SearchManager.QUERY);
        SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
                MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE);
        suggestions.saveRecentQuery(query, null);
    }
}

SearchRecentSuggestionsProvider 建構函式需要與內容供應商宣告的授權和資料庫模式相同。

saveRecentQuery() 方法會將搜尋查詢字串做為第一個參數,並視需要將第二個字串做為建議的第二行或空值。只有在您使用 DATABASE_MODE_2LINES 為搜尋建議啟用雙行模式時,才會用到第二個參數。如果啟用雙行模式,系統在尋找相符的建議時,會比對查詢文字與第二行。

清除建議資料

為保護使用者隱私,請務必提供清除近期查詢建議的方法。如要清除查詢記錄,請呼叫 clearHistory()。 例如:

Kotlin

SearchRecentSuggestions(this, HelloSuggestionsProvider.AUTHORITY, HelloSuggestionsProvider.MODE)
        .clearHistory()

Java

SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
        HelloSuggestionProvider.AUTHORITY, HelloSuggestionProvider.MODE);
suggestions.clearHistory();

從「清除搜尋記錄」選單項目、偏好設定項目或按鈕中執行此操作。 提供確認對話方塊,確認使用者是否要刪除搜尋記錄。