在本教程中,我们将讨论并在我们的Android应用程序中实现RecclerView上的Swipe to Delete功能。
安卓刷卡删除
滑动删除功能通常用于从RecillerView中删除行。为了实现刷卡删除功能,我们需要使用ItemTouchHelper实用程序类。
ItemTouchHelper.Callback
为了使用ItemTouchHelper类,我们需要实现ItemTouchHelper.Callback
。ItemTouchHelper.Callback
类主要用于拖放和滑动删除行为。在本教程中,我们将只使用滑动来删除。安卓框架为我们提供了ItemTouchHelper.Callback
的基本实现,即SimpleCallback.我们将创建我们自己的滑动删除功能的实现。以下是我们的类中需要重写的主要方法:getMovementFlags
-在这里我们设置了滑动的方向。我们在静态方法make MovementFlags
中返回方向标志。onMove
-用于拖放。如果不需要,则在此处返回FALSE。onSwiped
-当检测到刷屏动作时触发。一次完整的滑动可以达到整个屏幕的宽度。为了设置将部分滑动视为滑动,我们需要重写以下方法:getSwipeThreshold
-这里我们返回浮点值。示例0.5F表示,RecclerView行上50%的滑动将被视为滑动。onChildDraw
-在这里,我们将创建显示正在进行滑动的自定义视图。
ItemTouchHelper.Callback用于只刷行。它不会自己删除它们。我们将需要使用RecclerView适配器自行删除它。
说够了。让我们来编码吧。在下一节中,我们将创建我们的Android应用程序,其中包含一个包含Swipe to Dismit功能的Reccle View。我们将提供一个带有撤消选项的Snackbar。
项目结构
1implementation 'com.android.support:design:28.0.0-rc01'
代码
Active_main.xml布局的代码如下所示:
1<?xml version="1.0" encoding="utf-8"?>
2<android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android"
3 xmlns:app="https://schemas.android.com/apk/res-auto"
4 xmlns:tools="https://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:id="@+id/coordinatorLayout"
7 android:layout_height="match_parent"
8 tools:context=".MainActivity">
9
10 <RelativeLayout
11 android:layout_width="match_parent"
12 android:layout_height="match_parent">
13
14 <android.support.v7.widget.RecyclerView
15 android:id="@+id/recyclerView"
16 android:layout_width="match_parent"
17 android:layout_height="wrap_content"
18 android:orientation="vertical"
19 app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
20
21 </RelativeLayout>
22
23</android.support.design.widget.CoordinatorLayout>
扩展ItemTouchHelper.Callback类的SwipeToDeleteCallback.java
类代码如下:
1package com.journaldev.androidrecyclerviewswipetodelete;
2
3import android.content.Context;
4import android.graphics.Canvas;
5import android.graphics.Color;
6import android.graphics.Paint;
7import android.graphics.PorterDuff;
8import android.graphics.PorterDuffXfermode;
9import android.graphics.drawable.ColorDrawable;
10import android.graphics.drawable.Drawable;
11import android.support.annotation.NonNull;
12import android.support.v4.content.ContextCompat;
13import android.support.v7.widget.RecyclerView;
14import android.support.v7.widget.helper.ItemTouchHelper;
15import android.view.View;
16
17abstract public class SwipeToDeleteCallback extends ItemTouchHelper.Callback {
18
19 Context mContext;
20 private Paint mClearPaint;
21 private ColorDrawable mBackground;
22 private int backgroundColor;
23 private Drawable deleteDrawable;
24 private int intrinsicWidth;
25 private int intrinsicHeight;
26
27 SwipeToDeleteCallback(Context context) {
28 mContext = context;
29 mBackground = new ColorDrawable();
30 backgroundColor = Color.parseColor("#b80f0a");
31 mClearPaint = new Paint();
32 mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
33 deleteDrawable = ContextCompat.getDrawable(mContext, R.drawable.ic_delete);
34 intrinsicWidth = deleteDrawable.getIntrinsicWidth();
35 intrinsicHeight = deleteDrawable.getIntrinsicHeight();
36
37 }
38
39 @Override
40 public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
41 return makeMovementFlags(0, ItemTouchHelper.LEFT);
42 }
43
44 @Override
45 public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) {
46 return false;
47 }
48
49 @Override
50 public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
51 super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
52
53 View itemView = viewHolder.itemView;
54 int itemHeight = itemView.getHeight();
55
56 boolean isCancelled = dX == 0 && !isCurrentlyActive;
57
58 if (isCancelled) {
59 clearCanvas(c, itemView.getRight() + dX, (float) itemView.getTop(), (float) itemView.getRight(), (float) itemView.getBottom());
60 super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
61 return;
62 }
63
64 mBackground.setColor(backgroundColor);
65 mBackground.setBounds(itemView.getRight() + (int) dX, itemView.getTop(), itemView.getRight(), itemView.getBottom());
66 mBackground.draw(c);
67
68 int deleteIconTop = itemView.getTop() + (itemHeight - intrinsicHeight) / 2;
69 int deleteIconMargin = (itemHeight - intrinsicHeight) / 2;
70 int deleteIconLeft = itemView.getRight() - deleteIconMargin - intrinsicWidth;
71 int deleteIconRight = itemView.getRight() - deleteIconMargin;
72 int deleteIconBottom = deleteIconTop + intrinsicHeight;
73
74 deleteDrawable.setBounds(deleteIconLeft, deleteIconTop, deleteIconRight, deleteIconBottom);
75 deleteDrawable.draw(c);
76
77 super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
78
79 }
80
81 private void clearCanvas(Canvas c, Float left, Float top, Float right, Float bottom) {
82 c.drawRect(left, top, right, bottom, mClearPaint);
83
84 }
85
86 @Override
87 public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {
88 return 0.7f;
89 }
90}
这个类是抽象的,因为我们还没有实现Onwipe方法。我们将在MainActivity.Java类中完成这项工作。在onChildDraw
方法中,我们使用isCancated布尔值检查是否完成了滑动。在此基础上,我们创建了一个带有删除图标的视图。我们已将刷卡阈值设置为0.7。这意味着,如果行的刷取率低于70%,则不会触发Onwipe方法。MainActivity.Java类的代码如下所示:
1package com.journaldev.androidrecyclerviewswipetodelete;
2
3import android.graphics.Color;
4import android.os.Bundle;
5import android.support.annotation.NonNull;
6import android.support.design.widget.CoordinatorLayout;
7import android.support.design.widget.Snackbar;
8import android.support.v7.app.AppCompatActivity;
9import android.support.v7.widget.RecyclerView;
10import android.support.v7.widget.helper.ItemTouchHelper;
11import android.view.View;
12
13import java.util.ArrayList;
14
15public class MainActivity extends AppCompatActivity {
16
17 RecyclerView recyclerView;
18 RecyclerViewAdapter mAdapter;
19 ArrayList<String> stringArrayList = new ArrayList<>();
20 CoordinatorLayout coordinatorLayout;
21
22 @Override
23 protected void onCreate(Bundle savedInstanceState) {
24 super.onCreate(savedInstanceState);
25 setContentView(R.layout.activity_main);
26
27 recyclerView = findViewById(R.id.recyclerView);
28 coordinatorLayout = findViewById(R.id.coordinatorLayout);
29
30 populateRecyclerView();
31 enableSwipeToDeleteAndUndo();
32
33 }
34
35 private void populateRecyclerView() {
36 stringArrayList.add("Item 1");
37 stringArrayList.add("Item 2");
38 stringArrayList.add("Item 3");
39 stringArrayList.add("Item 4");
40 stringArrayList.add("Item 5");
41 stringArrayList.add("Item 6");
42 stringArrayList.add("Item 7");
43 stringArrayList.add("Item 8");
44 stringArrayList.add("Item 9");
45 stringArrayList.add("Item 10");
46
47 mAdapter = new RecyclerViewAdapter(stringArrayList);
48 recyclerView.setAdapter(mAdapter);
49
50 }
51
52 private void enableSwipeToDeleteAndUndo() {
53 SwipeToDeleteCallback swipeToDeleteCallback = new SwipeToDeleteCallback(this) {
54 @Override
55 public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
56
57 final int position = viewHolder.getAdapterPosition();
58 final String item = mAdapter.getData().get(position);
59
60 mAdapter.removeItem(position);
61
62 Snackbar snackbar = Snackbar
63 .make(coordinatorLayout, "Item was removed from the list.", Snackbar.LENGTH_LONG);
64 snackbar.setAction("UNDO", new View.OnClickListener() {
65 @Override
66 public void onClick(View view) {
67
68 mAdapter.restoreItem(item, position);
69 recyclerView.scrollToPosition(position);
70 }
71 });
72
73 snackbar.setActionTextColor(Color.YELLOW);
74 snackbar.show();
75
76 }
77 };
78
79 ItemTouchHelper itemTouchhelper = new ItemTouchHelper(swipeToDeleteCallback);
80 itemTouchhelper.attachToRecyclerView(recyclerView);
81 }
82
83}
为了将ItemTouchHelper设置到RecclerView上,需要使用attachToRecillerView方法。当单击Snackbar操作时,我们使用rest oreItem
方法在RecillerView中恢复该项目。rest oreItem
方法在Recical erViewAdapter类中定义。scroll ToPosition
将回收器视图滚动到指定位置。此选项主要用于将项目插入到循环视图的顶部时。Cardview_row.xml的代码如下:
1<?xml version="1.0" encoding="utf-8"?>
2<android.support.v7.widget.CardView xmlns:android="https://schemas.android.com/apk/res/android"
3 xmlns:card_view="https://schemas.android.com/apk/res-auto"
4 android:id="@+id/cardView"
5 android:layout_width="match_parent"
6 android:layout_height="64dp"
7 android:layout_margin="8dp"
8 card_view:cardCornerRadius="0dp"
9 card_view:cardElevation="2dp">
10
11 <RelativeLayout
12 android:id="@+id/relativeLayout"
13 android:layout_width="match_parent"
14 android:layout_height="match_parent"
15 android:paddingBottom="8dp"
16 android:paddingLeft="8dp"
17 android:paddingRight="8dp">
18
19 <TextView
20 android:id="@+id/txtTitle"
21 android:layout_width="wrap_content"
22 android:layout_height="wrap_content"
23 android:layout_centerVertical="true"
24 android:text="Item 1"
25 android:textAppearance="@style/TextAppearance.Compat.Notification.Title" />
26 </RelativeLayout>
27
28</android.support.v7.widget.CardView>
下面给出了RecillerViewAdapter.Java类的代码:
1package com.journaldev.androidrecyclerviewswipetodelete;
2
3import android.support.v7.widget.RecyclerView;
4import android.view.LayoutInflater;
5import android.view.View;
6import android.view.ViewGroup;
7import android.widget.RelativeLayout;
8import android.widget.TextView;
9
10import java.util.ArrayList;
11import java.util.List;
12
13public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {
14
15 private ArrayList<String> data;
16
17 public class MyViewHolder extends RecyclerView.ViewHolder {
18
19 private TextView mTitle;
20 RelativeLayout relativeLayout;
21
22 public MyViewHolder(View itemView) {
23 super(itemView);
24
25 mTitle = itemView.findViewById(R.id.txtTitle);
26 }
27 }
28
29 public RecyclerViewAdapter(ArrayList<String> data) {
30 this.data = data;
31 }
32
33 @Override
34 public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
35 View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_row, parent, false);
36 return new MyViewHolder(itemView);
37 }
38
39 @Override
40 public void onBindViewHolder(MyViewHolder holder, int position) {
41 holder.mTitle.setText(data.get(position));
42 }
43
44 @Override
45 public int getItemCount() {
46 return data.size();
47 }
48
49 public void removeItem(int position) {
50 data.remove(position);
51 notifyItemRemoved(position);
52 }
53
54 public void restoreItem(String item, int position) {
55 data.add(position, item);
56 notifyItemInserted(position);
57 }
58
59 public ArrayList<String> getData() {
60 return data;
61 }
62}
下面给出了上述应用程序的输出:本教程到此结束。您可以从下面的链接下载该项目: