如何在RecyclerViewAdapter中实现按名称搜索筛选功能
实现按猫咪名称筛选的具体方案
第一步:修改RecyclerViewAdapter,添加筛选逻辑
首先我们需要在Adapter中保存完整的原始数据集,同时实现Android原生的Filterable接口处理筛选逻辑,修改后的Adapter代码如下:
class RecyclerViewAdapter : RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder>(), Filterable { // 展示用的数据集(筛选后) private var items = ArrayList<CatBreed>() // 原始完整数据集,筛选时作为数据源 private val originalItems = ArrayList<CatBreed>() var onItemClick: ((CatBreed) -> Unit)? = null override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { val binding = CatBreedRowBinding.inflate(LayoutInflater.from(parent.context), parent, false) return MyViewHolder(binding) } override fun onBindViewHolder(holder: MyViewHolder, position: Int) { holder.bind(items[position]) holder.itemView.setOnClickListener { Log.d("adapter", "item clicked") onItemClick?.invoke(items[position]) } } override fun getItemCount(): Int { return items.size } fun setUpdatedData(items: ArrayList<CatBreed>) { // 同时更新展示数据集和原始数据集 this.items.clear() this.items.addAll(items) this.originalItems.clear() this.originalItems.addAll(items) notifyDataSetChanged() } // 重写Filterable接口的方法,返回自定义筛选器 override fun getFilter(): Filter { return object : Filter() { // 后台线程执行筛选逻辑 override fun performFiltering(constraint: CharSequence?): FilterResults { val filteredList = if (constraint.isNullOrEmpty()) { // 搜索关键词为空,返回全部原始数据 originalItems } else { val filterPattern = constraint.toString().lowercase().trim() // 筛选名称包含关键词的条目,忽略大小写 originalItems.filter { it.name.lowercase().contains(filterPattern) } as ArrayList<CatBreed> } val results = FilterResults() results.values = filteredList return results } // 主线程更新筛选后的展示数据 override fun publishResults(constraint: CharSequence?, results: FilterResults?) { items.clear() items.addAll(results?.values as ArrayList<CatBreed>) notifyDataSetChanged() } } } inner class MyViewHolder(private val binding: CatBreedRowBinding) : RecyclerView.ViewHolder(binding.root) { fun bind(data: CatBreed) { binding.tvName.text = data.name Picasso.get() .load(data.image.url) .into(binding.imageThumb) } } }
第二步:配置搜索菜单,关联Adapter筛选逻辑
首先确保你的res/menu/menu_item.xml中的搜索项配置了SearchView作为动作视图,示例配置如下:
<item android:id="@+id/action_search" android:title="搜索" android:icon="@drawable/ic_search" app:showAsAction="ifRoom|collapseActionView" app:actionViewClass="android.widget.SearchView" />
然后修改MainActivity的onCreateOptionsMenu方法,添加搜索框的文本变化监听,调用Adapter的筛选方法:
override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_item, menu) // 找到搜索菜单项 val searchItem = menu.findItem(R.id.action_search) val searchView = searchItem.actionView as SearchView // 设置搜索提示 searchView.queryHint = "输入猫咪名称搜索" // 监听搜索框文本变化 searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { // 提交搜索时触发 override fun onQueryTextSubmit(query: String?): Boolean { adapter.filter.filter(query) return true } // 搜索框文本变化时实时触发 override fun onQueryTextChange(newText: String?): Boolean { adapter.filter.filter(newText) return true } }) return true }
注意:上面代码中的
adapter要替换为你在MainActivity中实际声明的RecyclerViewAdapter实例变量名。
可选优化
如果需要更高的列表更新性能,可以把notifyDataSetChanged()替换为DiffUtil计算差异后局部刷新,避免整个列表重绘。
内容的提问来源于stack exchange,提问作者BRDroid
相关产品推荐
相关产品推荐

