Tạo giao diện tìm kiếm

Khi bạn đã sẵn sàng thêm chức năng tìm kiếm vào ứng dụng của mình, Android sẽ giúp bạn triển khai giao diện người dùng bằng hộp thoại tìm kiếm xuất hiện ở đầu cửa sổ hoạt động hoặc tiện ích tìm kiếm mà bạn có thể chèn vào bố cục của mình. Cả hộp thoại tìm kiếm và tiện ích đều có thể phân phối cụm từ tìm kiếm của người dùng đến một hoạt động cụ thể trong ứng dụng của bạn. Bằng cách này, người dùng có thể bắt đầu tìm kiếm từ bất kỳ hoạt động nào có hộp thoại hoặc tiện ích tìm kiếm, đồng thời hệ thống sẽ bắt đầu hoạt động thích hợp để thực hiện việc tìm kiếm và trình bày kết quả.

Các tính năng khác có sẵn cho hộp thoại tìm kiếm và tiện ích bao gồm:

  • Tìm kiếm bằng giọng nói
  • Cụm từ tìm kiếm được đề xuất dựa trên những cụm từ tìm kiếm gần đây
  • Nội dung tìm kiếm được đề xuất khớp với kết quả thực tế trong dữ liệu ứng dụng của bạn

Tài liệu này trình bày cách thiết lập ứng dụng để cung cấp giao diện tìm kiếm được hệ thống Android hỗ trợ để cung cấp các cụm từ tìm kiếm bằng cách sử dụng hộp thoại tìm kiếm hoặc tiện ích tìm kiếm.

Tài nguyên liên quan:

Thông tin cơ bản

Trước khi bắt đầu, hãy quyết định xem bạn muốn triển khai giao diện tìm kiếm bằng cách sử dụng hộp thoại tìm kiếm hay tiện ích tìm kiếm. Chúng cung cấp các tính năng tìm kiếm tương tự nhưng theo những cách hơi khác nhau:

  • Hộp thoại tìm kiếm là một thành phần giao diện người dùng do hệ thống Android kiểm soát. Khi được người dùng kích hoạt, hộp thoại tìm kiếm sẽ xuất hiện ở đầu hoạt động.

    Hệ thống Android kiểm soát tất cả sự kiện trong hộp thoại tìm kiếm. Khi người dùng gửi một truy vấn, hệ thống sẽ phân phối truy vấn đó đến hoạt động mà bạn chỉ định để xử lý các lượt tìm kiếm. Hộp thoại cũng có thể đưa ra đề xuất tìm kiếm trong khi người dùng nhập.

  • Tiện ích tìm kiếm là một thực thể của SearchView mà bạn có thể đặt vào bất cứ đâu trong bố cục của mình. Theo mặc định, tiện ích tìm kiếm hoạt động như một tiện ích EditText tiêu chuẩn và không làm gì cả. Tuy nhiên, bạn có thể định cấu hình tiện ích này để hệ thống Android xử lý mọi sự kiện nhập, phân phối truy vấn đến hoạt động thích hợp và cung cấp nội dung đề xuất tìm kiếm (giống như hộp thoại tìm kiếm).

Khi người dùng thực thi nội dung tìm kiếm qua hộp thoại tìm kiếm hoặc tiện ích tìm kiếm, hệ thống sẽ tạo một Intent và lưu trữ cụm từ tìm kiếm của người dùng trong đó. Sau đó, hệ thống sẽ khởi động hoạt động mà bạn khai báo để xử lý các hoạt động tìm kiếm – "hoạt động có thể tìm kiếm" và truyền ý định cho hoạt động đó. Để thiết lập ứng dụng cho loại hình tìm kiếm được hỗ trợ này, bạn cần có:

  • Cấu hình tìm kiếm
    Tệp XML định cấu hình một số chế độ cài đặt cho hộp thoại hoặc tiện ích tìm kiếm. Giao diện này có cả chế độ cài đặt cho các tính năng như tìm kiếm bằng giọng nói, cụm từ tìm kiếm được đề xuất và văn bản gợi ý cho hộp tìm kiếm.
  • Một hoạt động có thể tìm kiếm
    Activity sẽ nhận cụm từ tìm kiếm, tìm kiếm dữ liệu của bạn và hiển thị kết quả tìm kiếm.
  • Giao diện tìm kiếm, được cung cấp bởi một trong các thành phần sau:
    • Hộp thoại tìm kiếm
      Theo mặc định, hộp thoại tìm kiếm sẽ bị ẩn. Nút này xuất hiện ở đầu màn hình khi bạn gọi onSearchRequested() khi người dùng nhấn vào nút Search (Tìm kiếm).
    • Tiện ích SearchView
      Khi sử dụng tiện ích tìm kiếm, bạn có thể đặt hộp tìm kiếm ở bất cứ đâu trong hoạt động của mình, bao gồm cả khung hiển thị hành động trong thanh ứng dụng.

