RecyclerView implements sliding deletion and dragging functions

RecyclerView implements sliding deletion and dragging functions

[[185238]]

Preface

Starting from Android 5.0, Google launched a new control RecyclerView. Compared with the earlier ListView, it has many advantages and powerful functions. It also provides great convenience for our developers. Today, I will learn how to easily achieve the effects of sliding deletion and dragging with RecyclerView, as shown in the figure below.

I believe that students who have studied RecyclerView should know very well how to achieve such an effect. If using ListView, such an effect may be a bit troublesome to achieve, but in front of the powerful RecyclerView, such an effect only requires very little code, because Google provides us with a powerful tool class ItemTouchHelper, which has handled the implementation of RecyclerView dragging and sliding, and we can implement our own animations in it, as well as customize the effects we want.

ItemTouchHelper.Callback has several important abstract methods. We inherit this abstract class and override the abstract methods. It is an important callback for us to implement sliding and dragging.

  1. int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)

This method returns an integer that specifies the direction in which dragging and sliding are allowed. Use makeMovementFlags(int dragFlags, int swipeFlags) to return. The first parameter of this method is used to specify dragging, and the second parameter is used to specify sliding. There are 6 direction parameters

  1. ItemTouchHelper.UP //Slide and drag upward
  2.  
  3. ItemTouchHelper.DOWN //Down
  4.  
  5. ItemTouchHelper.LEFT // Left
  6.  
  7. ItemTouchHelper.RIGHT // right
  8.  
  9. ItemTouchHelper.START // Depends on the horizontal start direction of the layout direction
  10.  
  11. ItemTouchHelper.END //Horizontal end direction dependent on layout direction
  1. boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)

The onMove method is the callback of dragging. The parameter viewHolder is the dragged Item, and target is the Item at the target position of the drag. If this method returns true, it means the position has been switched, otherwise it returns false.

  1. void onSwiped(RecyclerView.ViewHolder viewHolder, int direction)

The onSwiped method is the Item sliding callback, viewHolder is the sliding item, and direction is the sliding direction.

The above three methods are the methods that must be rewritten, of course there are some other optional methods.

  1. /**
  2.  
  3. * Whether the item supports long press and drag
  4.  
  5. *
  6.  
  7. * @return  
  8.  
  9. * true to support long press operation
  10.  
  11. * false does not support long press operation
  12.  
  13. */
  14.  
  15. oolean isLongPressDragEnabled()
  16.  
  17.  
  18.  
  19. /**
  20.  
  21. * Whether the item supports sliding
  22.  
  23. *
  24.  
  25. * @return  
  26.  
  27. * true supports sliding operation
  28.  
  29. * false does not support sliding operation
  30.  
  31. */
  32.  
  33. oolean isItemViewSwipeEnabled()
  34.  
  35.  
  36.  
  37. /**
  38.  
  39. * Draw Item during movement
  40.  
  41. *
  42.  
  43. * @param c
  44.  
  45. * @param recyclerView
  46.  
  47. * @param viewHolder
  48.  
  49. * @param dX
  50.  
  51. * X-axis moving distance
  52.  
  53. * @param dY
  54.  
  55. * Y axis movement distance
  56.  
  57. * @param actionState
  58.  
  59. * The current item status
  60.  
  61. * @param isCurrentlyActive
  62.  
  63. * If the current user operation is true , otherwise it is false  
  64.  
  65. */
  66.  
  67. nChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive)

It should be noted that if we want to implement dragging or sliding, we must return true to the method above to determine whether dragging or sliding is supported, otherwise the onMove or onSwiped method will not be executed.

Functionality

  1. adapter=new CustomAdapter(getActivity(),strings);
  2.  
  3. recycleview.setAdapter(adapter);
  4.  
  5. ItemTouchHelper.Callback callback=new RecycleItemTouchHelper(adapter);
  6.  
  7. ItemTouchHelper itemTouchHelper=new ItemTouchHelper(callback);
  8.  
  9. itemTouchHelper.attachToRecyclerView(recycleview);

