如何实现对SearchView的缩写搜索

问题描述 投票:0回答:1

我有一个Fragment包含一个与SearchView一起使用的字符串(公司名称)列表。但是,由于许多公司名称很长,有没有办法可以输入公司名称的缩写而不必输入整个公司名称? 'FTSE 150'和'FTSE 250'是不言自明的,因此不需要abbereviation。

公司名称的缩写

  • GSK - GlaxoSmithKline plc
  • HSX - Hiscox Ltd.
  • IHG - InterContinental Hotels Group plc
  • MKS - Marks&Spencer Group plc

strings.xml中

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="company_names">
        <item>@string/glaxosmithkline_plc</item>
        <item>@string/hiscox_ltd</item>
        <item>@string/intercontinental_hotels_group_plc</item>
        <item>@string/marks_and_spencer_group_plc</item>
        <item>@string/ftse_150</item>
        <item>@string/ftse_250</item>
    </string-array>

    <string name="glaxosmithkline_plc">GlaxoSmithKline plc</string>
    <string name="hiscox_ltd">Hiscox Ltd</string>
    <string name="intercontinental_hotels_group_plc">InterContinental Hotels Group plc</string>
    <string name="marks_and_spencer_group_plc">Marks &amp; Spencer Group plc</string>
    <string name="ftse_150">FTSE 150</string>
    <string name="ftse_250">FTSE 250</string>
</resources>

片段类

class MyFragment : androidx.fragment.app.Fragment() {

    private var mAdapter: MyListAdapter? = null

    private lateinit var mRecyclerView: androidx.recyclerview.widget.RecyclerView

    private var mTwoPane: Boolean = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.layout_recyclerview, container, false)
        mTwoPane = (activity as androidx.fragment.app.FragmentActivity).findViewById<View>(R.id.detail_container) != null

        mRecyclerView = view.findViewById(R.id.recyclerView_list)
        mRecyclerView.setHasFixedSize(true)
        mRecyclerView.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this.activity)
        mRecyclerView.addItemDecoration(androidx.recyclerview.widget.DividerItemDecoration(Objects.requireNonNull<Context>(context), LinearLayout.VERTICAL))

        val myList = ArrayList<Companies>()

//        val items = resources.getStringArray(R.array.company_names)
//        for (n in items) {
//            val company = Companies(0, "", "")
//            myList.add(company)
//        }

        val companyA = Companies(1, "GlaxoSmithKline plc", "GSK")
        val companyB = Companies(2, "Hiscox Ltd", "HSX")
        val companyC = Companies(3, "InterContinental Hotels Group plc", "IHG")
        val companyD = Companies(4, "Marks & Spencer Group plc", "MKS")
        val companyE = Companies(5, "FTSE 150", "")
        val companyF = Companies(6, "FTSE 250", "")

        val myList = DatabaseHandler(this.context!!)
        myList.insertData(companyA)
        myList.insertData(companyB)
        myList.insertData(companyC)
        myList.insertData(companyD)
        myList.insertData(companyE)
        myList.insertData(companyF)

        mAdapter = MyListAdapter(activity!!, myList, mTwoPane)

        mRecyclerView.adapter = mAdapter

        return view
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        val mInflater = Objects.requireNonNull<androidx.fragment.app.FragmentActivity>(activity).menuInflater
        mInflater.inflate(R.menu.menu_search, menu)

        val searchView = searchitem.actionView as SearchView

        searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
            override fun onQueryTextSubmit(query: String): Boolean {
                return false
            }

            override fun onQueryTextChange(newText: String): Boolean {
                mAdapter!!.filter.filter(newText)
                return false
            }
        })

        super.onCreateOptionsMenu(menu, inflater)
    }
}

MyListAdapter类