Phần còn lại của tài liệu này cho bạn biết cách tạo cấu hình tìm kiếm và hoạt động có thể tìm kiếm cũng như cách triển khai giao diện tìm kiếm bằng hộp thoại tìm kiếm hoặc tiện ích tìm kiếm.

Tạo cấu hình có thể tìm kiếm

Điều đầu tiên bạn cần là một tệp XML có tên là cấu hình tìm kiếm. Tệp này định cấu hình một số khía cạnh trên giao diện người dùng của hộp thoại hoặc tiện ích tìm kiếm và xác định cách hoạt động của các tính năng như đề xuất và tính năng tìm kiếm bằng giọng nói. Tệp này thường có tên là searchable.xml và phải được lưu trong thư mục dự án res/xml/.

Tệp cấu hình tìm kiếm phải bao gồm phần tử <searchable> làm nút gốc và chỉ định một hoặc nhiều thuộc tính, như trong ví dụ sau:

<?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" >
</searchable>

Thuộc tính android:label là thuộc tính bắt buộc duy nhất. Tham số này trỏ đến một tài nguyên chuỗi, phải là tên ứng dụng. Người dùng không nhìn thấy nhãn này cho đến khi bạn bật tính năng đề xuất tìm kiếm cho Hộp Tìm kiếm Nhanh. Lúc này, nhãn sẽ xuất hiện trong danh sách các mục có thể Tìm kiếm trong phần cài đặt hệ thống.

Mặc dù không bắt buộc nhưng bạn nên luôn thêm thuộc tính android:hint. Thuộc tính này cung cấp chuỗi gợi ý trong hộp tìm kiếm trước khi người dùng nhập truy vấn. Gợi ý rất quan trọng vì nó cung cấp các gợi ý quan trọng cho người dùng về nội dung họ có thể tìm kiếm.

Phần tử <searchable> chấp nhận một số thuộc tính khác. Tuy nhiên, bạn không cần phải có hầu hết các thuộc tính cho đến khi thêm các tính năng như đề xuất tìm kiếmtìm kiếm bằng giọng nói. Để biết thông tin chi tiết về tệp cấu hình tìm kiếm, hãy xem tài liệu tham khảo về Cấu hình tìm kiếm.

Tạo hoạt động có thể tìm kiếm

Hoạt động có thể tìm kiếm là Activity trong ứng dụng của bạn. Hoạt động này thực hiện việc tìm kiếm dựa trên chuỗi truy vấn và trình bày kết quả tìm kiếm.

Khi người dùng thực hiện một nội dung tìm kiếm trong hộp thoại hoặc tiện ích tìm kiếm, hệ thống sẽ bắt đầu hoạt động có thể tìm kiếm của bạn và gửi cho người dùng cụm từ tìm kiếm đó trong một Intent bằng thao tác ACTION_SEARCH. Hoạt động có thể tìm kiếm của bạn sẽ truy xuất truy vấn từ phần bổ sung QUERY của ý định, sau đó tìm kiếm dữ liệu của bạn và trình bày kết quả.

Vì bạn có thể đưa hộp thoại hoặc tiện ích tìm kiếm vào bất kỳ hoạt động nào khác trong ứng dụng của mình, nên hệ thống phải biết hoạt động nào là hoạt động có thể tìm kiếm của bạn để có thể phân phối chính xác truy vấn tìm kiếm. Vì vậy, trước tiên, hãy khai báo hoạt động có thể tìm kiếm trong tệp kê khai Android.

Khai báo hoạt động có thể tìm kiếm

Nếu bạn chưa có khoá truy cập nào, hãy tạo một Activity để thực hiện hoạt động tìm kiếm và trình bày kết quả. Bạn chưa cần triển khai chức năng tìm kiếm mà chỉ cần tạo một hoạt động mà bạn có thể khai báo trong tệp kê khai. Bên trong phần tử <activity> của tệp kê khai, hãy làm như sau:

  1. Khai báo hoạt động để chấp nhận ý định ACTION_SEARCH trong phần tử <intent-filter>.
  2. Chỉ định cấu hình tìm kiếm để sử dụng trong phần tử <meta-data>.

Lệnh này được minh hoạ trong ví dụ sau:

<application ... >
    <activity android:name=".SearchableActivity" >
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
        <meta-data android:name="android.app.searchable"
                   android:resource="@xml/searchable"/>
    </activity>
    ...
