带过滤器的自定义ArrayAdapter未正确过滤

时间:2018-06-08 15:01:24

标签: android filter kotlin android-arrayadapter comparator

我有以下 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 中输入内容时显示一些建议。为此,我有一个过滤器,根据用户输入搜索物种名称。问题是这个过滤器没有按预期工作:

enter image description here 直到这里它还不错。它显示了以 agro

开头的所有物种名称

enter image description here 但是在输入更多内容之后,它就不再过滤了。它应该显示以 agrostis cas 开头的物种名称,但它仍然显示 Agrostis azorica

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

1 个答案:

答案 0 :(得分:2)

您目前缺少的是您的适配器没有考虑您的过滤器的任何内容,您将其设置为依赖于您的获取计数的完整物种列表,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
    }
}