preface
Without further ado, get straight to the picture above:
RecyclerView
ItemTouchHelper
Functions:
- Hold down the
item
The button on the left can be dragged up and downitem
- Swipe to the right to delete
item
item
Drag or side slide to have a shadow effect
Implement basic functions
Step by step learning, here we first implement the basic functions:
- Long press
item
Drag and drop - Swipe to the right to delete
Layout file
Very simple, not to say, directly on the code:
activity_main.xml
<?xml version="1.0" encoding="utf-8"? >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/main_recyclerView"
android:scrollbars="none"
android:background="#F2F8FC">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
Copy the code
item_list.xml
<?xml version="1.0" encoding="utf-8"? >
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#ffffff">
<ImageView
android:id="@+id/item_list_menu_imageView"
android:layout_width="30dp"
android:layout_height="25dp"
android:layout_marginBottom="8dp"
android:layout_marginStart="15dp"
android:layout_marginTop="8dp"
android:src="@drawable/imageview_menu"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/item_list_text_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginStart="15dp"
android:layout_marginTop="8dp"
android:textColor="# 000000"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/item_list_menu_imageView"
app:layout_constraintTop_toTopOf="parent"/>
<android.support.v7.widget.SwitchCompat
android:id="@+id/item_list_switchCompat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="15dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</android.support.constraint.ConstraintLayout>
Copy the code
ItemTouchHelper
Official API explanation:
This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.
This is a tool class for RecyclerView to add sideslip delete and drag. With it, we can easily achieve the above effect. Constructor: ItemTouchHelper(ItemTouchHelper.Callback Callback) we need an ItemTouchHelper.Callback to construct an ItemTouchHelper.
ItemTouchHelper. The Callback provides an implementation class official ItemTouchHelper. SimpleCallback (), its use is very simple, but in order to get higher customization, here we don’t use it, interested friends can go to try.
A new MyItemTouchHelperCallback class inheritance ItemTouchHelper Callback, here we focus on it to one of the three methods:
getMovementFlags()
defineitem
Can drag and slide the direction.onMove()
当item
This method is called when you want to drag and drop.onSwiped
当item
This method is called when you want to sideslip left and right.
We first create a before writing MyItemTouchHelperCallback IItemTouchHelperAdapter interface, let RecyclerViewAdapter implements this interface. Used for RecyclerViewAdapter callbacks.
public interface IItemTouchHelperAdapter {
/** ** is called when the item is moved@paramFromPosition The starting point of the item being manipulated *@paramToPosition Endpoint of the item being operated on */
void onItemMove(int fromPosition, int toPosition);
/** ** is called when item is sideslip@paramPosition Position of the item that is sideswiped */
void onItemDismiss(int position);
}
Copy the code
Implement the two methods you just inherited in RecyclerViewAdapter:
@Override
public void onItemMove(int fromPosition, int toPosition) {
Collections.swap(mList, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
}
@Override
public void onItemDismiss(int position) {
mList.remove(position);
notifyItemRemoved(position);
}
Copy the code
Then we can start to write MyItemTouchHelperCallback, comments clear, not much said.
public class MyItemTouchHelperCallback extends ItemTouchHelper.Callback {
private IItemTouchHelperAdapter mAdapter;
public MyItemTouchHelperCallback(IItemTouchHelperAdapter mAdapter) {
this.mAdapter = mAdapter;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
// Drag up and down, if you have other requirements
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
// Slide to the right, if you have other requirements
int swipeFlags = ItemTouchHelper.RIGHT;
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
// Notify Adapter to update data and views
mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
// If false is returned, dragging and dropping is not supported
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
// Notify Adapter to update data and views
mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}
@Override
public boolean isItemViewSwipeEnabled(a) {
// Whether you can slide left and right, default return true
return true;
}
@Override
public boolean isLongPressDragEnabled(a) {
// Whether you can drag up and down by long pressing, false is returned by default
return true; }}Copy the code
Finally, in Acivity, associate ItemTouchHelper with RecyclerView
mItemTouchHelper = new ItemTouchHelper(new MyItemTouchHelperCallback(adapter));
mItemTouchHelper.attachToRecyclerView(recyclerView);
Copy the code
Operation effect:
perfect
There is still a little gap between the basic effect we have achieved and the effect given at the beginning of the article, and the effect still needs to be achieved:
- By holding down the
item
The left button can only be dragged up and down. - Being operated by sideslip or drag
item
Z-axis height increased, there are distinct shadows.
By holding down theitem
The left button can only be dragged up and down
First modify MyItemTouchHelperCallback isLongPressDragEnabled ()
@Override
public boolean isLongPressDragEnabled(a) {
// Don't drag item up and down, because we want to customize when drag is enabled
return false;
}
Copy the code
Next, create an OnStartDragListener interface for callbacks
public interface OnStartDragListener {
/** * Callback ** when the View needs to be dragged@param viewHolder The holder of view to drag
*/
void onStartDrag(RecyclerView.ViewHolder viewHolder);
}
Copy the code
Let your Activity inherit this class and implement the onStartDrag() method
@Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
// Tell ItemTouchHelper to start dragging
mItemTouchHelper.startDrag(viewHolder);
}
Copy the code
In the RecyclerViewAdapter constructor, pass an instance of OnStartDragListener (that is, the Activity that implements the interface) to add event listeners to the button to the left of the Item
public class RecyclerViewAdapter extends
RecyclerView.Adapter<RecyclerViewAdapter.ItemViewHolder> implements IItemTouchHelperAdapter {
// constructor
public RecyclerViewAdapter(List<ItemEntity> list, OnStartDragListener mDragListener) {
mList = list;
this.mDragListener = mDragListener; }...@Override
public void onBindViewHolder(final IItemViewHolder holder, @SuppressLint("RecyclerView") final int position) {... holder.menu.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction()
== MotionEvent.ACTION_DOWN) {
// Tell ItemTouchHelper to start dragging
mDragListener.onStartDrag(holder);
}
return false; }}); }... }Copy the code
Being operated by sideslip or dragitem
Z-axis height increased, there are distinct shadows
To achieve this effect, we use two Callback methods provided by ItemTouchHelper.Callback:
onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState)
: whenViewHolder
(i.e.item
) is called when sliding or dragging.clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
: whenViewHolder
Is called when the slide and drag end
First create a new IItemTouchHelperViewHolder interface for callback, let RecyclerViewAdapter ViewHolder inherit it.
public interface IItemTouchHelperViewHolder {
/** * item is selected to update the status */ during sideslip or drag
void onItemSelected(a);
/** * The drag and slide of item ends, and the default state */ is restored
void onItemClear(a);
}
Copy the code
Then let ViewHolder override the above two methods:
class ItemViewHolder extends RecyclerView.ViewHolder implements IItemTouchHelperViewHolder {
private TextView text;
private ImageView menu;
private SwitchCompat switchCompat;
ItemViewHolder(View itemView) {
super(itemView);
text = itemView.findViewById(R.id.item_list_text_textView);
menu = itemView.findViewById(R.id.item_list_menu_imageView);
switchCompat = itemView.findViewById(R.id.item_list_switchCompat);
}
@Override
public void onItemSelected(a) {
itemView.setTranslationZ(10);
}
@Override
public void onItemClear(a) {
itemView.setTranslationZ(0); }}Copy the code
Here we change the height of the itemView by setTranslationZ().
I tried to change the height of the View by using setElevation(), but it didn’t work.
elevation
Is a static value, yesView
The initial value on the Z axistranslationZ
Is the dynamic value, is the shift on Z
So instead of using setElevation(), we should use setTranslationZ() to change the height of the View’s Z-axis. You can try it out for yourself.
Last modified MyItemTouchHelperCallback, rewrite the above two methods, the process is simple, direct look at the code:
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
if(actionState ! = ItemTouchHelper.ACTION_STATE_IDLE) {// No idle state, i.e. drag or slide state
if (viewHolder instanceofIItemTouchHelperViewHolder) { IItemTouchHelperViewHolder itemTouchHelperViewHolder = (IItemTouchHelperViewHolder) viewHolder; itemTouchHelperViewHolder.onItemSelected(); }}super.onSelectedChanged(viewHolder, actionState);
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
if (viewHolder instanceofIItemTouchHelperViewHolder) { IItemTouchHelperViewHolder itemTouchHelperViewHolder = (IItemTouchHelperViewHolder) viewHolder; itemTouchHelperViewHolder.onItemClear(); }}Copy the code
The last
Here is [source]
Feel free to leave me a comment in the comments section if there are any mistakes or areas that could be improved