</application>

Phần tử <meta-data> phải bao gồm thuộc tính android:name có giá trị "android.app.searchable" và thuộc tính android:resource có tham chiếu đến tệp cấu hình có thể tìm kiếm. Trong ví dụ trước, tệp này đề cập đến tệp res/xml/searchable.xml.

Tìm kiếm

Sau khi bạn khai báo hoạt động có thể tìm kiếm trong tệp kê khai, hãy làm theo quy trình sau để thực hiện tìm kiếm trong hoạt động có thể tìm kiếm của bạn:

  1. Nhận truy vấn.
  2. Tìm kiếm dữ liệu của bạn.
  3. Trình bày kết quả.

Nhận yêu cầu

Khi người dùng thực hiện một hoạt động tìm kiếm qua hộp thoại hoặc tiện ích tìm kiếm, hệ thống sẽ bắt đầu hoạt động có thể tìm kiếm và gửi ý định ACTION_SEARCH cho hoạt động đó. Ý định này mang cụm từ tìm kiếm trong phần bổ sung chuỗi QUERY. Kiểm tra ý định này khi hoạt động bắt đầu và trích xuất chuỗi. Ví dụ: dưới đây là cách bạn có thể nhận cụm từ tìm kiếm khi hoạt động có thể tìm kiếm bắt đầu:

Kotlin

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

    // Verify the action and get the query.
    if (Intent.ACTION_SEARCH == intent.action) {
        intent.getStringExtra(SearchManager.QUERY)?.also { query ->
            doMySearch(query)
        }
    }
}

Java

@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);
    }
}

Chuỗi QUERY luôn đi kèm với ý định ACTION_SEARCH. Trong ví dụ trước, truy vấn được truy xuất và chuyển đến phương thức doMySearch() cục bộ để thực hiện thao tác tìm kiếm thực tế.

Tìm dữ liệu của bạn

Quá trình lưu trữ và tìm kiếm dữ liệu là riêng biệt đối với ứng dụng của bạn. Bạn có thể lưu trữ và tìm kiếm dữ liệu của mình theo nhiều cách nhưng tài liệu này không hướng dẫn bạn cách thực hiện. Cân nhắc cách bạn lưu trữ và tìm kiếm dữ liệu theo nhu cầu và định dạng dữ liệu của bạn. Sau đây là những mẹo mà bạn có thể áp dụng:

  • Nếu dữ liệu của bạn được lưu trữ trong cơ sở dữ liệu SQLite trên thiết bị, thì việc tìm kiếm toàn bộ văn bản (bằng FTS3 thay vì truy vấn LIKE) có thể mang lại khả năng tìm kiếm hiệu quả hơn trên dữ liệu văn bản và có thể đưa ra kết quả nhanh hơn đáng kể. Hãy truy cập vào sqlite.org để biết thông tin về FTS3 và lớp SQLiteDatabase để biết thông tin về SQLite trên Android.
  • Nếu dữ liệu của bạn được lưu trữ trực tuyến, thì hiệu suất tìm kiếm dự kiến có thể bị hạn chế bởi kết nối dữ liệu của người dùng. Bạn có thể muốn hiển thị chỉ báo tiến trình cho đến khi tìm kiếm trở lại. Hãy xem android.net để tham khảo các API mạng và ProgressBar để biết thông tin về cách hiển thị chỉ báo tiến trình.

Trình bày kết quả

Bất kể dữ liệu của bạn nằm ở đâu và như thế nào, bạn nên trả về kết quả tìm kiếm cho hoạt động có thể tìm kiếm bằng Adapter. Bằng cách này, bạn có thể hiển thị tất cả kết quả tìm kiếm trong một RecyclerView. Nếu dữ liệu đến từ truy vấn cơ sở dữ liệu SQLite, bạn có thể áp dụng kết quả cho RecyclerView bằng cách sử dụng CursorAdapter. Nếu dữ liệu của bạn có định dạng khác, thì bạn có thể tạo phần mở rộng của BaseAdapter.

Adapter liên kết từng mục từ một tập dữ liệu vào đối tượng View. Khi Adapter được áp dụng cho một RecyclerView, mỗi phần dữ liệu sẽ được chèn dưới dạng một thành phần hiển thị riêng lẻ vào danh sách. Adapter chỉ là một giao diện, vì vậy, bạn cần triển khai các phương thức triển khai như CursorAdapter (để liên kết dữ liệu từ Cursor). Nếu không có phương pháp triển khai hiện tại nào phù hợp với dữ liệu của bạn, thì bạn có thể triển khai phương thức triển khai của riêng mình từ BaseAdapter.

