Giới thiệu
Bài viết này hướng dẫn sử dụng SearchView để lọc dữ liệu trong ListView theo thời gian thực. SearchView cung cấp UI tìm kiếm chuẩn Material Design với gợi ý, voice search, và callback lọc dữ liệu.
Các bước thực hiện
Bước 1: Tạo dự án mới
Mở Android Studio, chọn File → New Project và tạo dự án.
Bước 2: Thiết kế giao diện (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<SearchView
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:iconifiedByDefault="false"
android:queryHint="Tìm kiếm tại đây..." />
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/searchView"
android:divider="#aadd55"
android:dividerHeight="2dp" />
</RelativeLayout>
Bước 3: Viết code logic (src/MainActivity.java)
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
SearchView searchView;
ListView listView;
ArrayList<String> fruitList;
ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
searchView = findViewById(R.id.searchView);
listView = findViewById(R.id.listView);
// Dữ liệu mẫu
fruitList = new ArrayList<>();
fruitList.add("Táo");
fruitList.add("Chuối");
fruitList.add("Thơm");
fruitList.add("Cam");
fruitList.add("Xoài");
fruitList.add("Nho");
fruitList.add("Chanh");
fruitList.add("Dưa hấu");
fruitList.add("Dưa lưới");
fruitList.add("Đu đủ");
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, fruitList);
listView.setAdapter(adapter);
// Cấu hình SearchView
searchView.setIconifiedByDefault(false); // Mở rộng mặc định
searchView.setQueryHint("Tìm trái cây...");
searchView.setSubmitButtonEnabled(true);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
// Khi nhấn Enter/Search trên bàn phím
if (fruitList.contains(query)) {
adapter.getFilter().filter(query);
} else {
Toast.makeText(MainActivity.this, "Không tìm thấy: " + query, Toast.LENGTH_LONG).show();
}
return false; // false = không consume, cho SearchView xử lý tiếp
}
@Override
public boolean onQueryTextChange(String newText) {
// Lọc realtime khi gõ từng ký tự
adapter.getFilter().filter(newText);
return false;
}
});
// Xử lý click item
listView.setOnItemClickListener((parent, view, position, id) -> {
String selected = adapter.getItem(position);
Toast.makeText(this, "Đã chọn: " + selected, Toast.LENGTH_SHORT).show();
});
}
}
Bước 4: Cấu hình AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.com.sample">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Chạy ứng dụng
Kết nối thiết bị, nhấn Run. SearchView hiển thị ở trên, ListView 10 trái cây ở dưới. Gõ "Cam" -> ListView lọc chỉ còn "Cam". Xóa text -> hiển thị lại tất cả.
Tùy chỉnh SearchView nâng cao
1. SearchView trong Toolbar/ActionBar (Menu)
<!-- res/menu/menu_search.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="android.support.v7.widget.SearchView" />
</menu>
// Activity
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_search, menu);
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
// Cấu hình searchView...
return true;
}
2. Search Suggestions (Gợi ý tìm kiếm)
// Cung cấp suggestions qua ContentProvider hoặc CursorAdapter
searchView.setSuggestionsAdapter(new SimpleCursorAdapter(...));
searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
@Override public boolean onSuggestionSelect(int position) { return false; }
@Override public boolean onSuggestionClick(int position) { return false; }
});
3. Voice Search (Tìm kiếm bằng giọng nói)
searchView.setVoiceSearch(true); // Mặc định bật nếu có mic // Hoặc custom voice intent searchView.setVoiceButtonEnabled(true);
RecyclerView + SearchView (Hiện đại hơn)
Với RecyclerView, dùng Filterable interface trên Adapter:
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> implements Filterable {
private List<String> fullList, filteredList;
private Filter filter = new Filter() {
@Override protected FilterResults performFiltering(CharSequence constraint) { ... }
@Override protected void publishResults(CharSequence constraint, FilterResults results) { ... }
};
@Override public Filter getFilter() { return filter; }
}
Lưu ý
- ArrayAdapter có sẵn Filter cho List<String> – gọi
adapter.getFilter().filter(query) iconifiedByDefault="false"hiển thị SearchView mở rộng ngay từ đầu- Trả về
falsetrong listener để SearchView xử lý mặc định (xóa text, ẩn keyboard...) - Để tìm kiếm không phân biệt hoa thường: override Filter.performFiltering() dùng
toLowerCase()