The ItemTouchHelper construction method receives an ItemTouchHelper.Callback parameter, and this Callback is the tool class we mentioned above. After initializing ItemTouchHelper, we associate our implemented ItemTouchHelper.Callback with RecyclerView through its attachToRecyclerView(@Nullable RecyclerView recyclerView) method to achieve our desired effect. The code looks very simple, right? Next, let's take a look at our custom Callback.

  1. package com.example.xh.adapter;
  2.  
  3.   
  4.  
  5. import android.content.res.Resources;
  6.  
  7. import android.graphics.Bitmap;
  8.  
  9. import android.graphics.BitmapFactory;
  10.  
  11. import android.graphics.Canvas;
  12.  
  13. import android.graphics.Paint;
  14.  
  15. import android.graphics.Rect;
  16.  
  17. import android.support.v7.widget.RecyclerView;
  18.  
  19. import android.support.v7.widget.helper.ItemTouchHelper;
  20.  
  21. import android.util.Log;
  22.  
  23. import android. view . View ;
  24.  
  25.   
  26.  
  27. import com.example.xh.R;
  28.  
  29. import com.example.xh.utils.MyApplication;
  30.  
  31.   
  32.  
  33. /**
  34.  
  35. * Created by xiehui on 2017/2/23.
  36.  
  37. */
  38.  
  39. public class RecycleItemTouchHelper extends ItemTouchHelper.Callback{
  40.  
  41. private static final String TAG = "RecycleItemTouchHelper" ;
  42.  
  43. private final ItemTouchHelperCallback helperCallback;
  44.  
  45.   
  46.  
  47. public RecycleItemTouchHelper(ItemTouchHelperCallback helperCallback) {
  48.  
  49. this.helperCallback = helperCallback;
  50.  
  51. }
  52.  
  53.   
  54.  
  55. /**
  56.  
  57. * Set the slide type flag
  58.  
  59. *
  60.  
  61. * @param recyclerView
  62.  
  63. * @param viewHolder
  64.  
  65. * @return  
  66.  
  67. * Returns an integer type flag to determine whether the item's movement behavior is allowed
  68.  
  69. */
  70.  
  71. @Override
  72.  
  73. public   int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
  74.  
  75. Log.e(TAG, "getMovementFlags: " );
  76.  
  77. //START right to leftEND left to rightLEFT leftRIGHT right UP up
  78.  
  79. //If a value is passed as 0, it means that the operation is not triggered. The number of settings supports dragging up and down, and supports sliding to the right
  80.  
  81. return makeMovementFlags(ItemTouchHelper.UP|ItemTouchHelper.DOWN,ItemTouchHelper. END );
  82.  
  83. }
  84.  
  85. /**
  86.  
  87. * Whether the item supports long press and drag
  88.  
  89. *
  90.  
  91. * @return  
  92.  
  93. * true to support long press operation
  94.  
  95. * false does not support long press operation
  96.  
  97. */
  98.  
  99. @Override
  100.  
  101. public boolean isLongPressDragEnabled() {
  102.  
  103. return super.isLongPressDragEnabled();
  104.  
  105. }
  106.  
  107. /**
  108.  
  109. * Whether the item supports sliding
  110.  
  111. *
  112.  
  113. * @return  
  114.  
  115. * true supports sliding operation
  116.  
  117. * false does not support sliding operation
  118.  
  119. */
  120.  
  121. @Override
  122.  
  123. public boolean isItemViewSwipeEnabled() {
  124.  
  125. return super.isItemViewSwipeEnabled();
  126.  
  127. }
  128.  
  129. /**
  130.  
  131. * Drag and switch Item callback
  132.  
  133. *
  134.  
  135. * @param recyclerView
  136.  
  137. * @param viewHolder
  138.  
  139. * @param target
  140.  
  141. * @return  
  142.  
  143. * If the item changes position, return true ; otherwise, return false  
  144.  
  145. */
  146.  
  147. @Override
  148.  
  149. public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
  150.  
  151. Log.e(TAG, "onMove: " );
  152.  
  153. helperCallback.onMove(viewHolder.getAdapterPosition(),target.getAdapterPosition());
  154.  
  155. return   true ;
  156.  
  157. }
  158.  
  159. /**
  160.  
  161. * Slide Item
  162.  
  163. *
  164.  
  165. * @param viewHolder
  166.  
  167. * @param direction
  168.  
  169. * The direction in which the item slides
  170.  
  171. */
  172.  
  173. @Override
  174.  
  175. public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
  176.  
  177. Log.e(TAG, "onSwiped: " );
  178.  
  179. helperCallback.onItemDelete(viewHolder.getAdapterPosition());
  180.  
  181. }
  182.  
  183. /**
  184.  
  185. * Callback when Item is selected
  186.  
  187. *
  188.  
  189. * @param viewHolder
  190.  
  191. * @param actionState
  192.  
  193. * The current item status
  194.  
  195. * ItemTouchHelper.ACTION_STATE_IDLE idle state
  196.  
  197. * ItemTouchHelper.ACTION_STATE_SWIPE Sliding state
  198.  
  199. * ItemTouchHelper#ACTION_STATE_DRAG dragging state
  200.  
  201. */
  202.  
  203. @Override
  204.  
  205. public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
  206.  
  207. super.onSelectedChanged(viewHolder, actionState);
  208.  
  209. }
  210.  
  211. public interface ItemTouchHelperCallback{
  212.  
  213. void onItemDelete( int positon);
  214.  
  215. void onMove( int fromPosition, int toPosition);
  216.  
  217. }
  218.  
  219. }

