使用SearchView过滤RecyclerView / ListAdapter

问题描述 投票:1回答:1

我正在尝试为我的RecyclerView实现过滤器。我使用数据绑定,并且我的适配器是ListAdapter子类,如下所示

class BookAdapter(private val clickListener: ClickHandler) :
    ListAdapter<Book, BookAdapter.ViewHolder>(BooksDiffCallback()) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder.from(parent)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(getItem(position)!!, clickListener)
    }

    class ViewHolder private constructor(val binding: BookItemBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(
            item: Book,
            clickListener: ClickHandler
        ) {
            binding.book = item
            binding.clickListener = clickListener
            binding.executePendingBindings()
        }

        companion object {
            fun from(parent: ViewGroup): ViewHolder {
                val inflater = LayoutInflater.from(parent.context)
                val binding = BookItemBinding.inflate(inflater, parent, false)
                return ViewHolder(binding)
            }
        }
    }
}

class BooksDiffCallback : DiffUtil.ItemCallback<Book>() {
    override fun areItemsTheSame(oldItem: Book, newItem: Book): Boolean {
        return oldItem.id == newItem.id
    }

    override fun areContentsTheSame(oldItem: Book, newItem: Book): Boolean {
        return oldItem == newItem
    }

}

class ClickHandler(val clickListener: (id: String) -> Unit) {
    fun onClick(item: Book) = clickListener(item.id)
}

根据文档,要添加过滤功能,我需要在适配器中实现Filterable并定义getFilter()方法。这就是我坚持的地方:在getFilter()的情况下,我根本不知道如何实现ListAdapter。任何帮助将不胜感激。

kotlin android-recyclerview filtering listadapter
1个回答
0
投票

我没有找到获取列表的方法,所以我保存了对列表的引用。代码示例:

ListAdapter:实施可过滤:

class ItemAdapter(private val clickListener: ItemListener) :
ListAdapter<ItemAdapter.BaseDataItem, RecyclerView.ViewHolder>(ItemDiffCallBack()), Filterable {

添加变量以供参考:

var mListRef: List<BaseDataItem>? = null
var mFilteredList: List<BaseDataItem>? = null

在您第一次提交列表之前,请先保存其引用

    withContext(Dispatchers.Main) {
        if (mListRef == null) {
                mListRef = items
            }
        submitList(items)
    }

过滤器:

override fun getFilter(): Filter {

    return object : Filter() {
        override fun performFiltering(charSequence: CharSequence): FilterResults {

            val charString = charSequence.toString()

            if (charString.isEmpty()) {

                mFilteredList = mListRef
            } else {
                mListRef?.let {
                    val filteredList = arrayListOf<BaseDataItem>()
                    for (baseDataItem in mListRef!!) {
                        if (baseDataItem is BaseDataItem.DataItemWrapper) {
                            if (charString.toLowerCase(Locale.ENGLISH) in baseDataItem.dataItem.Name.toLowerCase(
                                    Locale.ENGLISH
                                )
                            ) {
                                filteredList.add(baseDataItem)
                            }
                        }
                    }

                    mFilteredList = filteredList
                }
            }
            val filterResults = FilterResults()
            filterResults.values = mFilteredList
            return filterResults
        }

        override fun publishResults(
            charSequence: CharSequence,
            filterResults: FilterResults
        ) {
            mFilteredList = filterResults.values as ArrayList<BaseDataItem>
            submitList(mFilteredList)
        }
    }
}

如果您在片段中搜索,请添加以下内容:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setHasOptionsMenu(true)
}

override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
    inflater.inflate(R.menu.menu_main, menu)
    val mSearchMenuItem = menu.findItem(R.id.search)
    val searchView = mSearchMenuItem.actionView as SearchView
    search(searchView)
    super.onCreateOptionsMenu(menu, inflater)
}


private fun search(searchView: SearchView) {

    searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
        override fun onQueryTextSubmit(query: String): Boolean {

            return false
        }

        override fun onQueryTextChange(newText: String): Boolean {

            (binding.recycler.adapter as ItemAdapter).filter.filter(newText)
            return true
        }
    })
}
© www.soinside.com 2019 - 2024. All rights reserved.