简体   繁体   中英

EditText is not filtering the list of RecyclerView in Android Kotlin

I am trying to filter the list in RecyclerView by EditText. In Activity, passing the response in the adapter object, which is getting from the ViewModel class. And in the adapter, the filter method is written. Overall the Search Filter from EditText is not working. Below the code is written I am not sure how can I resolve this problem.

Project having manly an Activity,Adapter, XML file, and the ViewModel class.

fragment_availabletender

This page is having EditText & RecyclerView.

         <EditText
         android:id="@+id/editMobileNo"
         android:layout_width="match_parent"
         android:layout_height="50dp"
         android:padding="0dp"
         android:background="@drawable/login_edittext"
         android:ems="10"
         android:hint="Search Tender"
         android:gravity="center"
         android:drawableLeft="@drawable/search_3_24"
         android:layout_below="@+id/tendertext"
         android:paddingLeft="50dp"
         >
       </EditText>

       <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/tender_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:color="@color/cardview_light_background"
        android:padding="6dp"
        android:background="@null"
        android:scrollbars="vertical"
        android:layout_marginTop="10dp"
        android:layout_below="@+id/text1"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        />

Model Class This class is having model

   data class TenderProperty(

    val id: String,
    @Json(name = "img_src") val imgSrcUrl: String,
    val type: String,
    val price: Double
    )

ViewModel Here response is getting

class NotificationViewModel : ViewModel() {


val response: LiveData<List<TenderProperty>>
    get() = _response

private var _responseByArray = ArrayList<TenderProperty>()
val responseByArray: List<TenderProperty>
    get() = _responseByArray

private val _navigateToSelectedProperty = MutableLiveData<TenderProperty>()
val navigateToSelectedProperty: LiveData<TenderProperty>
    get() = _navigateToSelectedProperty

// Create a Coroutine scope using a job to be able to cancel when needed
private var viewModelJob = Job()

private val coroutineScope = CoroutineScope(viewModelJob + Dispatchers.Main )


init {
    getTenderRealEstateProperties()
}

private fun getTenderRealEstateProperties() {

    coroutineScope.launch {
        // Get the Deferred object for our Retrofit request
        var getPropertiesDeferred = TenderApi.retrofitService.getProperties()
        try {
            // this will run on a thread managed by Retrofit
            val listResult = getPropertiesDeferred.await()

            _responseByArray= listResult as ArrayList<TenderProperty>

           Log.d("respbyary",responseByArray.toString())

        } catch (e: Exception) {

            _response.value = ArrayList()
            Log.d("class",responseByArray.toString())
        }
    }
}

This is the Adapter class

class ListTenderAdapter(context: Context, var tender: List<TenderProperty>) : ListAdapter<TenderProperty, ListTenderAdapter.TenderPropertyViewHolder>(DiffCallback),Filterable {

var originalData=tender

var filteredData = ArrayList<TenderProperty>()

//dought22
class TenderPropertyViewHolder(private var binding: TenderListViewBinding) : RecyclerView.ViewHolder(binding.root) {
    fun bind(tenderProperty: TenderProperty) {
        binding.property = tenderProperty
        binding.executePendingBindings()
    }
}

companion object DiffCallback : DiffUtil.ItemCallback<TenderProperty>()
{
    override fun areItemsTheSame(oldItem: TenderProperty, newItem: TenderProperty): Boolean {
        return oldItem === newItem
    }

    override fun areContentsTheSame(oldItem: TenderProperty, newItem: TenderProperty): Boolean {
        return oldItem.id == newItem.id
    }
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TenderPropertyViewHolder {
    return TenderPropertyViewHolder(TenderListViewBinding.inflate(LayoutInflater.from(parent.context)))
}

override fun onBindViewHolder(holder: TenderPropertyViewHolder, position: Int) {
    val tenderProperty = getItem(position)
    holder.bind(tenderProperty)
}

override fun getFilter(): Filter {

    return object : Filter() {

        override fun performFiltering(constraint: CharSequence?): FilterResults {

            var filteredList = ArrayList<TenderProperty>()
            if (constraint.isNullOrBlank()) {
                filteredData.addAll(originalData)
            }
            else {
                for (data in originalData) {
                    if (
                        data.id.toLowerCase().contains(constraint.toString().toLowerCase())||
                        data.price.toString().toLowerCase().contains(constraint.toString().toLowerCase())||
                        data.type.toLowerCase().contains(constraint.toString().toLowerCase()))
                    {
                        filteredList.add(data)
                    } }
            }
            val filterResults = FilterResults()
            filterResults.values = filteredList
            return filterResults
        }
        override fun publishResults(constraint: CharSequence, results: FilterResults) {

            filteredData.clear()
            filteredData.addAll(results.values as ArrayList<TenderProperty>)
            notifyDataSetChanged()

        }
    }}}

This is the Activity

 class TenderListActivity:AppCompatActivity() {

lateinit var adapter: ListTenderAdapter
lateinit var search:EditText
private lateinit var binding: FragmentAvailabletenderBinding
private val viewModel: NotificationViewModel by lazy {
    ViewModelProviders.of(this).get(NotificationViewModel::class.java)
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.fragment_availabletender)

    binding = DataBindingUtil.setContentView<FragmentAvailabletenderBinding>(
        this,
        R.layout.fragment_availabletender
    )

    search = binding.editMobileNo

    val divider = DividerItemDecoration(applicationContext, DividerItemDecoration.VERTICAL)
    binding.tenderList.addItemDecoration(divider)

    setupRecyclerView()
    initViewModel()
    search()
    backButton()
}

private fun setupRecyclerView() {

    binding.tenderList.addItemDecoration(MarginItemDecoration(5))
    adapter = ListTenderAdapter(this, viewModel.responseByArray)
    binding.tenderList.setAdapter(adapter)

}

private fun initViewModel() {
    viewModel.response.observe(this, Observer {
        adapter.submitList(it)
    })

}

private fun backButton()
{
    binding.backbtn.setOnClickListener(View.OnClickListener {

        val backbtn: Intent = Intent(this,MainActivity::class.java)
        startActivity(backbtn)

    })
}

private fun search()
{
       search.addTextChangedListener(object : TextWatcher {
        override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
        }

        override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
            adapter.getFilter().filter(s.toString())

        }

        override fun afterTextChanged(s: Editable) {

        }
    })
}}

i'm not use the filter in the adapter,but i think may be u can use the list.filter and setThe NewData with the DiffUtil? although it may be not the best solution

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM