Thiết lập giao diện tìm kiếm

Thử cách dùng Compose
Jetpack Compose là bộ công cụ giao diện người dùng được đề xuất cho Android. Tìm hiểu cách thêm chức năng tìm kiếm trong Compose.

Bạn nên sử dụng tiện ích SearchView làm một mục trong thanh ứng dụng để cung cấp chức năng tìm kiếm trong ứng dụng. Giống như tất cả các mục trong thanh ứng dụng, bạn có thể xác định SearchView để hiển thị mọi lúc hoặc chỉ khi có chỗ. Bạn cũng có thể xác định thao tác này là một thao tác có thể thu gọn, ban đầu hiển thị SearchView dưới dạng biểu tượng, sau đó chiếm toàn bộ thanh ứng dụng dưới dạng trường tìm kiếm khi người dùng nhấn vào biểu tượng.

Thêm SearchView vào thanh ứng dụng

Để thêm tiện ích SearchView vào thanh ứng dụng, hãy tạo một tệp trong dự án có tên là res/menu/options_menu.xml và thêm mã sau vào tệp. Mã này xác định cách tạo mục tìm kiếm, chẳng hạn như biểu tượng cần sử dụng và tiêu đề của mục. Thuộc tính collapseActionView cho phép SearchView mở rộng để chiếm toàn bộ thanh ứng dụng và thu gọn trở lại thành một mục thanh ứng dụng thông thường khi không sử dụng. Do không gian thanh ứng dụng trên thiết bị cầm tay bị hạn chế, bạn nên sử dụng thuộc tính collapsibleActionView để mang lại trải nghiệm tốt hơn cho người dùng.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/search"
        android:title="@string/search_title"
        android:icon="@drawable/ic_search"
        android:showAsAction="collapseActionView|ifRoom"
        android:actionViewClass="androidx.appcompat.widget.SearchView" />
</menu>

Nếu bạn muốn có biểu tượng tìm kiếm dễ tiếp cận hơn, hãy tạo một tệp ic_search.xml trong thư mục /res/drawable và đưa mã sau vào tệp đó:

<vector
    android:height="24dp"
    android:tint="#000000"
    android:viewportHeight="24"
    android:viewportWidth="24"
    android:width="24dp"
    xmlns:android="http://schemas.android.com/apk/res/android">
        <path android:fillColor="@android:color/white" android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
</vector>

Để hiển thị SearchView trong thanh ứng dụng, hãy tăng cường tài nguyên trình đơn XML res/menu/options_menu.xml trong phương thức onCreateOptionsMenu() của hoạt động:

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.options_menu, menu)

    return true
}

Khi chạy ứng dụng, bạn sẽ thấy kết quả như sau:

Hình ảnh hiển thị một màn hình trống có biểu tượng tìm kiếm trong thanh trên cùng của ứng dụng
Hình 1. Biểu tượng tìm kiếm trong thanh trên cùng của ứng dụng.

SearchView xuất hiện trong thanh ứng dụng của ứng dụng, nhưng không hoạt động. Nếu nhấn vào biểu tượng tìm kiếm, bạn sẽ thấy nội dung như sau:

Hình ảnh minh hoạ chế độ xem tìm kiếm
Hình 2. SearchView đang hoạt động.

Để SearchView hoạt động, bạn phải xác định cách hoạt động của SearchView.

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

Cấu hình tìm kiếm chỉ định cách hoạt động của SearchView và được xác định trong tệp res/xml/searchable.xml. Cấu hình tìm kiếm tối thiểu phải chứa một thuộc tính android:label có giá trị giống với thuộc tính android:label của phần tử <application> hoặc <activity> trong tệp kê khai Android. Tuy nhiên, bạn cũng nên thêm thuộc tính android:hint để cho người dùng biết nội dung cần nhập vào hộp tìm kiếm.

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

Trong tệp kê khai của ứng dụng, hãy khai báo phần tử <meta-data> trỏ đến tệp res/xml/searchable.xml. Khai báo phần tử trong <activity> mà bạn muốn hiển thị SearchView.

<activity
android:name=".SearchResultsActivity"
android:exported="false"
android:label="@string/title_activity_search_results"
android:launchMode="singleTop"
android:theme="@style/Theme.AppCompat.Light">
    <intent-filter>
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>
    <meta-data
        android:name="android.app.searchable"
        android:resource="@xml/searchable" />
</activity>

Trong phương thức onCreateOptionsMenu() mà bạn tạo, hãy liên kết cấu hình tìm kiếm với SearchView bằng cách gọi setSearchableInfo(SearchableInfo):

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.options_menu, menu)

    val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
    val searchView = menu.findItem(R.id.search).actionView as SearchView
    val component = ComponentName(this, SearchResultsActivity::class.java)
    val searchableInfo = searchManager.getSearchableInfo(component)
    searchView.setSearchableInfo(searchableInfo)
    return true
}

Lệnh gọi đến getSearchableInfo() sẽ lấy đối tượng SearchableInfo được tạo từ tệp XML cấu hình tìm kiếm. Khi cấu hình tìm kiếm được liên kết chính xác với SearchView và người dùng gửi một truy vấn, SearchView sẽ bắt đầu một hoạt động bằng ý định ACTION_SEARCH. Sau đó, bạn cần một hoạt động có thể lọc ý định này và xử lý truy vấn tìm kiếm.

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

Hoạt động có thể tìm kiếm sẽ lọc ý định ACTION_SEARCH và tìm kiếm cụm từ tìm kiếm trong một tập dữ liệu. Để tạo một hoạt động có thể tìm kiếm, hãy khai báo một hoạt động mà bạn chọn để lọc ý định ACTION_SEARCH:

<activity android:name=".SearchResultsActivity" ... >
    ...
    <intent-filter>
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>
    ...
</activity>

Trong hoạt động có thể tìm kiếm, hãy xử lý ý định ACTION_SEARCH bằng cách kiểm tra ý định đó trong phương thức onCreate().

Kotlin

class SearchResultsActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_search_results)
        handleIntent(intent)
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        handleIntent(intent)
    }

    private fun handleIntent(intent: Intent) {
        if (Intent.ACTION_SEARCH == intent.action) {
            val query = intent.getStringExtra(SearchManager.QUERY)
            Log.d("SEARCH", "Search query was: $query")
        }
    }
}

Giờ đây, SearchView có thể chấp nhận truy vấn của người dùng và bắt đầu hoạt động có thể tìm kiếm bằng ý định ACTION_SEARCH.

Sau khi lấy cụm từ tìm kiếm, bạn có thể chuyển cụm từ đó đến ViewModel. Tại đây, bạn có thể sử dụng cụm từ đó trong các lớp khác của cấu trúc để truy xuất kết quả tìm kiếm để hiển thị.