Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

SearchView trong Android - Tìm kiếm trong ListView

SearchView là widget cho phép người dùng nhập từ khóa để lọc dữ liệu trong danh sách. Thường dùng kết hợp với ListView/RecyclerView và Adapter có hỗ trợ filtering.

Các bước triển khai

Bước 1: Tạo project mới

Bước 2: Layout activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="16dp">

        <androidx.appcompat.widget.SearchView
            android:id="@+id/searchView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:queryHint="Tìm kiếm..." 
            android:iconifiedByDefault="false" />

        <ListView
            android:id="@+id/listView"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:layout_marginTop="8dp" />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Bước 3: MainActivity.java

import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private ListView listView;
    private SearchView searchView;
    private ArrayAdapter adapter;
    private List dataList;

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

        listView = findViewById(R.id.listView);
        searchView = findViewById(R.id.searchView);

        // Dữ liệu mẫu
        dataList = new ArrayList<>(Arrays.asList(
            "Java", "Android", "C Language", "C++ Language", 
            "Go Language", "Kotlin", "Python", "JavaScript",
            "Dart", "Flutter", "React Native", "Swift"
        ));

        // Adapter hỗ trợ filter
        adapter = new ArrayAdapter<>(this, 
            android.R.layout.simple_list_item_1, dataList);
        listView.setAdapter(adapter);

        // Cấu hình SearchView
        searchView.setIconifiedByDefault(false); // Mở rộng mặc định
        searchView.setQueryHint("Nhập từ khóa...");
        searchView.clearFocus(); // Tránh focus tự động

        // Listener tìm kiếm
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                // Khi nhấn Enter/search trên bàn phím
                searchView.clearFocus();
                return true;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                // Lọc real-time khi gõ
                adapter.getFilter().filter(newText);
                return true;
            }
        });

        // Click item
        listView.setOnItemClickListener((parent, view, position, id) -> {
            String item = adapter.getItem(position);
            Toast.makeText(this, "Đã chọn: " + item, Toast.LENGTH_SHORT).show();
        });
    }
}

Giải thích OnQueryTextListener

  • onQueryTextSubmit(query): Gọi khi user nhấn nút search/Enter. Trả về true nếu đã xử lý.
  • onQueryTextChange(newText): Gọi real-time khi text thay đổi. Dùng adapter.getFilter().filter() để lọc.

Yêu cầu Adapter phải implement Filterable

ArrayAdapter mặc định đã implement Filterable. Nếu dùng custom adapter, phải override getFilter():

public class CustomAdapter extends BaseAdapter implements Filterable {
    // ...
    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                // Logic lọc dữ liệu ở background thread
            }
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                // Cập nhật dữ liệu và notifyDataSetChanged()
            }
        };
    }
}

Chạy ứng dụng

Gõ từ khóa vào SearchView → ListView lọc real-time chỉ hiển thị item chứa từ khóa. Nhấn item → Toast hiển thị tên item.

Mở rộng: SearchView trong Toolbar/ActionBar

// menu/search_menu.xml
<menu xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_search"
        android:title="Tìm kiếm"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="collapseActionView|ifRoom"
        app:actionViewClass="androidx.appcompat.widget.SearchView" />
</menu>

// Activity
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.search_menu, menu);
    MenuItem searchItem = menu.findItem(R.id.action_search);
    SearchView searchView = (SearchView) searchItem.getActionView();
    // Cấu hình searchView...
    return true;
}