SearchView 在滚动之前不更新 RecyclerView
SearchView not updating RecyclerView until scroll
我正在尝试过滤包含大约 3000 项的 recyclerList
。
我的过滤器有点管用,但出于某种原因,它不会更新列表,直到我滚动到足够远为止。
例如:前 2 个元素以字母 A 开头 --> 如果我的过滤器以 B 开头,前 2 个元素仍会显示,直到我滚动到足够远以至于它们不再可见为止。当我向上滚动时,它们从视图中消失了。
适配器
class LocationAdapter(
private var locations: ArrayList<Costcenter>,
private val onLocationClick: (location: Costcenter) -> Unit
) : RecyclerView.Adapter<LocationAdapter.LocationViewHolder>(), Filterable {
var locationsFiltered = locations
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LocationViewHolder {
val view = LayoutInflater
.from(parent.context)
.inflate(R.layout.location_row, parent, false)
return LocationViewHolder(view)
}
override fun getItemCount(): Int = locationsFiltered.size
override fun onBindViewHolder(holder: LocationViewHolder, position: Int) {
holder.bind(locationsFiltered[position])
}
inner class LocationViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val title: TextView = itemView.findViewById(R.id.txtCostCenter)
private val desc: TextView = itemView.findViewById(R.id.txtCostCenterDescription)
fun bind(loc: Costcenter) {
title.text = loc.goederenontvanger
desc.text = loc.goederenontvanger_omschrijving
itemView.setOnClickListener {
onLocationClick.invoke(loc)
}
}
}
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
val charSearch = constraint.toString()
locationsFiltered = if (charSearch.isEmpty()) {
locations
} else {
val resultList = ArrayList<Costcenter>()
for (row in locations) {
if (row.goederenontvanger.toLowerCase()
.contains(charSearch.toLowerCase()) || row.goederenontvanger_omschrijving.toLowerCase()
.contains(charSearch.toLowerCase())
) {
resultList.add(row)
}
}
resultList
}
val filterResults = FilterResults()
filterResults.values = locationsFiltered
return filterResults
}
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
}
}
}
}
创建回收视图的片段
class LocationsFragment : Fragment() {
private lateinit var locationAdapter: LocationAdapter
private val storageViewModel by activityViewModels<StorageViewModel>()
private lateinit var currentView : View
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
var view = inflater.inflate(R.layout.fragment_locations, container, false)
var recycler = view.findViewById<RecyclerView>(R.id.recyclerLocations)
var filter = view.findViewById<SearchView>(R.id.editFilter)
locationAdapter = LocationAdapter(Utilities.costcenters) { loc -> setSelectedLocation(loc) }
val recycleMngr: RecyclerView.LayoutManager =
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
filter.setOnQueryTextListener(object: SearchView.OnQueryTextListener{
override fun onQueryTextSubmit(query: String?): Boolean {
return false
}
override fun onQueryTextChange(newText: String?): Boolean {
locationAdapter.filter.filter(newText)
return false
}
})
recycler.layoutManager = recycleMngr
recycler.adapter = locationAdapter
currentView = view
return view
}
当使用 publishResults()
发布过滤器时,您需要使用过滤结果更新原始列表 locationsFiltered
,然后 notifyDataSetChanged()
将更改应用到 RecyclerView
所以在 publishResults()
方法中添加以下内容:
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
locationsFiltered = filterResults.values as ArrayList<Costcenter>
notifyDataSetChanged()
}
我正在尝试过滤包含大约 3000 项的 recyclerList
。
我的过滤器有点管用,但出于某种原因,它不会更新列表,直到我滚动到足够远为止。
例如:前 2 个元素以字母 A 开头 --> 如果我的过滤器以 B 开头,前 2 个元素仍会显示,直到我滚动到足够远以至于它们不再可见为止。当我向上滚动时,它们从视图中消失了。
适配器
class LocationAdapter(
private var locations: ArrayList<Costcenter>,
private val onLocationClick: (location: Costcenter) -> Unit
) : RecyclerView.Adapter<LocationAdapter.LocationViewHolder>(), Filterable {
var locationsFiltered = locations
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LocationViewHolder {
val view = LayoutInflater
.from(parent.context)
.inflate(R.layout.location_row, parent, false)
return LocationViewHolder(view)
}
override fun getItemCount(): Int = locationsFiltered.size
override fun onBindViewHolder(holder: LocationViewHolder, position: Int) {
holder.bind(locationsFiltered[position])
}
inner class LocationViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val title: TextView = itemView.findViewById(R.id.txtCostCenter)
private val desc: TextView = itemView.findViewById(R.id.txtCostCenterDescription)
fun bind(loc: Costcenter) {
title.text = loc.goederenontvanger
desc.text = loc.goederenontvanger_omschrijving
itemView.setOnClickListener {
onLocationClick.invoke(loc)
}
}
}
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
val charSearch = constraint.toString()
locationsFiltered = if (charSearch.isEmpty()) {
locations
} else {
val resultList = ArrayList<Costcenter>()
for (row in locations) {
if (row.goederenontvanger.toLowerCase()
.contains(charSearch.toLowerCase()) || row.goederenontvanger_omschrijving.toLowerCase()
.contains(charSearch.toLowerCase())
) {
resultList.add(row)
}
}
resultList
}
val filterResults = FilterResults()
filterResults.values = locationsFiltered
return filterResults
}
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
}
}
}
}
创建回收视图的片段
class LocationsFragment : Fragment() {
private lateinit var locationAdapter: LocationAdapter
private val storageViewModel by activityViewModels<StorageViewModel>()
private lateinit var currentView : View
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
var view = inflater.inflate(R.layout.fragment_locations, container, false)
var recycler = view.findViewById<RecyclerView>(R.id.recyclerLocations)
var filter = view.findViewById<SearchView>(R.id.editFilter)
locationAdapter = LocationAdapter(Utilities.costcenters) { loc -> setSelectedLocation(loc) }
val recycleMngr: RecyclerView.LayoutManager =
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
filter.setOnQueryTextListener(object: SearchView.OnQueryTextListener{
override fun onQueryTextSubmit(query: String?): Boolean {
return false
}
override fun onQueryTextChange(newText: String?): Boolean {
locationAdapter.filter.filter(newText)
return false
}
})
recycler.layoutManager = recycleMngr
recycler.adapter = locationAdapter
currentView = view
return view
}
当使用 publishResults()
发布过滤器时,您需要使用过滤结果更新原始列表 locationsFiltered
,然后 notifyDataSetChanged()
将更改应用到 RecyclerView
所以在 publishResults()
方法中添加以下内容:
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
locationsFiltered = filterResults.values as ArrayList<Costcenter>
notifyDataSetChanged()
}