SearchView 在回收站视图中不起作用

Posted

技术标签:

【中文标题】SearchView 在回收站视图中不起作用【英文标题】:SearchView in Not Working in Recycler View 【发布时间】:2021-11-02 07:18:33 【问题描述】:

我正在尝试在 recyclerview 上添加 searchview,但它无法正常工作,甚至没有显示任何错误。我在***上准备了很多答案,但它们对我不起作用。请告诉我我的代码中有什么错误。当我调试我的代码时,搜索的值显示在结果变量中,但没有显示在 recyclerview 中。我想搜索 1) 国家名称 2) 大写 3) 和 id 可以帮助我

我的适配器在这里

class ProfileListAdapter(var profiles:ArrayList<Profile>):RecyclerView.Adapter<ProfileListAdapter.ProfileViewHolder>(),Filterable 

   
    fun updateProfile(newProfiles:List<Profile>)
        profiles.clear()
        profiles.addAll(newProfiles)
        notifyDataSetChanged()
    
    var profileFilterList = ArrayList<Profile>()
    init 
        profileFilterList = profiles
    
    class ProfileViewHolder(view: View):RecyclerView.ViewHolder(view)
       private var id = view.findViewById<TextView>(R.id.tv_id)
       private var name = view.findViewById<TextView>(R.id.tv_name)
       private var fatherName = view.findViewById<TextView>(R.id.tv_father_name)
       private var profileImage = view.findViewById<ImageView>(R.id.iv_profile_image)
       private var progressDrawable = getProgressDrawable(view.context)

       fun bind(profile: Profile)
          id.text = profile.id.toString()
           name.text = profile.name
           fatherName.text = profile.fatherName
           profileImage.loadImage(profile.profilePicture,progressDrawable)
       
   
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ProfileViewHolder(
        LayoutInflater.from(parent.context).inflate(R.layout.rv_dummy_items,parent,false)
    )
    override fun onBindViewHolder(holder: ProfileViewHolder, position: Int) 
        holder.bind(profiles[position])
    
    override fun getItemCount() = profiles.size


// Search items
    override fun getFilter(): Filter 
        return object : Filter() 
            override fun performFiltering(constraint: CharSequence?): FilterResults 
                val charString = constraint?.toString() ?: ""
                if (charString.isEmpty())
                    profiles.also  profileFilterList = it 
                 else 
                    val filteredList = ArrayList<Profile>()
                    profiles
                        .filter 
                            (it.name.contains(constraint!!)) or (it.fatherName.contains(constraint))
                        
                        .forEach  filteredList.add(it) 
                    profileFilterList = filteredList
                
                return FilterResults().apply  values = profileFilterList 
            
            override fun publishResults(constraint: CharSequence?, results: FilterResults?) 
                profileFilterList = if (results?.values == null) ArrayList()
                else
                    results.values as ArrayList<Profile>
                notifyDataSetChanged()
            
        
    

    

我的主要活动在这里

class MainActivity : AppCompatActivity() 
    lateinit var binding: ActivityMainBinding
    lateinit var viewModel: ListViewModel
    var profileAdapter = ProfileListAdapter(arrayListOf())

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)
        //here I'm calling search profile function
        searchProfile()
        //
        viewModel = ViewModelProviders.of(this).get(ListViewModel::class.java)
        viewModel.refresh()

        binding.rvProfileList.apply 
            layoutManager = LinearLayoutManager(context)
            adapter = profileAdapter
        
        observeViewModel()
        filterButtons()
    
    fun observeViewModel() 
        viewModel.profiles.observe(this, Observer  profiles: List<Profile>? ->
            profiles?.let 
                binding.rvProfileList.visibility = View.VISIBLE
                profileAdapter.updateProfile(it)
            
        )
        viewModel.profileLoadingError.observe(this, Observer  isError: Boolean? ->
            isError?.let 
                binding.listError.visibility = if (it) View.VISIBLE else View.GONE
            
        )
        viewModel.loading.observe(this, Observer  isLoading ->
            isLoading?.let 
                binding.loadingView.visibility = if (it) View.VISIBLE else View.GONE
            
        )

    

    //search function
    fun searchProfile()

        binding.searchView.setOnQueryTextListener(object: SearchView.OnQueryTextListener
            override fun onQueryTextSubmit(query: String?): Boolean 
                profileAdapter.filter.filter(query)
                return false
            
            override fun onQueryTextChange(newText: String?): Boolean 
                profileAdapter.filter.filter(newText)
                return false
            

        )
    