Sử dụng hộp thoại tìm kiếm

Hộp thoại tìm kiếm cung cấp một hộp tìm kiếm nổi ở đầu màn hình, với biểu tượng ứng dụng ở bên trái. Hộp thoại tìm kiếm có thể cung cấp đề xuất tìm kiếm khi người dùng nhập. Khi người dùng thực hiện tìm kiếm, hệ thống sẽ gửi cụm từ tìm kiếm đó đến một hoạt động có thể tìm kiếm thực hiện việc tìm kiếm.

Theo mặc định, hộp thoại tìm kiếm luôn bị ẩn cho đến khi người dùng kích hoạt. Ứng dụng có thể kích hoạt hộp thoại tìm kiếm bằng cách gọi onSearchRequested(). Tuy nhiên, phương thức này sẽ không hoạt động cho đến khi bạn bật hộp thoại tìm kiếm cho hoạt động đó.

Để hộp thoại tìm kiếm thực hiện việc tìm kiếm, hãy cho hệ thống biết hoạt động có thể tìm kiếm nào phải nhận truy vấn tìm kiếm từ hộp thoại tìm kiếm. Ví dụ: trong phần trước về cách tạo hoạt động có thể tìm kiếm, một hoạt động có thể tìm kiếm tên là SearchableActivity sẽ được tạo. Nếu bạn muốn có một hoạt động riêng biệt, chẳng hạn như hoạt động có tên OtherActivity, để hiện hộp thoại tìm kiếm và gửi nội dung tìm kiếm đến SearchableActivity, hãy khai báo trong tệp kê khai rằng SearchableActivity là hoạt động có thể tìm kiếm sẽ được sử dụng cho hộp thoại tìm kiếm trong OtherActivity.

Để khai báo hoạt động có thể tìm kiếm cho hộp thoại tìm kiếm của một hoạt động, hãy thêm phần tử <meta-data> vào bên trong phần tử <activity> của hoạt động tương ứng. Phần tử <meta-data> phải bao gồm thuộc tính android:value chỉ định tên lớp của hoạt động có thể tìm kiếm và thuộc tính android:name có giá trị "android.app.default_searchable".

Ví dụ: dưới đây là phần khai báo cho cả hoạt động có thể tìm kiếm (SearchableActivity) và một hoạt động khác (OtherActivity). Hoạt động này sử dụng SearchableActivity để thực hiện các lượt tìm kiếm được thực thi qua hộp thoại tìm kiếm:

<application ... >
    <!-- This is the searchable activity; it performs searches. -->
    <activity android:name=".SearchableActivity" >
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
        <meta-data android:name="android.app.searchable"
                   android:resource="@xml/searchable"/>
    </activity>

    <!-- This activity enables the search dialog to initiate searches
         in the SearchableActivity. -->
    <activity android:name=".OtherActivity" ... >
        <!-- Enable the search dialog to send searches to SearchableActivity. -->
        <meta-data android:name="android.app.default_searchable"
                   android:value=".SearchableActivity" />
    </activity>
    ...
</application>

OtherActivity hiện bao gồm một phần tử <meta-data> để khai báo hoạt động có thể tìm kiếm nào sẽ sử dụng cho nội dung tìm kiếm, nên hoạt động đó sẽ bật hộp thoại tìm kiếm. Mặc dù người dùng đang ở trong hoạt động này, nhưng phương thức onSearchRequested() sẽ kích hoạt hộp thoại tìm kiếm. Khi người dùng thực thi tìm kiếm, hệ thống sẽ khởi động SearchableActivity và gửi ý định ACTION_SEARCH cho đối tượng đó.

Nếu bạn muốn mọi hoạt động trong ứng dụng của mình cung cấp hộp thoại tìm kiếm, hãy chèn phần tử <meta-data> trước đó làm phần tử con của phần tử <application>, thay vì từng <activity>. Bằng cách này, mọi hoạt động đều kế thừa giá trị, cung cấp hộp thoại tìm kiếm và phân phối nội dung tìm kiếm đến cùng một hoạt động có thể tìm kiếm. Nếu có nhiều hoạt động có thể tìm kiếm, bạn có thể ghi đè hoạt động có thể tìm kiếm mặc định bằng cách đặt một nội dung khai báo <meta-data> khác bên trong từng hoạt động.

Khi hộp thoại tìm kiếm hiện đã được bật cho các hoạt động, ứng dụng của bạn đã sẵn sàng thực hiện tìm kiếm.

Gọi hộp thoại tìm kiếm

