【问题标题】:Custom ArrayAdapter with filter is not filtering correctly带有过滤器的自定义 ArrayAdapter 未正确过滤
【发布时间】:2018-11-18 16:18:51
【问题描述】:

我有以下 ArrayAdapter

class SearchAdapter(private val activity: Activity, private var species: ArrayList<Specie>) : ArrayAdapter<Specie>(activity, R.layout.specie_item, species) {

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        return convertView ?: createView(position, parent)
    }

    private fun createView(position: Int, parent: ViewGroup?): View {
        val specie = species[position]

        val view = LayoutInflater.from(context).inflate(R.layout.specie_item, parent, false)
        view.specie_text.text = specie.name

        return view
    }

    override fun getCount() = species.size

    override fun getItem(position: Int) = species[position]

    override fun getFilter() = filter

    private var filter: Filter = object : Filter() {

        override fun performFiltering(constraint: CharSequence?): Filter.FilterResults {
            val results = FilterResults()

            val query = if (constraint != null && constraint.isNotEmpty()) autocomplete(constraint.toString())
            else arrayListOf()

            results.values = query
            results.count = query.size

            return results
        }

        private fun autocomplete(input: String): ArrayList<Specie> {
            val results = arrayListOf<Specie>()

            for (specie in species) {
                if (specie.name.toLowerCase().contains(input.toLowerCase())) results.add(specie)
            }

            return results
         }

         override fun publishResults(constraint: CharSequence?, results: Filter.FilterResults) {
            if (results.count > 0) notifyDataSetChanged()
            else notifyDataSetInvalidated()
         }

         override fun convertResultToString(result: Any) = (result as Specie).name
     }
}

此适配器的目的是在我们在 AutoCompleteTextview 中键入内容时显示一些建议。为此,我有一个过滤器,可以根据用户输入搜索物种名称。问题是这个过滤器没有像我预期的那样工作:

到这里为止还好。它显示所有以 agro

开头的物种名称

但是在输入更多内容后,它不再过滤。它应该显示以 agrostis cas 开头的物种名称,但仍显示 Agrostis azorica。 p>

我的过滤器坏了吗?我尝试了一些其他的过滤方式,但我得到了完全相同的结果。

【问题讨论】:

    标签: android filter kotlin android-arrayadapter comparator


    【解决方案1】:

    您目前缺少的是您的适配器没有考虑有关您的过滤器的任何内容,您将其设置为依赖于您的获取计数 getItemPosition 的完整物种列表。

    此外,您应该注意在适配器回收视图时更新文本,而不是仅在创建视图时设置值。

    这样的东西应该更好:

    class SearchAdapter(private val activity: Activity, private var species: ArrayList<Specie>) : ArrayAdapter<Specie>(activity, R.layout.specie_item, species) {
    
        var filtered = ArrayList<Specie>()
    
        override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
            return convertView ?: createView(position, parent)
        }
    
        private fun createView(position: Int, parent: ViewGroup?): View {
            val view = LayoutInflater.from(context).inflate(R.layout.specie_item, parent, false)
            view?.name?.text = filtered[position].name
            return view
        }
    
        override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup?): View {
            convertView ?: LayoutInflater.from(context).inflate(R.layout.specie_item, parent, false)
            convertView?.name?.text = filtered[position].name
            return super.getDropDownView(position, convertView, parent)
        }
    
        override fun getCount() = filtered.size
    
        override fun getItem(position: Int) = filtered[position]
    
        override fun getFilter() = filter
    
        private var filter: Filter = object : Filter() {
    
            override fun performFiltering(constraint: CharSequence?): Filter.FilterResults {
                val results = FilterResults()
    
                val query = if (constraint != null && constraint.isNotEmpty()) autocomplete(constraint.toString())
                else arrayListOf()
    
                results.values = query
                results.count = query.size
    
                return results
            }
    
            private fun autocomplete(input: String): ArrayList<Specie> {
                val results = arrayListOf<Specie>()
    
                for (specie in species) {
                    if (specie.name.toLowerCase().contains(input.toLowerCase())) results.add(specie)
                }
    
                return results
            }
    
            override fun publishResults(constraint: CharSequence?, results: Filter.FilterResults) {
                filtered = results.values as ArrayList<Specie>
                notifyDataSetInvalidated()
            }
    
            override fun convertResultToString(result: Any) = (result as Specie).name
        }
    }
    

    【讨论】:

    • 您的回答似乎有效!唯一的问题是建议一直隐藏并显示我输入的每种类型。就像他们每次都在重新创建一样。有什么办法可以避免这种情况?
    • 它显示和隐藏,因为我只放了 notifyDataSetInvalidated,我必须承认我有点懒得解决这个问题,我想你想先了解你的过滤问题,刷新当然可以解决
    • 哦,我明白了。我将尝试调查这种显示和隐藏行为。谢谢!
    猜你喜欢
    • 2012-04-24
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    相关资源
    最近更新 更多