【问题讨论】:

请修剪您的代码,以便更容易找到您的问题。请按照以下指南创建minimal reproducible example。 【参考方案1】:

你的代码质量真的很差。我反复阅读以了解您的意思。

首先,您在 OnQueryTextListener 中进行了两次过滤。相反,您只能过滤一次。将您的 searchProfile 函数更改为

 fun searchProfile()

    binding.searchView.setOnQueryTextListener(object: SearchView.OnQueryTextListener
        override fun onQueryTextSubmit(query: String?): Boolean 
            return false
        
        override fun onQueryTextChange(newText: String?): Boolean 
            profileAdapter.filter.filter(newText)
            return false
        

    )

您的失败可能是因为重新分配了您的 profilesprofileFilterList 列表。

在少数情况下,您将 profiles 分配给 profileFilterList,而不是复制!两个列表都有相同的引用。因此,如果其中一个发生变化,其他列表会直接发生变化。

更改您的适配器初始化块
init 
    profileFilterList = profiles

init 
    profileFilterList = ArrayList(profiles)

更改您的 getFilter 函数
    override fun getFilter(): Filter 
    return object : Filter() 
        override fun performFiltering(constraint: CharSequence?): FilterResults 
            val charString = constraint?.toString() ?: ""
            if (charString.isEmpty())
                profiles.also  profileFilterList = it 
             else 
                val filteredList = ArrayList<Profile>()
                profiles
                    .filter 
                        (it.name.contains(constraint!!)) or (it.fatherName.contains(constraint))
                    
                    .forEach  filteredList.add(it) 
                profileFilterList = filteredList
            
            return FilterResults().apply  values = profileFilterList 
        
        override fun publishResults(constraint: CharSequence?, results: FilterResults?) 
            profileFilterList = if (results?.values == null) ArrayList()
            else
                results.values as ArrayList<Profile>
            notifyDataSetChanged()
        
    

    override fun getFilter(): Filter 
    return object : Filter() 
        override fun performFiltering(constraint: CharSequence?): FilterResults 
            val filteredList = mutableListOf<Profile>()

            if (constraint == null || constraint.isEmpty()) 
                filteredList.addAll(profiles)
             else 
                filteredList.addAll(
                    profiles.filter  (it.name.contains(constraint!!)) or (it.fatherName.contains(constraint))                     )
            

            return FilterResults().apply  values = filteredList 
        

        override fun publishResults(constraint: CharSequence?, results: FilterResults?) 
            profileFilterList.clear()
            results?.values?.let 
                profileFilterList.addAll(it as MutableList<Profile>)
            
            notifyDataSetChanged()
        
    

【讨论】:

非常感谢您的回答。先生,它仍然无法正常工作 你能解释一下'不工作'是什么意思吗? 表示当我搜索某些东西时,它不搜索 提交答案后,我稍作修改。你可以试试当前的代码吗?【参考方案2】:

我在您的适配器中进行编辑,并且过滤器在修改后对我的代码正常工作

class ProfileListAdapter():RecyclerView.Adapter<ProfileListAdapter.ProfileViewHolder>(),Filterable 
  
 var profileList: ArrayList<Profile> = ArrayList()
 var profileListFiltered: ArrayList<Profile> = ArrayList()


fun updateProfile(newProfiles:List<Profile>)
    
     profileList = ArrayList(newProfiles)
     profileListFiltered = profileList
    notifyDataSetChanged()