Mặc dù một số thiết bị cung cấp nút tìm kiếm chuyên dụng, nhưng hành vi của nút đó có thể khác nhau giữa các thiết bị và nhiều thiết bị không cung cấp nút tìm kiếm. Vì vậy, khi sử dụng hộp thoại tìm kiếm, bạn phải cung cấp một nút tìm kiếm trong giao diện người dùng để kích hoạt hộp thoại tìm kiếm bằng cách gọi onSearchRequested().

Ví dụ: thêm nút tìm kiếm trong trình đơn tuỳ chọn hoặc bố cục giao diện người dùng gọi onSearchRequested().

Bạn cũng có thể bật chức năng "nhập để tìm kiếm". Chức năng này sẽ kích hoạt hộp thoại tìm kiếm khi người dùng bắt đầu nhập trên bàn phím. Các tổ hợp phím được chèn vào hộp thoại tìm kiếm. Bạn có thể bật tính năng loại để tìm kiếm trong hoạt động của mình bằng cách gọi setDefaultKeyMode (hoặc DEFAULT_KEYS_SEARCH_LOCAL) trong phương thức onCreate() của hoạt động.

Tác động của hộp thoại tìm kiếm đối với vòng đời hoạt động

Hộp thoại tìm kiếm là một Dialog nổi ở đầu màn hình. Điều này không gây ra bất kỳ thay đổi nào trong ngăn xếp hoạt động. Vì vậy, khi hộp thoại tìm kiếm xuất hiện, sẽ không có phương thức vòng đời nào (chẳng hạn như onPause()) được gọi. Hoạt động của bạn sẽ mất tiêu điểm nhập, vì tiêu điểm nhập được cấp cho hộp thoại tìm kiếm.

Nếu bạn muốn nhận thông báo khi hộp thoại tìm kiếm được kích hoạt, hãy ghi đè phương thức onSearchRequested(). Khi hệ thống gọi phương thức này, đây là chỉ báo cho biết hoạt động của bạn sẽ mất tiêu điểm nhập vào hộp thoại tìm kiếm, nhờ đó, bạn có thể thực hiện mọi thao tác phù hợp với sự kiện, chẳng hạn như tạm dừng trò chơi. Trừ phi bạn truyền dữ liệu ngữ cảnh tìm kiếm (được thảo luận trong phần khác của tài liệu này), hãy kết thúc phương thức bằng cách gọi phương thức triển khai lớp cấp cao:

Kotlin

override fun onSearchRequested(): Boolean {
    pauseSomeStuff()
    return super.onSearchRequested()
}

Java

@Override
public boolean onSearchRequested() {
    pauseSomeStuff();
    return super.onSearchRequested();
}

Nếu người dùng huỷ thao tác tìm kiếm bằng cách nhấn vào nút Quay lại, hộp thoại tìm kiếm sẽ đóng và hoạt động lấy lại tâm điểm nhập. Bạn có thể đăng ký để nhận thông báo khi hộp thoại tìm kiếm đóng bằng setOnDismissListener(), setOnCancelListener() hoặc cả hai. Bạn chỉ cần đăng ký OnDismissListener vì hệ thống sẽ gọi mỗi khi hộp thoại tìm kiếm đóng. OnCancelListener chỉ liên quan đến các sự kiện mà người dùng thoát khỏi hộp thoại tìm kiếm một cách rõ ràng, vì vậy, sự kiện này không được gọi khi thực thi tìm kiếm. Khi thực thi nội dung tìm kiếm, hộp thoại tìm kiếm sẽ tự động biến mất.