By default, dragging and sliding are supported, that is, isLongPressDragEnabled() and isItemViewSwipeEnabled() return true. In this class, we create an interface ItemTouchHelperCallback and create two abstract methods, representing dragging and sliding respectively. In the onMove method, we call back to create the interface method interface onMove(int fromPosition, int toPosition) we created, and pass in the drag and Item's posion and target posion. The posion is obtained through ViewHolder's getAdapterPosition(), and then the onItemDelete(int position) is called back in the sliding callback method onSwiped. At this point, our custom ItemTouchHelper.Callback is created.

After completing the above, we only need to implement the RecycleItemTouchHelper.ItemTouchHelperCallback interface in our custom Adapter, and then update the interface in the callback method, as shown in the callback method implementation in Apdater below.

  1. @Override
  2.  
  3. public void onItemDelete( int positon) {
  4.  
  5. list.remove(positon);
  6.  
  7. notifyItemRemoved(positon);
  8.  
  9. }
  10.  
  11.  
  12.  
  13. @Override
  14.  
  15. public void onMove( int fromPosition, int toPosition) {
  16.  
  17. Collections.swap(list,fromPosition,toPosition);//Exchange data
  18.  
  19. notifyItemMoved(fromPosition,toPosition);
  20.  
  21. }

We delete the corresponding posion data in the onItemDelete method, exchange the corresponding item data through the Collections.swap method in the onMove method, and then call notifyItemRemoved and notifyItemMoved respectively to update the UI through the adapter.

Well, the function has been implemented here. Did you find that there are very few codes? Of course, it is just more verbose.

Functional upgrade

Through the implementation of the simple code above, you can already slide to delete and drag. Of course, you may find that there is no animation and no background when sliding to delete. But I want to change the background and a delete icon will appear during the sliding process to give users feedback and let them know that the operation is to delete data. Of course, you will also want to add an animation during the deletion process. In fact, it is not very troublesome to achieve this effect. Next, a new method will be implemented. Oh, no, it was mentioned before.

  1. onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, fl

This method is the callback for drawing the Item during the movement process. When actionState==ItemTouchHelper.ACTION_STATE_SWIPE, we draw the background and delete the image when sliding.