class ProfileViewHolder(view: View):RecyclerView.ViewHolder(view)
   private var id = view.findViewById<TextView>(R.id.tv_id)
   private var name = view.findViewById<TextView>(R.id.tv_name)
   private var fatherName = view.findViewById<TextView>(R.id.tv_father_name)
   private var profileImage = view.findViewById<ImageView>(R.id.iv_profile_image)
   private var progressDrawable = getProgressDrawable(view.context)

   fun bind(profile: Profile)
      id.text = profile.id.toString()
       name.text = profile.name
       fatherName.text = profile.fatherName
       profileImage.loadImage(profile.profilePicture,progressDrawable)
   
  
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = 
    ProfileViewHolder(
    


LayoutInflater.from(parent.context).inflate(R.layout.rv_dummy_items,parent,false)
)
        override fun onBindViewHolder(holder: ProfileViewHolder, position: Int) 
      
           holder.bind(profileListFiltered[position])
        
          override fun getItemCount() = profileListFiltered.size


         // Search items
        override fun getFilter(): Filter 
              return object : Filter() 
        override fun performFiltering(constraint: CharSequence?): FilterResults 
           
            val charString = constraint?.toString() ?: ""
            if (charString.isEmpty())
               profileListFiltered = profileList
             else 
                val filteredList = ArrayList<Profile>()
                profileList
                    .filter 
                        (it.name.contains(constraint!!)) or 
                  (it.fatherName.contains(constraint))
                    
                    .forEach  filteredList.add(it) 
                profileFilterList = filteredList
            
            return FilterResults().apply  values = profileFilterList 
        
        override fun publishResults(constraint: CharSequence?, results: 
    FilterResults?) 
            profileFilterList = if (results?.values == null) ArrayList()
            else
                results.values as ArrayList<Profile>
            notifyDataSetChanged()
          
      
    


 

在您的活动中,只需在使用适配器 updateProfile 中的函数获取数据后声明不带参数构造函数的适配器,然后您的 ISA 即可正常工作

为您的适配器编辑

class ProfileListAdapter(var 
    profiles:ArrayList<Profile>)
  :RecyclerView.Adapter<ProfileListAdapter.Profile 
 ViewHolder>(),Filterable 


fun updateProfile(newProfiles:List<Profile>)
    profiles.clear()
    profiles.addAll(newProfiles)
    notifyDataSetChanged()

var profileFilterList = ArrayList<Profile>()
init 
    profileFilterList = profiles

class ProfileViewHolder(view: View):RecyclerView.ViewHolder(view)
   private var id = view.findViewById<TextView>(R.id.tv_id)
   private var name = view.findViewById<TextView>(R.id.tv_name)
   private var fatherName = view.findViewById<TextView> 
    (R.id.tv_father_name)
   private var profileImage = view.findViewById<ImageView> 
   (R.id.iv_profile_image)
   private var progressDrawable = getProgressDrawable(view.context)

   fun bind(profile: Profile)
      id.text = profile.id.toString()
       name.text = profile.name
       fatherName.text = profile.fatherName
       profileImage.loadImage(profile.profilePicture,progressDrawable)
   
  
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = 
  ProfileViewHolder(
   LayoutInflater.from(parent.context)
   .inflate(R.layout.rv_dummy_items,parent,false)
     )
      override fun onBindViewHolder(holder: ProfileViewHolder, position: 
      Int) 
   
    holder.bind(profileFilterList[position])
    
    override fun getItemCount() = profileFilterList.size


  // Search items
   override fun getFilter(): Filter 
      return object : Filter() 
        override fun performFiltering(constraint: CharSequence?): 
         FilterResults 
            val charString = constraint?.toString() ?: ""
            if (charString.isEmpty())
               profileFilterList = profiles
             else 
                val filteredList = ArrayList<Profile>()
                profiles
                    .filter 
                        (it.name.contains(constraint!!)) or 
          (it.fatherName.contains(constraint))
                    
                    .forEach  filteredList.add(it) 
                profileFilterList = filteredList
            
            return FilterResults().apply  values = profileFilterList 
        
        override fun publishResults(constraint: CharSequence?, results: 
     FilterResults?) 
            profileFilterList = if (results?.values == null) ArrayList()
            else
                results.values as ArrayList<Profile>
            notifyDataSetChanged()
        
    
    


  

【讨论】:

如果我删除此行:profiles.addAll(newProfiles) 则列表未显示,如果我添加此行则搜索不起作用 这是适配器工作与你合作?@faizdev @faizdev 您的适配器没有问题您使用配置文件列表绑定视图并为其返回计数您必须在适配器中使用 profileFilterList 并从此列表中返回计数只是尝试它会与您一​​起使用我想,但我尝试将我的适配器与我一起很好地用于过滤器 我看不懂你能编辑我的代码吗? 没有 searchview 这个适配器对我来说很好用

以上是关于SearchView 在回收站视图中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

回收站视图在 Fragment 中不起作用

DiffUtil 在嵌套的 recyclerview Kotlin 中不起作用

Constraintlayout Vertical Bias 在Android的两个视图中不起作用

Recyclerview 滚动在嵌套滚动视图中的片段中不起作用

由于应用程序兼容,Searchview 不起作用

@font-face 在 Firefox 中不起作用 [重复]