Gurarshdeep Singh
Gurarshdeep Singh

Reputation: 92

Filter List in recyclerView

I am using recyclerView to show list of apps installed in device ....see images below

image 1 - Link

image 2 - Link

image 1 desc --> In this, i use popup menu to filter installed and system apps

image 2 desc --> In this, i showed that, i use imageView to find out which is installed or system app...these are indicated by play store and phone icon resp.

Question is ... sorting is working fine and I want to filter list and can do sort at that list to

somehow I manage to send filteredList to adapter with the help of Boolean value and function in adapter class, which assign new list to original list, but sort is not working there

Moreover, I also used swipe to delete and if I send new list...onSwiped method doesn't get new filtered position....as it hold original list adapterposition

MainActivity.kt

   class MainActivity : AppCompatActivity() {

    lateinit var adapter: Adapter  // create adapter instance
    lateinit var applicationList: MutableList<AppData>

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

        applicationList = getApps(installedApps()) // initialize applicationList variable
        recyclerView.layoutManager = LinearLayoutManager(this)
        adapter = Adapter(applicationList) // initialize adapter variable
        recyclerView.adapter = adapter // pass adapter to recyclerView
        updateNumberOfApps()

        sortList()
        filterList()


    }

  private fun sortList() {
        Sort_List.setOnClickListener {
            val popUp = PopupMenu(this, Sort_List)
            popUp.menuInflater.inflate(R.menu.sort_menu, popUp.menu)

            popUp.setOnMenuItemClickListener { myItem ->
                when (myItem.itemId) {
                    R.id.Name_ASC -> {
                        applicationList.sortBy { it.name }
                        adapter.notifyDataSetChanged()
                        scrollToTop()
                    }
                }
                true
            }
            popUp.show()
        }
    }

    private fun filterList() {

        Filter_List.setOnClickListener {
            val popUp = PopupMenu(this, Filter_List)
            popUp.menuInflater.inflate(R.menu.filter_menu, popUp.menu)

            popUp.setOnMenuItemClickListener { myItem ->
                when (myItem.itemId) {
                    R.id.Installed_Apps -> {
                        applicationList.all { it.category }
                        adapter.notifyDataSetChanged()
                        updateNumberOfApps()
                        scrollToTop()
                    }
                    R.id.System_Apps -> {
                   // PROBLEM IS HERE>>>I WANT FILTER AND SORTING WORKING TOGETHER
                       applicationList.sortedBy { it.category }
                        adapter.notifyDataSetChanged()
                        updateNumberOfApps()

                   // here I also manage to send list and assign to adapter like
                   // val list = applicationList.filter { it.category }
                   //  adapter.update(list)
                    }
                }
                true
            }
            popUp.show()
        }
    }

    private fun getApps(List: MutableList<ResolveInfo>): MutableList<AppData> {

        // here I get all apps and return list

        // In this, I also get Boolean value(named category), which return true on system app and false on the installed app
    }
 }
}

Adapter.kt

    class Adapter(private var listOfApps: MutableList<AppData>) :
    RecyclerView.Adapter<Adapter.ViewHolder>() {

    class ViewHolder(appView: View) : RecyclerView.ViewHolder(appView) {

        // call elements from list_apps.xml
        val icon: ImageView = appView.App_icon
        val name: TextView = appView.App_name
        val size: TextView = appView.App_size
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(
            R.layout.list_apps, parent, false
        )
        return ViewHolder(view)
    }

    override fun getItemCount() = listOfApps.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {

        val currentItem = listOfApps[position]
        holder.icon.setImageDrawable(currentItem.icon) 
        holder.name.text = currentItem.name
        holder.size.text = currentItem.size

       }
    }

// here I declare function which get list from filter method and assign new list to original list
    fun update(newList: MutableList<AppData>){
        listOfApps = newList
        notifyDataSetChanged()

    }
}

Upvotes: 0

Views: 936

Answers (1)

aminography
aminography

Reputation: 22832

The problem is that applicationList.all { it.category } does not filter the list. It checks over the list and returns true if the it.category gets true for all of the items, otherwise it returns false. You should use filter instead.

applicationList = applicationList.filter { it.category }

Note that filter is not an in-place action. So, you should set its result to applicationList.


Edit

You should always keep the state of the current showing list and populate it according to these states. I've changed your code by adding two boolean values like the following:

class MainActivity : AppCompatActivity() {

    lateinit var adapter: Adapter  // create adapter instance
    lateinit var applicationList: MutableList<AppData>

    private val showingApplicationList: MutableList<AppData> = mutableListOf()
    private var isSortedDesc = false
    private var isShowingSystemApps = false

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

        applicationList = getApps(installedApps()) // initialize applicationList variable

        recyclerView.layoutManager = LinearLayoutManager(this)
        adapter = Adapter(showingApplicationList) // initialize adapter variable
        recyclerView.adapter = adapter // pass adapter to recyclerView
        updateNumberOfApps()

        sortList()
        filterList()

        arrangeAppList()
        adapter.update(showingApplicationList)
    }

    private fun sortList() {
        Sort_List.setOnClickListener {
            val popUp = PopupMenu(this, Sort_List)
            popUp.menuInflater.inflate(R.menu.sort_menu, popUp.menu)

            popUp.setOnMenuItemClickListener { myItem ->
                when (myItem.itemId) {
                    R.id.Name_ASC -> {
                        isSortedDesc = false
                        arrangeAppList()
                        adapter.update(showingApplicationList)
                        scrollToTop()
                    }
                    R.id.Name_DESC -> {
                        isSortedDesc = true
                        arrangeAppList()
                        adapter.update(showingApplicationList)
                        scrollToTop()
                    }
                }
                true
            }
            popUp.show()
        }
    }

    private fun filterList() {

        Filter_List.setOnClickListener {
            val popUp = PopupMenu(this, Filter_List)
            popUp.menuInflater.inflate(R.menu.filter_menu, popUp.menu)

            popUp.setOnMenuItemClickListener { myItem ->
                when (myItem.itemId) {
                    R.id.Installed_Apps -> {
                        isShowingSystemApps = false
                        arrangeAppList()
                        adapter.update(showingApplicationList)
                        scrollToTop()
                        updateNumberOfApps()
                    }
                    R.id.System_Apps -> {
                        isShowingSystemApps = true
                        arrangeAppList()
                        adapter.update(showingApplicationList)
                        scrollToTop()
                        updateNumberOfApps()
                    }
                }
                true
            }
            popUp.show()
        }
    }

    private fun arrangeAppList() {
        showingApplicationList.clear()
        showingApplicationList.addAll(
            applicationList.filter { it.category == isShowingSystemApps }
        )
        if (isSortedDesc) {
            showingApplicationList.sortByDescending { it.name }
        } else {
            showingApplicationList.sortBy { it.name }
        }
    }

    private fun getApps(List: MutableList<ResolveInfo>): MutableList<AppData> {

        // here I get all apps and return list

        // In this, I also get Boolean value(named category), which return true on system app and false on the installed app
    }
}

Upvotes: 2

Related Questions