Nếu hoạt động hiện tại không phải là hoạt động có thể tìm kiếm, thì các sự kiện trong vòng đời hoạt động thông thường sẽ được kích hoạt khi người dùng thực hiện một hoạt động tìm kiếm. Hoạt động hiện tại sẽ nhận được onPause(), như mô tả trong phần Giới thiệu về hoạt động. Tuy nhiên, nếu hoạt động hiện tại là hoạt động có thể tìm kiếm, thì một trong hai điều sẽ xảy ra:

  • Theo mặc định, hoạt động có thể tìm kiếm sẽ nhận được ý định ACTION_SEARCH bằng lệnh gọi đến onCreate() và một thực thể mới của hoạt động đó sẽ được đưa lên đầu ngăn xếp hoạt động. Hiện tại, có 2 thực thể của hoạt động có thể tìm kiếm trong ngăn xếp hoạt động. Vì vậy, việc nhấn vào nút Quay lại sẽ đưa bạn quay lại thực thể trước đó của hoạt động có thể tìm kiếm đó, thay vì thoát khỏi hoạt động có thể tìm kiếm.
  • Nếu bạn thiết lập android:launchMode thành "singleTop", thì hoạt động có thể tìm kiếm sẽ nhận được ý định ACTION_SEARCH với lệnh gọi đến onNewIntent(Intent), truyền ý định ACTION_SEARCH mới. Ví dụ: dưới đây là cách bạn có thể xử lý trường hợp này, trong đó chế độ chạy của hoạt động có thể tìm kiếm là "singleTop":

    Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.search)
        handleIntent(intent)
    }
    
    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        setIntent(intent)
        handleIntent(intent)
    }
    
    private fun handleIntent(intent: Intent) {
        if (Intent.ACTION_SEARCH == intent.action) {
            intent.getStringExtra(SearchManager.QUERY)?.also { query ->
                doMySearch(query)
            }
        }
    }
    

    Java

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.search);
        handleIntent(getIntent());
    }
    
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        handleIntent(intent);
    }
    
    private void handleIntent(Intent intent) {
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
          String query = intent.getStringExtra(SearchManager.QUERY);
          doMySearch(query);
        }
    }
    

    So với mã ví dụ trong phần về thực hiện tìm kiếm, tất cả mã để xử lý ý định tìm kiếm hiện đều nằm trong phương thức handleIntent(), để cả onCreate()onNewIntent() đều có thể thực thi nó.

    Khi hệ thống gọi onNewIntent(Intent), hoạt động không được bắt đầu lại, vì vậy, phương thức getIntent() sẽ trả về cùng một ý định nhận được bằng onCreate(). Đây là lý do tại sao bạn phải gọi setIntent(Intent) bên trong onNewIntent(Intent) để cập nhật ý định do hoạt động lưu trong trường hợp bạn gọi getIntent() trong tương lai.

Thông thường, bạn nên sử dụng chế độ chạy "singleTop" vì sau khi tìm kiếm xong, người dùng có thể thực hiện các lần tìm kiếm bổ sung và bạn không muốn ứng dụng của mình tạo nhiều thực thể của hoạt động có thể tìm kiếm. Bạn nên đặt hoạt động có thể tìm kiếm thành chế độ chạy "singleTop" trong tệp kê khai ứng dụng, như minh hoạ trong ví dụ sau:

<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>

Truyền dữ liệu ngữ cảnh tìm kiếm

Trong một số trường hợp, bạn có thể thực hiện các tinh chỉnh cần thiết đối với cụm từ tìm kiếm bên trong hoạt động có thể tìm kiếm cho mỗi lượt tìm kiếm được thực hiện. Tuy nhiên, nếu muốn tinh chỉnh tiêu chí tìm kiếm dựa trên hoạt động mà từ đó người dùng thực hiện việc tìm kiếm, bạn có thể cung cấp dữ liệu bổ sung trong ý định mà hệ thống gửi đến hoạt động tìm kiếm của bạn. Bạn có thể truyền dữ liệu bổ sung trong APP_DATA Bundle, có trong ý định ACTION_SEARCH.

Để chuyển loại dữ liệu này đến hoạt động tìm kiếm, hãy ghi đè phương thức onSearchRequested() cho hoạt động mà từ đó người dùng có thể thực hiện tìm kiếm, tạo Bundle với dữ liệu bổ sung và gọi startSearch() để kích hoạt hộp thoại tìm kiếm. Ví dụ:

Kotlin

override fun onSearchRequested(): Boolean {
    val appData = Bundle().apply {
        putBoolean(JARGON, true)
    }
    startSearch(null, false, appData, false)
    return true
}

Java

@Override
public boolean onSearchRequested() {
     Bundle appData = new Bundle();
     appData.putBoolean(SearchableActivity.JARGON, true);
     startSearch(null, false, appData, false);
     return true;
 }

Việc trả về giá trị true cho biết rằng bạn đã xử lý thành công sự kiện gọi lại này và gọi startSearch() để kích hoạt hộp thoại tìm kiếm. Sau khi người dùng gửi một truy vấn, truy vấn đó sẽ được gửi đến hoạt động có thể tìm kiếm của bạn cùng với dữ liệu mà bạn thêm. Bạn có thể trích xuất dữ liệu bổ sung từ APP_DATA Bundle để tinh chỉnh nội dung tìm kiếm, như trong ví dụ sau:

Kotlin

val jargon: Boolean = intent.getBundleExtra(SearchManager.APP_DATA)?.getBoolean(JARGON) ?: false

Java

Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);
if (appData != null) {
    boolean jargon = appData.getBoolean(SearchableActivity.JARGON);
}

Sử dụng tiện ích tìm kiếm

Hình ảnh cho thấy chế độ xem tìm kiếm trong thanh trên cùng của ứng dụng

Hình 1. Tiện ích SearchView dưới dạng một khung hiển thị hành động trong thanh ứng dụng.

Tiện ích tìm kiếm cung cấp chức năng giống như hộp thoại tìm kiếm. API này bắt đầu hoạt động thích hợp khi người dùng thực hiện tìm kiếm, đồng thời có thể cung cấp các cụm từ tìm kiếm được đề xuất và thực hiện tìm kiếm bằng giọng nói. Nếu không thể đặt tiện ích tìm kiếm vào thanh ứng dụng, bạn có thể đặt tiện ích tìm kiếm ở đâu đó trong bố cục hoạt động của mình.

Định cấu hình tiện ích tìm kiếm

Sau khi bạn tạo một cấu hình tìm kiếmhoạt động có thể tìm kiếm, hãy bật tính năng tìm kiếm được hỗ trợ cho mỗi SearchView bằng cách gọi setSearchableInfo() và truyền vào đó đối tượng SearchableInfo đại diện cho cấu hình có thể tìm kiếm của bạn.

Bạn có thể tham chiếu đến SearchableInfo bằng cách gọi getSearchableInfo() trên SearchManager.

Ví dụ: nếu bạn đang sử dụng SearchView làm khung hiển thị hành động trong thanh ứng dụng, hãy bật tiện ích này trong khi gọi lại onCreateOptionsMenu(), như minh hoạ trong ví dụ sau:

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    // Inflate the options menu from XML.
    val inflater = menuInflater
    inflater.inflate(R.menu.options_menu, menu)

    // Get the SearchView and set the searchable configuration.
    val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
    (menu.findItem(R.id.menu_search).actionView as SearchView).apply {
        // Assumes current activity is the searchable activity.
        setSearchableInfo(searchManager.getSearchableInfo(componentName))
        setIconifiedByDefault(false) // Don't iconify the widget. Expand it by default.
    }

    return true
}

Java

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the options menu from XML.
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.options_menu, 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();
    // Assumes current activity is the searchable activity.
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
    searchView.setIconifiedByDefault(false); // Don't iconify the widget. Expand it by default.

    return true;
}

Tiện ích tìm kiếm hiện được định cấu hình và hệ thống phân phối truy vấn tìm kiếm đến hoạt động có thể tìm kiếm của bạn. Bạn cũng có thể bật đề xuất tìm kiếm cho tiện ích tìm kiếm.

Để biết thêm thông tin về khung hiển thị thao tác trong thanh ứng dụng, hãy xem phần Sử dụng khung hiển thị thao tác và trình cung cấp thao tác.

Các tính năng khác của tiện ích Tìm kiếm

Tiện ích SearchView cung cấp thêm một số tính năng mà bạn có thể cần:

Nút gửi
Theo mặc định, không có nút nào để gửi cụm từ tìm kiếm, vì vậy người dùng phải nhấn phím Return trên bàn phím để bắt đầu tìm kiếm. Bạn có thể thêm nút "gửi" bằng cách gọi setSubmitButtonEnabled(true).
Tinh chỉnh cụm từ tìm kiếm cho cụm từ tìm kiếm được đề xuất
Khi bật cụm từ tìm kiếm được đề xuất, người dùng thường sẽ chọn một cụm từ đề xuất, nhưng cũng có thể họ sẽ muốn tinh chỉnh cụm từ tìm kiếm đề xuất. Bạn có thể thêm một nút bên cạnh mỗi đề xuất để chèn đề xuất đó vào hộp tìm kiếm để người dùng tinh chỉnh lại bằng cách gọi setQueryRefinementEnabled(true).
Khả năng bật/tắt chế độ hiển thị hộp tìm kiếm
Theo mặc định, tiện ích tìm kiếm được "biểu tượng hoá", nghĩa là tiện ích này chỉ được biểu thị bằng một biểu tượng tìm kiếm (kính lúp). Nút này sẽ mở rộng để hiển thị hộp tìm kiếm khi người dùng nhấn vào biểu tượng đó. Như minh hoạ trong ví dụ trước, bạn có thể hiển thị hộp tìm kiếm theo mặc định bằng cách gọi setIconifiedByDefault(false). Bạn cũng có thể bật/tắt giao diện của tiện ích tìm kiếm bằng cách gọi setIconified().