class MyListAdapter(private val mCtx: Context, private val myList: MutableList<Companies>,
                          private val
mTwoPane: Boolean) : androidx.recyclerview.widget.RecyclerView.Adapter<MyListAdapter
.CompanyViewHolder>(), Filterable {
    private var myListFull = myList.toMutableList()

    private val companyFilter = object : Filter() {
        override fun performFiltering(constraint: CharSequence?): Filter.FilterResults {
            val filteredList = ArrayList<Companies>()

            when {
                constraint == null || constraint.isEmpty() -> filteredList.addAll(myListFull)
                else -> {
                    val filterPattern = constraint.toString().toLowerCase().trim { it <= ' ' }

                    for (item in myListFull) {
                        when {
                            item.companyName!!.toLowerCase().contains(filterPattern) ->
                                filteredList.add(item)
                        }
                    }
                }
            }

            val results = Filter.FilterResults()
            results.values = filteredList
            return results
        }

        override fun publishResults(constraint: CharSequence?, results: Filter.FilterResults?) {
            myList.clear()
            myList.addAll(results!!.values as List<Companies>)
            notifyDataSetChanged()
        }
    }

    inner class CompanyViewHolder(itemView: View) : androidx.recyclerview.widget.RecyclerView
    .ViewHolder(itemView) {
        var tvTitle: TextView = itemView.findViewById(R.id.tv_RVItem)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CompanyViewHolder {
        val inflater = LayoutInflater.from(mCtx)
        val v = inflater.inflate(R.layout.recyclerview_item_textview, parent, false)
        return CompanyViewHolder(v)
    }

    override fun onBindViewHolder(holder: CompanyViewHolder, position: Int) {
        val product = myList[holder.adapterPosition]

        holder.tvTitle.text = product.companyfuName
    }

    override fun getItemCount(): Int {
        return myList.size
    }

    override fun getFilter(): Filter {
        return companyFilter
    }
}

enter image description here

enter image description here

enter image description here

更新

自定义模型类

data class Companies (val id: String, val fullName: String, val abbreviation: String)

更新的适配器类

class MyListAdapter(private val mCtx: Context,
                    private val mCompanies: MutableList<Companies>,
                    private val mTwoPane: Boolean) : androidx.recyclerview.widget.RecyclerView.Adapter<MyListAdapter
.CompanyViewHolder>(), Filterable {
    private val mCompaniesFull = mCompanies.toMutableList()

    private val companyFilter = object : Filter() {
        override fun performFiltering(constraint: CharSequence?): Filter.FilterResults {
            val filteredList = if (constraint == null || constraint.isEmpty()) {
                mCompanies
            } else {
                val filterText = constraint.toString()
                mCompanies.filter { it.companyName.matchesIgnoreCase(filterText) || it.companyAbbreviation.matchesIgnoreCase(filterText) }
            }

            val results = Filter.FilterResults()
            results.values = filteredList
            return results
        }

        override fun publishResults(constraint: CharSequence?, results: Filter.FilterResults?) {
            mCompanies.clear()
            mCompanies.addAll(results!!.values as List<Companies>)
            notifyDataSetChanged()
        }
    }

    private fun String.matchesIgnoreCase(otherString: String): Boolean {
        return this.toLowerCase().contains(otherString.trim().toLowerCase())
    }

    inner class CompanyViewHolder(itemView: View) : androidx.recyclerview.widget.RecyclerView
    .ViewHolder(itemView) {
        var tvTitle: TextView = itemView.findViewById(R.id.tv_RVItem)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CompanyViewHolder {
        val inflater = LayoutInflater.from(mCtx)
        val v = inflater.inflate(R.layout.recyclerview_item_textview, parent, false)
        return CompanyViewHolder(v)
    }

    override fun onBindViewHolder(holder: CompanyViewHolder, position: Int) {
        val product = mCompanies[holder.adapterPosition]
        holder.tvTitle.text = product.companyName
    }

    override fun getItemCount(): Int {
        return mCompanies.size
    }

    override fun getFilter(): Filter {
        return companyFilter
    }
}

更新了Fragment类

class MonFragment : androidx.fragment.app.Fragment() {

    private var mAdapter: MyListAdapter? = null

    private lateinit var mRecyclerView: androidx.recyclerview.widget.RecyclerView

    private var mTwoPane: Boolean = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.layout_recyclerview, container, false)
        mTwoPane = (activity as androidx.fragment.app.FragmentActivity).findViewById<View>(R.id.detail_container) != null

        mRecyclerView = view.findViewById<RecyclerView>(R.id.recyclerView_list)
        mRecyclerView.setHasFixedSize(true)
        mRecyclerView.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this.activity)
        mRecyclerView.addItemDecoration(androidx.recyclerview.widget.DividerItemDecoration(Objects.requireNonNull<Context>(context), LinearLayout.VERTICAL))

        mCompanies.add(Companies("GlaxoSmithKline plc", "GSK"))
        mCompanies.add(Companies("Hiscox Ltd", "HSX"))
        mCompanies.add(Companies("InterContinental Hotels Group plc", "IHG"))
        mCompanies.add(Companies("Marks & Spencer Group plc", "MKS"))
        mCompanies.add(Companies("FTSE 150", ""))
        mCompanies.add(Companies("FTSE 250", ""))

        mAdapter = MyListAdapter(activity!!, mCompanies, mTwoPane)

        mRecyclerView.adapter = mAdapter

        return view
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        val mInflater = Objects.requireNonNull<androidx.fragment.app.FragmentActivity>(activity).menuInflater
        mInflater.inflate(R.menu.menu_search, menu)

        val searchitem = menu.findItem(R.id.action_search)
        val searchView = searchitem.actionView as SearchView

        searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
            override fun onQueryTextSubmit(query: String): Boolean {
                return false
            }

            override fun onQueryTextChange(newText: String): Boolean {
                mAdapter!!.filter.filter(newText)
                mAdapter!!.notifyDataSetChanged()

                return false
            }
        })

        super.onCreateOptionsMenu(menu, inflater)
    }
}
android kotlin searchview android-search android-searchmanager
1个回答
1
投票

在评论中讨论后,我建议使用两种方法来存储数据:

  1. 使用SharedPreferences或数据库进行设备存储:SQLiteRoom(它们是轻量级本地存储数据库,不需要Internet连接)。
  2. 设备内存(不推荐)作为在MainActivityFragmentonCreate方法中初始化的硬编码对象的列表(取决于用法)。

正如@CoolMind建议您应该实现自定义模型类CompanyName(id, fullName, abbreviation),然后通过fullNameabbreviation的替代方法进行过滤。

编辑:在MyListAdapter摆脱myListFull,因为它什么都不做,并把:

private val stockFilter = object : Filter() {
        override fun performFiltering(constraint: CharSequence?): Filter.FilterResults {
            val filteredList = if (constraint == null || constraint.isEmpty()) myList
                else {
                   val filterText = constraint.toString()
                   myList.filter { it.fullName.matchesIgnoreCase(filterText ) || it.abbreviation.matchesIgnoreCase(filterText) }
                }
            val results = Filter.FilterResults()
            results.values = filteredList
            return results
        }
}

还在MyListAdapter类中添加了这个扩展函数:

private fun String.matchesIgnoreCase(otherString: String): Boolean {
    return this.toLowerCase().contains(otherString.trim().toLowerCase())
}
© www.soinside.com 2019 - 2024. All rights reserved.