RecyclerView系列之三:使用ItemTouchHelper实现RecyclerView的条目交互特效

来源:互联网 发布:数据安全管理方案 编辑:程序博客网 时间:2024/04/29 18:28
  • 文章目录
  1. 效果图
  2. ItemTouchHelper类解析和主要调用方法介绍
  3. 代码实现

  • ItemTouchHelper类介绍:该类主要用于支持RecyclerView添加侧滑和拖拽特效的辅助类,虽然是辅助类,但该类本身却是不工作的,只作为中间类,联系RecyclerView和ItemTouchHelper.Callback这两个真正工作的类.
  1. 问题一:ItemTouchHelp怎么与RecyclerView怎么联系?->itemTouchHelper.attachToRecyclerView(recyclerView)在该方法中实现
    1. //看人家的代码写的多风骚
    2. public void attachToRecyclerView(@Nullable RecyclerView recyclerView) {
    3. if (mRecyclerView == recyclerView) {
    4. return; // nothing to do
    5. }
    6. if (mRecyclerView != null) {
    7. destroyCallbacks();
    8. }
    9. mRecyclerView = recyclerView;
    10. if (mRecyclerView != null) {
    11. final Resources resources = recyclerView.getResources();
    12. mSwipeEscapeVelocity = resources
    13. .getDimension(R.dimen.item_touch_helper_swipe_escape_velocity);
    14. mMaxSwipeVelocity = resources
    15. .getDimension(R.dimen.item_touch_helper_swipe_escape_max_velocity);
    16. setupCallbacks();
    17. }
    18. }
  2. 问题二:真正工作的Callback类怎么起作用?->在ItemTouchHelper构造函数中传入.
    1. public class ItemTouchHelper extends RecyclerView.ItemDecoration
    2. implements RecyclerView.OnChildAttachStateChangeListener {
    3. //构造函数
    4. public ItemTouchHelper(Callback callback) {
    5. mCallback = callback;
    6. }
    7. }
  3. 问题三:实现自己的CallBack并与RecyclerView联系起来->因为我们的拖拽和侧滑的动作都是在RecyclerView的适配器中进行,所有我们需要将自己实现的CallBack类和RecyclerView的Adapter通过接口关联起来
  4. 触摸接口主要定义两个方法:分别是长安拖拽和左右侧滑
    1. public interface ItemTouchListener {
    2. /**
    3. * 左右滑动时,adapter回调该方法去删除该位置的item
    4. * @param position
    5. */
    6. boolean onItemRemove(int position);
    7. /**
    8. * 上下拖拽时回调方法,adpater将两个位置的item调换位置
    9. * @param desPos
    10. * @param targetPos
    11. */
    12. boolean onItemMoved(int desPos,int targetPos);
    13. }
  5. 让Adapter适配器实现触摸接口,而接口回调在CallBack实现类中处理
    1. public class InteractiveAdapter extends RecyclerView.Adapter<InteractiveAdapter.InteractiveViewHolder> implements ItemTouchListener {
    2. private final ItemDragListener mDragListener;
    3. private final Context mContext;
    4. private List<String> mData;
    5. public InteractiveAdapter(Context context, ItemDragListener listener) {
    6. this.mContext = context;
    7. this.mDragListener = listener;
    8. mData = new ArrayList<>();
    9. }
    10. public void setData(List<String> datas) {
    11. this.mData = datas;
    12. }
    13. private List<String> getRealDatas() {
    14. return mData;
    15. }
    16. @Override
    17. public InteractiveViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    18. LayoutInflater inflater = LayoutInflater.from(mContext);
    19. View itemView = inflater.inflate(R.layout.item_interactive, parent, false);
    20. return new InteractiveViewHolder(itemView);
    21. }
    22. @Override
    23. public void onBindViewHolder(final InteractiveViewHolder holder, int position) {
    24. String data = mData.get(position);
    25. holder.name.setText(data);
    26. holder.logo.setOnTouchListener(new View.OnTouchListener() {
    27. @Override
    28. public boolean onTouch(View v, MotionEvent event) {
    29. if (event.getAction() == MotionEvent.ACTION_DOWN) {
    30. if (mDragListener != null) {
    31. mDragListener.onItemDrag(holder);
    32. }
    33. }
    34. return false;
    35. }
    36. });
    37. }
    38. @Override
    39. public int getItemCount() {
    40. return mData.size();
    41. }
    42. public class InteractiveViewHolder extends RecyclerView.ViewHolder {
    43. private final ImageView logo;
    44. private final TextView name;
    45. public InteractiveViewHolder(View itemView) {
    46. super(itemView);
    47. logo = (ImageView) itemView.findViewById(R.id.iv_logo);
    48. name = (TextView) itemView.findViewById(R.id.tv_name);
    49. }
    50. }
    51. @Override
    52. public boolean onItemRemove(int position) {
    53. getRealDatas().remove(position);
    54. notifyItemRemoved(position);
    55. return true;
    56. }
    57. @Override
    58. public boolean onItemMoved(int desPos, int targetPos) {
    59. Collections.swap(getRealDatas(), desPos, targetPos);
    60. notifyItemMoved(desPos, targetPos);
    61. return true;
    62. }
    63. }
  6. 实现自己的CallBack类,并进行方法解析
    1. public class MyItemTouchHelpCallback extends ItemTouchHelper.Callback {
    2. private final java.lang.String TAG = this.getClass().getSimpleName();
    3. private final ItemTouchListener mItemTouchListener;
    4. public MyItemTouchHelpCallback(ItemTouchListener listener) {
    5. this.mItemTouchListener = listener;
    6. }
    7. /**
    8. * 该方法主要用于设置事件的方向:上下拖拽和左右滑动
    9. *
    10. * @param recyclerView
    11. * @param viewHolder
    12. * @return
    13. */
    14. @Override
    15. public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    16. Logger.d(TAG, "getMovementFlags");
    17. int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;//拖拽方向:上下
    18. int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;//滑动方向:左右
    19. return makeMovementFlags(dragFlags, swipeFlags);
    20. }
    21. /**
    22. * 是否支持item左右滑动功能
    23. *
    24. * @return
    25. */
    26. @Override
    27. public boolean isItemViewSwipeEnabled() {
    28. return true;
    29. }
    30. /**
    31. * 是否支持item长按拖拽功能
    32. *
    33. * @return
    34. */
    35. @Override
    36. public boolean isLongPressDragEnabled() {
    37. return true;
    38. }
    39. /**
    40. * item拖拽回调的方法
    41. *
    42. * @param recyclerView
    43. * @param viewHolder
    44. * @param target
    45. * @return
    46. */
    47. @Override
    48. public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    49. Logger.d(TAG, "onMove");
    50. return mItemTouchListener.onItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
    51. }
    52. /**
    53. * recyclerview滑动时,会调用该方法-》设置接口,让接口的实现类去真是处理
    54. *
    55. * @param viewHolder
    56. * @param direction 滑动方向,可以判断是向左滑动还是向右
    57. */
    58. @Override
    59. public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
    60. Logger.d(TAG, "onSwiped");
    61. mItemTouchListener.onItemRemove(viewHolder.getAdapterPosition());
    62. }
    63. /**
    64. * item左右滑动时,改变item的样式
    65. *
    66. * @param c
    67. * @param recyclerView
    68. * @param viewHolder
    69. * @param dX
    70. * @param dY
    71. * @param actionState
    72. * @param isCurrentlyActive
    73. */
    74. @Override
    75. public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
    76. Logger.d("dx:" + dX + " -dy:" + dY);
    77. if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
    78. float scale = 1 - (Math.abs(dX) / viewHolder.itemView.getWidth());// 1-0
    79. viewHolder.itemView.setScaleX(scale);
    80. viewHolder.itemView.setScaleY(scale);
    81. viewHolder.itemView.setAlpha(scale);
    82. }
    83. super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    84. }
    85. /**
    86. * 当item拖拽或滑动时调用
    87. *
    88. * @param viewHolder
    89. * @param actionState
    90. */
    91. @Override
    92. public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
    93. Logger.d("actionState:" + actionState);
    94. //当item拽或滑动时改变item的背景-->放开时,item背景恢复
    95. if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
    96. viewHolder.itemView.setBackgroundColor(Color.GRAY);
    97. }
    98. super.onSelectedChanged(viewHolder, actionState);
    99. }
    100. @Override
    101. public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    102. viewHolder.itemView.setBackgroundColor(Color.WHITE);
    103. //处理item布局复用问题
    104. viewHolder.itemView.setScaleX(1.0f);
    105. viewHolder.itemView.setScaleY(1.0f);
    106. viewHolder.itemView.setAlpha(1.0f);
    107. super.clearView(recyclerView, viewHolder);
    108. }
    109. }
  7. ItemTouchHelper.Callback方法解析:
  • getMovementFlags():获取条目的运动方向标示->在该方法中通过位运算与和makeMovementFlags方法获取,并返回.
  • isItemViewSwipeEnabled():是否允许条目左右滑动->放回true表示允许
  • ieLongPressDragEnable():是否运行长按拖拽功能->返回true
  • onMove():条目拖拽时调用
  • onSwiped():条目滑动时调用->接口回调
  • onChildDraw():当条目左右滑动时,可以通过该方法为条目设置样式进行重新绘制
  • onSelectedChanged():条目选中时调用
  • clearView():条目滑动完或者拖拽完会调用的方法->可在该方法中进行样式的处理->界面重新绘制

  • itemTouchHelper类实现拖拽效果:通过调用方法ItemTouchHelper.startDrag(ViewHolder )->也是通过接口和RecyclerView的适配器关联起来
  • Activiey的代码
    1. public class InteractiveRecyclerView extends BaseActivity implements ItemDragListener {
    2. @Bind(R.id.rv_recycleView)
    3. RecyclerView mRecyclerView;
    4. private InteractiveAdapter adapter;
    5. private ItemTouchHelper touchHelper;
    6. private List<String> datas;
    7. @Override
    8. protected void onCreate(Bundle savedInstanceState) {
    9. super.onCreate(savedInstanceState);
    10. setContentView(R.layout.activity_interactive_recycler);
    11. ButterKnife.bind(this);
    12. initToolBar();
    13. initRecyclerView();
    14. }
    15. private void initRecyclerView() {
    16. datas = new ArrayList<>();
    17. for (int i = 0; i < 21; ) {
    18. datas.add("Item" + ++i);
    19. }
    20. mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
    21. adapter = new InteractiveAdapter(this, this);
    22. adapter.setData(datas);
    23. mRecyclerView.setAdapter(adapter);
    24. //条目触摸辅助类
    25. ItemTouchHelper.Callback callBack = new MyItemTouchHelpCallback(adapter);
    26. touchHelper = new ItemTouchHelper(callBack);
    27. touchHelper.attachToRecyclerView(mRecyclerView);
    28. }
    29. @Override
    30. protected void onDestroy() {
    31. super.onDestroy();
    32. ButterKnife.unbind(this);
    33. }
    34. /**
    35. * Adapter中logo设置了拖拽监听,让ItemTouchHelper去处理
    36. *
    37. * @param viewHolder
    38. */
    39. @Override
    40. public void onItemDrag(RecyclerView.ViewHolder viewHolder) {
    41. touchHelper.startDrag(viewHolder);
    42. }
    43. }
    1. public interface ItemDragListener {
    2. void onItemDrag(RecyclerView.ViewHolder viewHolder);
    3. }
0 0
原创粉丝点击