使用UIPanGestureRecognizer删除UICollectionView Swift 3中的单元格

我想分享一个快速的小项目,该项目使用UIPanGestureRecognizer删除UICollectionView中的单元格。 以下是其外观示例:

假定您具有如何创建UICollectionView和自定义CollectionViewCell的基本知识。 项目文件可以位于这里:

GitHub – almusto / PanToDelete
通过在GitHub上创建一个帐户为PanToDelete开发做出贡献。 github.com

当涉及到UI时,该项目非常简单。 我所做的就是创建一个UICollectionViewController,并将其嵌入到导航控制器中的自定义单元格。

设置CollectionView:

让我们快速浏览一下UICollectionView的基本设置

因为我们使用的是UICollectionViewController,所以我们不需要设置委托,因为Xcode会为我们这样做。 但是,我们确实设置了UICollectionViewDelegateFlowLayout以允许我们调整在viewDidLoad()之后的第一个函数中执行的单元格框架。

接下来的三个函数是标准的collectionView函数,我们在其中设置节数,将numberOfItemsInSection设置为grocerList.count,然后创建单元格本身。

您可能想知道功能允许我删除单元格的位置在哪里……不要担心,我稍后再讲。

设置自定义单元:

这是我们大多数代码将要使用的地方。 让我们先来看一下变量和初始化程序。

我在这里创建了一些变量。 cellLabel将存储我们的杂货项目,两个deleteButton标签将根据我们平移的方式添加到左侧或右侧的内容视图下方。 当然还有我们的平移手势识别器。 我们还向类添加了UIGestureRecognizerDelegate协议。 稍后我将解释原因。

接下来,我们有两个init方法,其中调用了我创建的自定义函数comonInit()。

对于所需的init,我仍然有些朦胧,但是据我所知,当我们创建自己的自定义类init时,我们需要使用它。 此必需的init允许我们通过NSCoder“取消存档”数据。

似乎这里发生了很多事情,但这确实很简单。 而不是在情节提要中创建这些对象,而是手动进行,因此我们必须初始化每个对象并将其添加到视图中。 让我们一次浏览一个项目。

首先,我将contentView的背景色设置为灰色,将self.background颜色设置为红色。 每个单元格都有一个contentView,它显示我们想要的单元格中的对象或颜色。 当我设置self.background颜色时,实际上是在contentView下设置颜色。

完成此操作后,我将初始化cellLabel并将其添加到contentView中。 我也将translatesAutoresizingMaskIntoConstraints设置为false,这使我可以手动设置该标签的约束。 如果我不这样做,则自动布局会尝试为我创建约束。

同样,我初始化deleteLables并将它们插入到contentView的下面。 因为我希望这些标签可以用平底锅拍摄,所以我不在这里设置边框。 相反,我在平底锅发生时设置了帧。

最后,我使用一个名为onPan的动作来初始化平移手势。 与创建UIButton时非常相似。 我还将委托设为self..self作为CustomCell类。

现在,我们的视图已初始化,让我们开始平移手势:

制作手势:

首先让我们看一下我们的onPan函数。 您会注意到我们的if语句涵盖了手势的某些不同状态。 如果状态为“开始”,则不执行任何操作;如果状态为“已更改”,则调用setNeedsLayout()。 该方法说“在下一个运行循环上调用layoutSubViews()。”当某人按下我们的单元格时,状态变为开始,然后当他们向左或向右移动该单元格时,状态变为更改并调用layoutSubViews()。

现在在layoutSubViews()中,我们通过调用translation(in:View)来检查状态是否已更改,以及状态是否改变,以获取平移的当前点,该平移返回“标识坐标系统中视图新位置的点”。然后,我们根据该点设置contentView和deleteLabels的框架。

现在回到我们的onPan函数,我们有一条else语句,它检查平移手势速度以查看其是否大于每秒500点。 在检查速度之前,您会注意到腹肌。 这是绝对值,我们这样做的原因是因为用户可以向左或向右平移,因此该值可能为负。 如果满足该条件,我们现在为我们的collectionView创建一个常量,并使用我们在collectionView上按下的位置的CGPoint来获取indexPath。 一旦有了这个,我们就可以告诉collectionView调用下面的函数,我们尚未在CollectionViewController类中实现该函数,所以让我们回去做一下。

如您所见,当我们调用此函数时,我们正在从collectionView和杂货店列表中删除该indexPath处的项目。

现在,如果您在此处运行该应用程序,则可以删除单元格,但是您会注意到,当您按下某个单元格并向下滚动时,您将无法删除该单元格。 这是在我们的CustomCell中添加UIGestureRecognizerDelegate协议的地方。 我们想向我们的CustomCell添加两个功能。

第一个只是使我们的单元能够处理多个手势识别器。 因此,现在我们的平移手势和滚动手势可以一起工作了。

下一个功能是让我们决定何时开始手势。 如果x方向上的速度大于y方向上的速度,则将其设置为true,因为当用户要删除某些内容时,我们只希望平移在左右方向上起作用。 如果速度在y方向上更大,我们假定用户正在尝试滚动。

就是这样!