CyStack logo
  • Sản phẩm & Dịch vụ
  • Giải pháp
  • Bảng giá
  • Công ty
  • Tài liệu
Vi

vi

Trang chủHướng dẫnHướng dẫn sử dụng SearchView trong Android với DataBinding

Hướng dẫn sử dụng SearchView trong Android với DataBinding

CyStack blog 4 phút để đọc
CyStack blog18/07/2025
Locker Avatar

Chris Pham

Technical Writer

Locker logo social
Reading Time: 4 minutes

Trong bài viết này, chúng ta sẽ tìm hiểu về SearchView trong Android và xây dựng một ứng dụng đơn giản để lọc dữ liệu trong ListView dựa trên văn bản người dùng nhập vào. Chúng ta sẽ sử dụng DataBinding để liên kết layout trong Activities và Adapters.

Searchview trong Android

Android SearchView

Android cho phép chúng ta tích hợp chức năng tìm kiếm vào ứng dụng bằng cách hiển thị SearchView widget. Widget này có thể được đặt trên ToolBar/ActionBar hoặc chèn trực tiếp vào một file layout. SearchView có sẵn từ phiên bản Android 3.0 (API 11) trở đi. Bạn có thể khai báo nó trong XML như sau:

<android.support.v7.widget.SearchView
        android:id="@+id/search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

Android hỗ trợ nhiều hình thức tìm kiếm khác nhau, chẳng hạn như tìm kiếm bằng giọng nói, hiển thị gợi ý, v.v. Trong hướng dẫn này, chúng ta sẽ tập trung vào việc sử dụng hai interface chính là SearchView.OnQueryTextListenerFilterable.

Interface Filterable được dùng để lọc danh sách dữ liệu (ví dụ như trong một ListView) dựa trên từ khóa tìm kiếm và chỉ hiển thị những kết quả phù hợp. Trong khi đó, interface OnQueryTextListener giúp chúng ta lắng nghe hai sự kiện chính từ người dùng:

  • onQueryTextChange(): Được gọi ngay lập tức mỗi khi người dùng thay đổi nội dung trong ô tìm kiếm (ví dụ: gõ hoặc xóa một ký tự).
  • onQueryTextSubmit(): Được kích hoạt khi người dùng hoàn tất việc tìm kiếm (ví dụ: nhấn phím Enter hoặc nút tìm kiếm trên bàn phím).

Ví dụ Android SearchView

Hình ảnh bên dưới minh họa kết quả cuối cùng của ứng dụng mẫu sử dụng SearchView trong Android.

Hướng dẫn Android SearchView sử dụng DataBinding

Ví dụ này gồm có một Activity và một Adapter dùng cho ListView.

Mã nguồn ví dụ Android SearchView

activity_main.xml được trình bày dưới đây. Layout này gồm một SearchView nằm phía trên và một ListView bên dưới:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="<https://schemas.android.com/apk/res/android>">

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <android.support.v7.widget.SearchView
            android:id="@+id/search"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:clickable="true" />

        <ListView
            android:id="@+id/list_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_below="@+id/search" />

    </RelativeLayout>

</layout>

MainActivity.java được trình bày như sau:

package com.journaldev.searchview;

import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.SearchView;

import com.journaldev.searchview.databinding.ActivityMainBinding;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    ActivityMainBinding activityMainBinding;
    ListAdapter adapter;

    List<String> arrayList= new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        arrayList.add("January");
        arrayList.add("February");
        arrayList.add("March");
        arrayList.add("April");
        arrayList.add("May");
        arrayList.add("June");
        arrayList.add("July");
        arrayList.add("August");
        arrayList.add("September");
        arrayList.add("October");
        arrayList.add("November");
        arrayList.add("December");

        adapter= new ListAdapter(arrayList);
        activityMainBinding.listView.setAdapter(adapter);

        activityMainBinding.search.setActivated(true);
        activityMainBinding.search.setQueryHint("Type your keyword here");
        activityMainBinding.search.onActionViewExpanded();
        activityMainBinding.search.setIconified(false);
        activityMainBinding.search.clearFocus();

        activityMainBinding.search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {

                adapter.getFilter().filter(newText);

                return false;
            }
        });
    }
}

