I am using recyclerView to show list of apps installed in device, I implement onSwipe method to perform uninstall ....along with sorting feature such as name, size etc..
Now when I sort list according to name onswipe viewholder ...doesn't refresh
Suppose in a list ...at index[1]...gallery app is there, after sorting this goes to index[10] now the problem is onSwipe method think gallery is at index[1], but actually it is displayed on index[10] in recyclerView ..
Problem occur here is when I swipe at index[1] it execute uninstall dialog of gallery but it is displayed at [10]
How to notify onSwiped method that list is sorted and every item change its index
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
sortList()
// I create sepearate abstract class SwipeToDeleteCallback and call here
val swipeHandler = object : SwipeToDeleteCallback(this) {
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
currentItem = viewHolder.adapterPosition
val packageName =
applicationList[currentItem].packageName // get packageName from position
val appCategory = applicationList[currentItem].category
uninstall() // call uninstall function
}
}
val itemTouchHelper = ItemTouchHelper(swipeHandler)
itemTouchHelper.attachToRecyclerView(recyclerView) // attach onSwipe to recyclerView
}
fun uninstall(){
// perform uninstall
}
private fun installedApps(): MutableList<ResolveInfo> {
// get installed apps
}
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 -> {
val sortedList = applicationList.sortedBy { it.name }
adapter.update(sortedList)
}
R.id.Name_DES -> {
val sortedList = applicationList.sortedByDescending { it.name }
adapter.update(sortedList)
}
}
true
}
popUp.show()
}
}
private fun getApps(List: MutableList<ResolveInfo>): MutableList<AppData> {
// fetch all apps and return list
}
SwipeToDeleteCallback.kt
abstract class SwipeToDeleteCallback(context: Context) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
private val deleteIcon = ContextCompat.getDrawable(context, R.drawable.ic_delete_white)
private val intrinsicWidth = deleteIcon?.intrinsicWidth
private val intrinsicHeight = deleteIcon?.intrinsicHeight
private val background = ColorDrawable()
private val backgroundColor = Color.parseColor("#f44336")
private val clearPaint = Paint().apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) }
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
return super.getMovementFlags(recyclerView, viewHolder)
}
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
return false
}
override fun onChildDraw(
c: Canvas,
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
dX: Float,
dY: Float,
actionState: Int,
isCurrentlyActive: Boolean
) {
val itemView = viewHolder.itemView
val itemHeight = itemView.bottom - itemView.top
val isCanceled = dX == 0f && !isCurrentlyActive
if (isCanceled){
clearCanvas(c,itemView.right + dX, itemView.top.toFloat(), itemView.right.toFloat(), itemView.bottom.toFloat())
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
}
// Draw the red delete button
//Calculate position of delete icon
// Draw the delete icon
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
}
private fun clearCanvas(c: Canvas?, left: Float, top: Float, right: Float, bottom: Float) {
c?.drawRect(left, top, right, bottom, clearPaint)
}
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
}
fun update(newList: MutableList<AppData>){
listOfApps = newList
notifyDataSetChanged()
}
There is one problem i see in your code: you are using applicationList to get swiped item inside onSwiped but after sorting you are putting another list to adapter. there are two ways to fix this
MODIFY SNIPPET TO
popUp.setOnMenuItemClickListener { myItem ->
when (myItem.itemId) {
R.id.Name_ASC -> {
applicationList.sortBy{ it.name }
adapter.notifyDataSetChanged()
}
R.id.Name_DES -> {
applicationList.sortByDescending{ it.name }
adapter.notifyDataSetChanged()
}
}
true
}