I have a ListView that uses a custom adaper (that extends BaseAdapter). How do I add the swipe to delete gesture?
I want use the same functionality the gmail application uses.
I have a ListView that uses a custom adaper (that extends BaseAdapter). How do I add the swipe to delete gesture?
I want use the same functionality the gmail application uses.
The easiest way to do this is to move your ListView
over to a RecyclerView
and use a GridLayoutManager
with a single column. It will look the same, but allows you to swipe to dismiss using the ItemTouchHelper
.
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 1));
recyclerView.setAdapter(adapter);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
// Remove item from backing list here
adapter.notifyDataSetChanged();
}
});
itemTouchHelper.attachToRecyclerView(recyclerView);
notifyDataSetChanged
will force it to redraw whatever is on the screen. –
Playa You can use the lib ::
Accepted answer translated to Kotlin:
val itemTouchHelper = ItemTouchHelper(object: ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
TODO("Not yet implemented")
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
todoListAdapter.notifyDataSetChanged()
}
})
this.runOnUiThread {
itemTouchHelper.attachToRecyclerView(recyclerView)
}
A Kotlin version using a ListAdapter
all credit goes to this blog post: https://theeasiestwayy.medium.com/listadapter-and-swipe-to-delete-741e32e5f824 (which as a couple of typos in it's code examples)
abstract class ListAdapterSwipeable <T, VH: RecyclerView.ViewHolder>(
diffCallback: DiffUtil.ItemCallback<T>
): ListAdapter<T, VH>(diffCallback) {
private val removedItems: MutableList<T> = mutableListOf()
fun removeItem(position: Int): T? {
if (position >= itemCount) return null
val item = currentList[position]
removedItems.add(item)
val actualList = currentList - removedItems
if (actualList.isEmpty()) removedItems.clear()
submit(actualList, true)
return item
}
private fun submit(list: List<T>?, isLocalSubmit: Boolean) {
if (!isLocalSubmit) removedItems.clear()
super.submitList(list)
}
@CallSuper
override fun submitList(list: List<T>?) {
submit(list, false)
}
}
class ItemSwipeHandler<T>(
private val adapter: ListAdapterSwipeable<T, *>,
private val onItemRemoved: ((item: T) -> Unit)? = null
) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
// val position = viewHolder.adapterPosition DEPRECATED!!
val position = viewHolder.bindingAdapterPosition
val item = adapter.removeItem(position) ?: return
onItemRemoved?.invoke(item)
}
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean = false
}
More about it's usage see the blog article from above
The simplest way I have found is to use a ListView.builder
in a StatefullWidget
and wrap the children in a Dismissible
component:
ListView.builder(
itemCount: sampleList.length, //number of items on the list
itemBuilder: (BuildContext context, int index) {
return Dismissible(
key: Key(sampleList[index]), //unique key string for each element (in this case each string is unique)
onDismissed: (direction) {
setState(() {
sampleList.removeAt(index); //remove list element at given index and repaint
});
},
child: child: Text('${sampleList[index]}'), //what to display form the list
);
},
);
you can check/copy the code bellow as a working example, and pass it as a child to a component:
import 'package:flutter/material.dart';
class DismissibleList extends StatefulWidget {
@override
_DismissibleListState createState() => _DismissibleListState();
}
class _DismissibleListState extends State<DismissibleList> {
@override
Widget build(BuildContext context) {
List<String> sampleList = ['aa', 'bb', 'cc']; // the list of elements
return ListView.builder(
itemCount: sampleList.length, //number of items on the list
itemBuilder: (BuildContext context, int index) {
return Dismissible(
key: Key(sampleList[index]), //unique key string for each element (in this case each string is unique)
onDismissed: (direction) {
setState(() {
sampleList.removeAt(index); //remove list element at given index and repaint
});
},
child: child: Padding(
padding: EdgeInsets.all(16.0), // just to help the visual
child: Text('${sampleList[index]}'),
) //what to display form the list
);
},
);
}
}
© 2022 - 2024 — McMap. All rights reserved.