Trong đoạn mã trên, một danh sách ArrayList chứa các tháng trong năm được truyền vào ListAdapter. Mỗi khi người dùng thay đổi nội dung trong SearchView, phương thức filter() của adapter sẽ được gọi để lọc dữ liệu.

package com.journaldev.searchview;

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import com.journaldev.searchview.databinding.RowItemBinding;
import java.util.ArrayList;
import java.util.List;

public class ListAdapter extends BaseAdapter implements Filterable {

    List<String> mData;
    List<String> mStringFilterList;
    ValueFilter valueFilter;
    private LayoutInflater inflater;

    public ListAdapter(List<String> cancel_type) {
        mData=cancel_type;
        mStringFilterList = cancel_type;
    }

    @Override
    public int getCount() {
        return mData.size();
    }

    @Override
    public String getItem(int position) {
        return mData.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, final ViewGroup parent) {

        if (inflater == null) {
            inflater = (LayoutInflater) parent.getContext()
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
        RowItemBinding rowItemBinding = DataBindingUtil.inflate(inflater, R.layout.row_item, parent, false);
        rowItemBinding.stringName.setText(mData.get(position));

        return rowItemBinding.getRoot();
    }

    @Override
    public Filter getFilter() {
        if (valueFilter == null) {
            valueFilter = new ValueFilter();
        }
        return valueFilter;
    }

    private class ValueFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();

            if (constraint != null && constraint.length() > 0) {
                List<String> filterList = new ArrayList<>();
                for (int i = 0; i < mStringFilterList.size(); i++) {
                    if ((mStringFilterList.get(i).toUpperCase()).contains(constraint.toString().toUpperCase())) {
                        filterList.add(mStringFilterList.get(i));
                    }
                }
                results.count = filterList.size();
                results.values = filterList;
            } else {
                results.count = mStringFilterList.size();
                results.values = mStringFilterList;
            }
            return results;

        }

        @Override
        protected void publishResults(CharSequence constraint,
                                      FilterResults results) {
            mData = (List<String>) results.values;
            notifyDataSetChanged();
        }

    }

}

Như bạn có thể thấy, việc lọc dữ liệu được thực hiện thông qua một lớp bên trong (inner class) có tên là ValueFilter, lớp này kế thừa từ Filter. ValueFilter thực hiện việc lọc bằng cách kiểm tra xem chuỗi người dùng nhập vào có khớp với bất kỳ chuỗi nào trong ArrayList hay không. Dưới đây là layout XML được sử dụng cho mỗi hàng (row) trong ListView, được định nghĩa trong file row_item.xml.

<layout xmlns:android="<https://schemas.android.com/apk/res/android>">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/stringName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_centerVertical="true"
            android:padding="@dimen/activity_horizontal_margin"
            android:textAllCaps="false"
            android:textAppearance="?android:attr/textAppearanceMedium" />

    </RelativeLayout>

</layout>

Giao diện kết quả khi chạy ứng dụng SearchView

SearchView chỉ hiển thị biểu tượng tìm kiếm, người dùng phải nhấn vào biểu tượng này mới có thể nhập nội dung tìm kiếm. Ngoài ra, nó cũng không hiển thị văn bản gợi ý (hint). Để cải thiện trải nghiệm người dùng, bạn có thể kích hoạt sẵn ô tìm kiếm và thêm hint bằng đoạn mã sau trong MainActivity:

activityMainBinding.search.setActivated(true);
        activityMainBinding.search.setQueryHint("Type your keyword here");
        activityMainBinding.search.onActionViewExpanded();
        activityMainBinding.search.setIconified(false);
        activityMainBinding.search.clearFocus();

SearchView sau khi được tùy chỉnh sẽ hiển thị như sau:

Như vậy, chúng ta vừa hoàn thành hướng dẫn sử dụng SearchView trong Android với ListView và DataBinding. Trong các bài tiếp theo, chúng ta sẽ tìm hiểu sâu hơn về những tính năng nâng cao của SearchView.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất