I'm trying to implement a Recycleview with different ItemTouchHelper for each item on the list.
The only way that I know is to add an ItemTouchHelper directly to the RecycleView and not to the item.
Example of what I'm trying to do:
I have a list with 4 items and all items I can swipe to the left.
The first item will show a delete button.
The second item will show a delete button and edit button.
The third item shows a delete button.
The fourth item shows a copy, a delete, and an edit button.
*The list can have a lot of items.
Does someone know how to do that?
So basically your your question is about how to add a unique ItemTouchHelper
to each RecyclerView
item based on the item type.
Without going deeply into the details of how you want each item to differ in the ItemTouchHelper
swipe action, like you said to add some button functionalities like copy, edit, and delete. I will be just to the point How to differ ItemTouchHelper
's swipe for different items.
Step 1: Differentiate among RecyclerView
items using a POJO field
So, first you need to create a field in your POJO (typically an int
or enum
) that differentiates among different items.
Step 2: Implement a custom ItemTouchHelper.SimpleCallback
Create a custom ItemTouchHelper.SimpleCallback
class that takes the list of the RecyclerView
items into its constructor.
Next, override onChildDraw()
which is called by ItemTouchHelper
on RecyclerView
's onDraw()
callback; and this is the right place as it's called whenever the RecyclerView draws its individual items.
So, in this method you can implement how you want each item looks like when you swipe. And as it takes a ViewHolder instance, so you can get the swiped item position with ViewHolder.getAdapterPosition()
, and from the provided list of items, you can get the swiped item of this paritcular positon.
Here is a simple example that is a list of colors that reflects the background color whenever you swipe a certain item.
This is how it looks like:
POJO
For the above mentioned step 1, I store the value into colorValue
field
class ColorItem {
String colorName;
int colorValue;
public ColorItem(String colorName, int colorValue) {
this.colorName = colorName;
this.colorValue = colorValue;
}
public String getColorName() {
return colorName;
}
public void setColorName(String colorName) {
this.colorName = colorName;
}
public int getColorValue() {
return colorValue;
}
public void setColorValue(int colorValue) {
this.colorValue = colorValue;
}
}
RecyclerView adapter (no fancy code)
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.CustomViewHolder> {
List<ColorItem> mColors;
// Constructor
RecyclerAdapter(List<ColorItem> colors) {
this.mColors = colors;
}
@NonNull
@Override
public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
View listItem = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
return new CustomViewHolder(listItem);
}
@Override
public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) {
holder.tvColorName.setText(mColors.get(position).getColorName());
}
@Override
public int getItemCount() {
return mColors.size();
}
class CustomViewHolder extends RecyclerView.ViewHolder implements {
TextView tvColorName;
CustomViewHolder(@NonNull View listItem) {
super(listItem);
tvColorName = listItem.findViewById(R.id.tvColorName);
}
}
}
Custom ItemTouchHelper.SimpleCallback
public class ItemSwipeCallback extends ItemTouchHelper.SimpleCallback {
private final List<ColorItem> mColorItems;
private Context mContext;
public interface OnTouchListener {
void onSwiped(RecyclerView.ViewHolder viewHolder, int direction);
}
private OnTouchListener mOnTouchListener;
public ItemSwipeCallback(Context context, List<ColorItem> items, int dragDirs, int swipeDirs, OnTouchListener onTouchListener) {
super(dragDirs, swipeDirs);
mContext = context;
mColorItems = items;
mOnTouchListener = onTouchListener;
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
mOnTouchListener.onSwiped(viewHolder, direction);
}
@Override
public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
// Getting the swiped item
ColorItem item = mColorItems.get(viewHolder.getAdapterPosition());
// Get the color of the swiped item (the thing that differentiates among items)
ColorDrawable background = new ColorDrawable(mContext.getResources().getColor(item.getColorValue()));
// Changing the color of the background item
View itemView = viewHolder.itemView;
int backgroundCornerOffset = 25; //so mBackground is behind the rounded corners of itemView
if (dX > 0) { // Swiping to the right
background.setBounds(itemView.getLeft(), itemView.getTop(),
itemView.getLeft() + ((int) dX) + backgroundCornerOffset, itemView.getBottom());
} else if (dX < 0) { // Swiping to the left
background.setBounds(itemView.getRight() + ((int) dX) - backgroundCornerOffset,
itemView.getTop(), itemView.getRight(), itemView.getBottom());
} else { // view is unSwiped
background.setBounds(0, 0, 0, 0);
}
background.draw(c);
}
}
Activity
public class MainActivity extends AppCompatActivity {
ArrayList<ColorItem> mColors;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mColors = new ArrayList<>();
populateColors();
setupRecyclerView();
}
private void setupRecyclerView() {
RecyclerAdapter adapter = new RecyclerAdapter(this, mColors);
RecyclerView recyclerview = findViewById(R.id.recyclerview);
RecyclerView.LayoutManager layoutMgr = new LinearLayoutManager(getApplicationContext());
recyclerview.setLayoutManager(layoutMgr);
recyclerview.setAdapter(adapter);
ItemTouchHelper helper = new ItemTouchHelper(new ItemSwipeCallback(this, mColors,
0, ItemTouchHelper.RIGHT, new ItemSwipeCallback.OnTouchListener() {
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
// Do something here
}
}));
helper.attachToRecyclerView(recyclerview);
}
private void populateColors() {
mColors.add(new ColorItem("Red", R.color.red));
mColors.add(new ColorItem("White", R.color.white));
mColors.add(new ColorItem("Green", R.color.green));
mColors.add(new ColorItem("Yellow", R.color.yellow));
mColors.add(new ColorItem("Black", R.color.black));
mColors.add(new ColorItem("Red", R.color.red));
mColors.add(new ColorItem("White", R.color.white));
mColors.add(new ColorItem("Green", R.color.green));
mColors.add(new ColorItem("Yellow", R.color.yellow));
mColors.add(new ColorItem("Black", R.color.black));
mColors.add(new ColorItem("Red", R.color.red));
mColors.add(new ColorItem("White", R.color.white));
mColors.add(new ColorItem("Green", R.color.green));
mColors.add(new ColorItem("Yellow", R.color.yellow));
mColors.add(new ColorItem("Black", R.color.black));
}
}