Có một số API khác trong lớp SearchView cho phép bạn tuỳ chỉnh tiện ích tìm kiếm. Tuy nhiên, hầu hết các thuộc tính này chỉ được dùng khi bạn tự xử lý mọi hoạt động đầu vào của người dùng, thay vì sử dụng hệ thống Android để phân phối các cụm từ tìm kiếm và hiển thị nội dung đề xuất tìm kiếm.

Sử dụng cả tiện ích và hộp thoại

Nếu bạn chèn tiện ích tìm kiếm vào thanh ứng dụng dưới dạng khung hiển thị thao tác và cho phép tiện ích này xuất hiện trên thanh ứng dụng nếu vẫn còn chỗ (bằng cách đặt android:showAsAction="ifRoom"), thì tiện ích tìm kiếm có thể không xuất hiện dưới dạng khung hiển thị hành động. Thay vào đó, một mục trong trình đơn có thể xuất hiện trong trình đơn mục bổ sung. Ví dụ: khi ứng dụng chạy trên màn hình nhỏ hơn, thanh ứng dụng có thể không có đủ chỗ để hiển thị tiện ích tìm kiếm cùng với các mục hành động hoặc phần tử điều hướng khác, vì vậy, mục trong trình đơn sẽ xuất hiện trong trình đơn mục bổ sung. Khi được đặt trong trình đơn mục bổ sung, mục này sẽ hoạt động như một mục trong trình đơn thông thường và không hiển thị khung hiển thị hành động, tức là tiện ích tìm kiếm.

Để xử lý trường hợp này, mục trong trình đơn mà bạn đính kèm tiện ích tìm kiếm phải kích hoạt hộp thoại tìm kiếm khi người dùng chọn mục đó từ trình đơn mục bổ sung. Để làm việc này, hãy triển khai onOptionsItemSelected() để xử lý mục trong trình đơn "Tìm kiếm" và mở hộp thoại tìm kiếm bằng cách gọi onSearchRequested().

Để biết thêm thông tin về cách hoạt động của các mục trong thanh ứng dụng và cách xử lý trường hợp này, hãy xem phần Thêm thanh ứng dụng.

Thêm tìm kiếm bằng giọng nói

Bạn có thể thêm chức năng tìm kiếm bằng giọng nói vào hộp thoại hoặc tiện ích tìm kiếm bằng cách thêm thuộc tính android:voiceSearchMode vào cấu hình có thể tìm kiếm. Thao tác này sẽ thêm nút tìm kiếm bằng giọng nói để khởi chạy lời nhắc bằng giọng nói. Khi người dùng nói xong, cụm từ tìm kiếm được chép lời sẽ được gửi đến hoạt động có thể tìm kiếm của bạn.

Lệnh này được minh hoạ trong ví dụ sau:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/search_label"
    android:hint="@string/search_hint"
    android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" >
</searchable>

Bạn cần có giá trị showVoiceSearchButton để bật tính năng tìm kiếm bằng giọng nói. Giá trị thứ hai, launchRecognizer, chỉ định rằng nút tìm kiếm bằng giọng nói phải khởi chạy một trình nhận dạng để trả về văn bản đã chép lời cho hoạt động có thể tìm kiếm.

Bạn có thể cung cấp các thuộc tính bổ sung để chỉ định hành vi tìm kiếm bằng giọng nói, chẳng hạn như ngôn ngữ dự kiến và số lượng kết quả tối đa cần trả về. Hãy xem tài liệu tham khảo về Cấu hình tìm kiếm để biết thêm thông tin về các thuộc tính hiện có.

Thêm cụm từ tìm kiếm được đề xuất

Cả hộp thoại tìm kiếm và tiện ích tìm kiếm đều có thể cung cấp các đề xuất tìm kiếm khi người dùng nhập, với sự hỗ trợ của hệ thống Android. Hệ thống sẽ quản lý danh sách các đề xuất và xử lý sự kiện khi người dùng chọn một đề xuất.

Bạn có thể cung cấp hai loại đề xuất tìm kiếm:

Cụm từ tìm kiếm được đề xuất gần đây
Những đề xuất này là những từ mà trước đây người dùng đã sử dụng làm cụm từ tìm kiếm trong ứng dụng của bạn. Xem phần Thêm cụm từ tìm kiếm tuỳ chỉnh được đề xuất để biết thêm thông tin.
Cụm từ tìm kiếm được đề xuất tuỳ chỉnh
Đây là những cụm từ tìm kiếm được đề xuất mà bạn cung cấp từ nguồn dữ liệu của riêng mình để giúp người dùng chọn ngay lập tức đúng chính tả hoặc mục họ đang tìm kiếm. Xem bài viết Thêm cụm từ tìm kiếm được đề xuất tuỳ chỉnh để biết thêm thông tin.