initialization

  1. /**
  2.  
  3. * Draw Item during movement
  4.  
  5. *
  6.  
  7. * @param c
  8.  
  9. * @param recyclerView
  10.  
  11. * @param viewHolder
  12.  
  13. * @param dX
  14.  
  15. * X-axis moving distance
  16.  
  17. * @param dY
  18.  
  19. * Y axis movement distance
  20.  
  21. * @param actionState
  22.  
  23. * The current item status
  24.  
  25. * @param isCurrentlyActive
  26.  
  27. * If the current user operation is true , otherwise it is false  
  28.  
  29. */
  30.  
  31. @Override
  32.  
  33. public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
  34.  
  35. //Implement the background and pictures by yourself when sliding
  36.  
  37. if (actionState==ItemTouchHelper.ACTION_STATE_SWIPE){
  38.  
  39.  
  40.  
  41. //When dX is greater than 0, slide to the right, and when dX is less than 0, slide to the left
  42.  
  43. View itemView=viewHolder.itemView; //Get the sliding view  
  44.  
  45. Resources resources= MyApplication.getAppContext().getResources();
  46.  
  47. Bitmap bitmap = BitmapFactory.decodeResource(resources, R.drawable. delete ); //Get the background image of the deletion instruction
  48.  
  49. int padding =10; //padding for drawing the image
  50.  
  51. int maxDrawWidth=2*padding+bitmap.getWidth(); //*** drawing width
  52.  
  53. Paint paint=new Paint();
  54.  
  55. paint.setColor(resources.getColor(R.color.btninvalid));
  56.  
  57. int x=Math.round(Math. abs (dX));
  58.  
  59. int drawWidth = Math.min ( x, maxDrawWidth); //Actual drawing width, take the minimum value of real-time sliding distance x and maximum drawing distance maxDrawWidth
  60.  
  61. int itemTop=itemView.getBottom()-itemView.getHeight(); //Draw the top position
  62.  
  63. //Slide to the right
  64.  
  65. if(dX>0){
  66.  
  67. //Draw a background in real time based on sliding
  68.  
  69. c.drawRect(itemView.getLeft(),itemTop,drawWidth,itemView.getBottom(),paint);
  70.  
  71. // Draw the image on the background
  72.  
  73. if (x>padding){//Start drawing the image when the sliding distance is greater than padding
  74.  
  75. //Specify the location where the picture is drawn
  76.  
  77. Rect rect=new Rect(); //Drawing location
  78.  
  79. rect.left =itemView.getLeft()+padding;
  80.  
  81. rect.top =itemTop+(itemView.getBottom()-itemTop-bitmap.getHeight())/2;//Center the image
  82.  
  83. int maxRight=rect.left + bitmap.getWidth();
  84.  
  85. rect. right =Math. min (x,maxRight);
  86.  
  87. rect.bottom= rect.top +bitmap.getHeight();
  88.  
  89. //Specify the drawing area of ​​the image
  90.  
  91. Rect rect1= null ;
  92.  
  93. if (x

After the above processing, we can see our customized blue and low deletion background by sliding. At this time, we may still have doubts whether this deletion is very abrupt. Then add a transparency animation to it, as shown below.

  1. float alpha = 1.0f - Math. abs (dX) / ( float ) itemView.getWidth();
  2.  
  3. itemView.setAlpha(alpha);

Well, here we have introduced the sliding deletion and dragging functions of RecyclerView. If you have any questions, please leave a message. Have a wonderful day.

Source code portal

  • https://github.com/xiehui999/fuseProgram

<<:  Are you ready for an in-depth look at Android 7.0?

>>:  UI operations in the main thread are not absolutely safe

Recommend

Humans tried to teach AI how to make a little sun, and the result was -

Recently, there was a big news in the field of nu...

How to quickly increase followers on Xiaohongshu?

Today I want to talk about a hot topic, as the ti...

How to write the title copy for Tik Tok? 6 Tik Tok title copywriting tips

For a short video to have the potential to become...

A complete summary of the offline event planning process!

For advertisers, offline event planning is no str...

How did 100,000 yuan get 937 orders?

The author of this article is Liu Shuopei, deputy...

Zhang Chaoyang: TV series are still the "staple food" of Sohu Video

January 30 (Reporter Zhang Zhichang) After the fu...