Android 循环视图轻扫即可删除和撤销

在本教程中,我们将讨论并在我们的Android应用程序中实现RecclerView上的Swipe to Delete功能。

安卓刷卡删除

滑动删除功能通常用于从RecillerView中删除行。为了实现刷卡删除功能,我们需要使用ItemTouchHelper实用程序类。

ItemTouchHelper.Callback

为了使用ItemTouchHelper类,我们需要实现ItemTouchHelper.CallbackItemTouchHelper.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。

项目结构

安卓回收站滚动查看delete在该应用的build.gradle中添加以下依赖:

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}

下面给出了上述应用程序的输出:android clerview滑动删除输出本教程到此结束。您可以从下面的链接下载该项目:

AndroidRecyclerViewSwipeToDelete

GitHub项目Link

Published At
Categories with 技术
Tagged with
comments powered by Disqus