微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用自定义适配器为 AutoCompleteTextView 制作自定义过滤器?

如何解决如何使用自定义适配器为 AutoCompleteTextView 制作自定义过滤器?

我的布局中有一个 AutoCompleteTextView,它将从 API 获取数据,数据返回两个参数,描述和代码AutoCompleteText 必须可过滤代码和描述。>

为了查看代码和描述,我制作了一个自定义 ArrayAdapter,我试图实现 Filterable 方法来设置自定义过滤器,该过滤器将检查代码和描述属性。>

问题是,一旦我尝试通过在 AutoCompleteTextView 开始时抛出异常来写入 publishResults 我的应用程序崩溃:java.lang.UnsupportedOperationException

那么我如何为我的 ArrayAdapter 实现自定义过滤器?

这是我的适配器代码

class FornitoriAdapter(context: Context,resource: Int,private val fornitori: List<Fornitori>) :
    ArrayAdapter<Fornitori>(context,resource,fornitori),Filterable {

    override fun getView(position: Int,convertView: View?,parent: ViewGroup): View {
        val row: View
        val holder: ViewHolder

        if (convertView == null) {
            val inflater = LayoutInflater.from(context)
            row = inflater.inflate(R.layout.list_item,parent,false)
            holder = ViewHolder(row)
            row.tag = holder
        } else {
            row = convertView
            holder = row.tag as ViewHolder
        }

        val fornitore: Fornitori = fornitori[position]

        holder.descrText.text = fornitore.desc
        holder.codeText.text = fornitore.cod

        return row
    }

    override fun getItem(position: Int): Fornitori {
        return fornitori[position]
    }

    override fun getCount(): Int {
        return fornitori.size
    }

    private class ViewHolder constructor(row: View) {
        val descrText: TextView = row.findViewById(R.id.description)
        val codeText: TextView = row.findViewById(R.id.code)

    }

    override fun getFilter(): Filter {
        return customFilter
    }

    private val customFilter = object : Filter() {
    override fun convertResultToString(resultValue: Any?): CharSequence {
        return (resultValue as Fornitori).desc
    }

        override fun performFiltering(constraint: CharSequence?): FilterResults {
            val filteredList = mutablelistof<Fornitori>()
            if (constraint == null || constraint.isEmpty()) {
                filteredList.addAll(fornitori)
            } else {
                for (item in fornitori) {
                    if (item.cod.equals(constraint.toString(),ignoreCase = true) || item.desc.toLowerCase(
                            Locale.ROOT
                        ).startsWith(
                            constraint.toString().toLowerCase(
                                Locale.ROOT
                            )
                        )
                    ) {
                        filteredList.add(item)
                    }
                }
            }
            val results = FilterResults()
            results.values = filteredList
            return results
        }

        override fun publishResults(constraint: CharSequence?,filterResults: FilterResults?) {
            clear()
            val newValues: List<Fornitori> = filterResults?.values as List<Fornitori>
            for (element in newValues) {
                add(element)
            }
            if (filterResults.count > 0) {
                notifyDataSetChanged()
            } else {
                notifyDataSetInvalidated()
            }
        }

    }

}

这里是我如何在我的 Fragment 中管理它:

autocompleteFornitore = view.findViewById(R.id.autocompleteFornitore)

val fornitori: List<Fornitori> = listof(Fornitori("001","GAB"),Fornitori("002","TEST"))
val adapter = FornitoriAdapter(requireContext(),R.layout.list_item,fornitori)
autocompleteFornitore.setAdapter(adapter)


autocompleteFornitore.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
    override fun onItemSelected(
        parent: AdapterView<*>?,view: View?,position: Int,id: Long
    ) {

    }

    override fun onnothingSelected(parent: AdapterView<*>?) {

    }
}

根据需要完整的堆栈跟踪:

2021-03-09 16:05:26.915 31076-31076/it.xxx.xxx E/AndroidRuntime: FATAL EXCEPTION: main
    Process: it.xxx.xxx,PID: 31076
    java.lang.UnsupportedOperationException
        at java.util.AbstractList.remove(AbstractList.java:161)
        at java.util.AbstractList$Itr.remove(AbstractList.java:374)
        at java.util.AbstractList.removeRange(AbstractList.java:571)
        at java.util.AbstractList.clear(AbstractList.java:234)
        at android.widget.ArrayAdapter.clear(ArrayAdapter.java:320)
        at it.gabtamagnini.visualstock.adapters.FornitoriAdapter$customFilter$1.publishResults(FornitoriAdapter.kt:88)
        at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6518)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

解决方法

它在 ArrayAdapter 的文档中说:

@throws UnsupportedOperationException 如果底层数据集合是不可变的

因此,如果您想使用 MutableList,您应该将 ArrayAdapter 传入 clear(),通过将 FornitoriAdapter 构造为 1,或将其转换为 {{ 1}}。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。