使用 SearchView 过滤 RecyclerView/ListAdapter

Ale*_*lex 13 filtering listadapter kotlin android-recyclerview

我正在尝试为我的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)
}
Run Code Online (Sandbox Code Playgroud)

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

小智 15

我遇到了类似的问题,并尝试使用类似于上面Maor Hadad描述的方法来解决它。它在某些时候起作用,并在

Filter.publishResult()

方法。所以,我是这样解决的。首先创建一个变量private var unfilteredlist = listOf<BaseDataItem>()和一个方法

fun modifyList(list : List<BaseDataItem>) {
    unfilteredList = list
    submitList(list)
}

fun filter(query: CharSequence?) {
    val list = mutableListOf<BaseDataItem>()

    // perform the data filtering
    if(!query.isNullOrEmpty()) {
        list.addAll(unfilteredList.filter {
            it.*field1*.toLowerCase(Locale.getDefault()).contains(query.toString().toLowerCase(Locale.getDefault())) ||
                    it.*field2*.toLowerCase(Locale.getDefault()).contains(query.toString().toLowerCase(Locale.getDefault())) })
    } else {
        list.addAll(unfilteredList)
    }

    submitList(list)
}
Run Code Online (Sandbox Code Playgroud)

BookAdapter课堂上。其中*field1**field2*(您可以添加更多字段)是您希望搜索查询匹配的字段。然后,无论您adapter.submitList(List<BaseDataItem>)在原始代码中调用 的何处,都将其替换为自定义方法adapter.modifyList(List<BaseDataItem>)。然后searchView.setOnQueryTextListener像下面这样写

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(newText)
        return true
    }
})
Run Code Online (Sandbox Code Playgroud)

不要忘记删除Filterable接口及其方法,您不再需要它们了


Mao*_*dad 5

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

ListAdapter:实现可过滤:

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

添加变量供参考:

var mListRef: List<BaseDataItem>? = null
var mFilteredList: List<BaseDataItem>? = null
Run Code Online (Sandbox Code Playgroud)

在第一次提交列表之前,请保存其参考文献

    withContext(Dispatchers.Main) {
        if (mListRef == null) {
                mListRef = items
            }
        submitList(items)
    }
Run Code Online (Sandbox Code Playgroud)

过滤器:

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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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
        }
    })
}
Run Code Online (Sandbox Code Playgroud)