【问题标题】:Why filtering property not work for search bar in android?为什么过滤属性不适用于android中的搜索栏?
【发布时间】:2022-01-20 22:12:20
【问题描述】:

我有一个简单的 android 项目,在片段中有一个用户列表的回收器视图,我想为这些用户使用搜索栏,这就是为什么我在列表视图中使用过滤来搜索用户,一切正常但是当我搜索用户名时,没有任何变化,并且过滤属性不适用于用户名。任何想法将不胜感激。

游戏适配器:

class GameAdapter(
    private val userId: String,
      var chatList: ArrayList<Game>

): RecyclerView.Adapter<GameAdapter.GamesHolder>(), Filterable {

    private var clickListener: ClickListener? = null
        var filteredUserDataList: MutableList<Game>

    inner class GamesHolder(view: View) : RecyclerView.ViewHolder(view), View.OnClickListener, View.OnLongClickListener {
        val textGameTitle: TextView = view.findViewById(R.id.textUsername)
     
    }
   override fun onBindViewHolder(holder: GamesHolder, position: 
   Int) {
    val game = filteredUserDataList[position]
  holder.textGameTitle.text = 
 game.getGameName(userId).toString()
    }

  override fun getItemCount(): Int {
    return filteredUserDataList.size
}
override fun getFilter(): Filter {
    return filter
}

private var filter = object : Filter() {

    override fun performFiltering(keyword: CharSequence): FilterResults {
        val filtereddata = java.util.ArrayList<Game>()
        if (keyword.toString().isEmpty()) filtereddata.addAll(gameList) else {
            for (obj in gameList) {
                if (obj.getGameName(userId).toLowerCase()
                        .contains(keyword.toString().toLowerCase())
                ) filtereddata.add(obj)
            }
        }
        val results = FilterResults()
        results.values = filtereddata
        return results
    }

  
    override fun publishResults(constraint: CharSequence, results: FilterResults) {
        gameList.clear()
        gameList.addAll((results.values as ArrayList<Game>))
        notifyDataSetChanged()
    }

    init {
        filteredUserDataList = gameList
    }
}

fun getItem(index: Int): Game {
    return filteredUserDataList[index]
} 

游戏片段:

class GameFragment : Fragment() {

    lateinit var recyclerViewGame: RecyclerView

    var searchView: EditText? = null
    var search: CharSequence = ""

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        val view = inflater.inflate(R.layout.fragment_games, container, false)

        recyclerViewGame = view.findViewById(R.id.game_list)

        configureRecycler(gameList)

        return view

    }

    private fun configureRecycler(games: ArrayList<Game>) {
        val userId = userPresenter.getGame().id
        val gamesAdapter = context?.let {
            GameAdapter(userId, it, games)
        }

        searchView = view?.findViewById(R.id.search_bar)

        searchView?.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
            override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
                gamesAdapter.filter.filter(charSequence)
                search = charSequence
            }
            override fun afterTextChanged(editable: Editable) {}
        })
     } }

【问题讨论】:

  • if (row.participants.find { it.id != userId }!!.username.lowercase(Locale.getDefault()) .contains(Key.lowercase(Locale.getDefault()))) { 是一个可能不匹配的条件..你试过用更简单的条件吗?
  • @Zain,我使用的是用户名而不是“iparticipants.find { it.id != userId }!!.username”,它显示“未解析的参考:用户名”,有什么想法吗?
  • Key指的是什么..是搜索到的用户名吗?
  • @Zain,我更新问题
  • 你的适配器有点乱。您正在 filteredUserDataList 内部进行更改 publishResults 而您的 getItemCount 返回 gameList.size .. 看看 This answer 我试图在那里解释它。关于这个主题有很多答案,但我找不到确切的答案。所以给你..

标签: android android-recyclerview android-filterable


【解决方案1】:

我可以看到这些东西

  1. filteredUserDataList 应该用 gameList 初始化

  2. 改变

    覆盖 fun getItemCount() = gameList.size

    覆盖 fun getItemCount() = filteredUserDataList.size

  3. 记住,filteredUserDataList 是主列表,而实际的 gameList 只是在用户清除或更改搜索查询时保持原始数据

【讨论】:

  • tnx 这么多,但它不起作用,我想,也许我可以使用用户名而不是参与者。find { it.id != userId }!!.username,但是如何?
  • 我必须同时使用 override fun getItemCount() = gameList.size override fun getItemCount(): Int { return filteredUserDataList.size } 可能对我有帮助,但我该如何同时使用完全
  • @Skysoft13 您只能覆盖一个方法一次,这是正确的覆盖覆盖 fun getItemCount(): Int { return filteredUserDataList.size }
  • 是的,你是对的,我做了,但还是一样没有过滤,我不明白,哪里出错了
【解决方案2】:

您检查了userName 而不是userId。这对我来说有点令人困惑,因为您在谓词中使用 userIduserId 在您的情况下是一个全局字段。看不懂userId这里的作用。

无论如何,我根据我的理解在下面添加了一个解决方案。试试看

override fun performFiltering(charSequence: CharSequence): FilterResults {
            val searchTerm = charSequence.toString().lowercase(Locale.getDefault())
            filteredUserDataList = if(searchTerm.isEmpty()){
                gameList
            }else{
                val lstFiltered: ArrayList<Game> = ArrayList()
                for (row in gameList) {
                    val user = row.participants.find {
                        it.username.lowercase(Locale.getDefault()).contains(searchTerm)
                    }
                    if (user!=null) {
                        lstFiltered.add(row)
                    }
                }
                lstFiltered
            }
            val filterResults = FilterResults()
            filterResults.values = filteredUserDataList
            return filterResults
        }

 override fun publishResults(charSequence: CharSequence, filterResults: FilterResults) {
            filteredUserDataList = filterResults.values as ArrayList<Game>
            notifyDataSetChanged()
        }

如果您尝试通过 usernameuserId 两个字段进行搜索,那么您在应用过滤器时必须同时考虑这两个字段。

【讨论】:

  • tnx 为你的回应,我想使用用户名,这就是我使用 getGameName(userId) 的原因,因为游戏模型中没有用户名,用户名是否有其他解决方案 :)
猜你喜欢
  • 2020-07-17
  • 2011-07-29
  • 2022-12-12
  • 1970-01-01
  • 2017-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多