在UITableView(iOS)中滑动删除整个部分

3
我过去使用MGSwipeTableCell成功地实现了滑动删除单元格的功能,但是我的当前任务需要在相同的行为中滑动整个部分。
我目前在UITableView中设置了一个滑动手势识别器,当触发滑动手势时,我会计算出所接收到的触摸位于哪个部分,并删除填充该部分的对象(在Core Data中),然后调用删除动画。
//Delete objects that populate table datasource 
for notification in notifications {
    notificationObject.deleted = true
}

DataBaseManager.sharedInstance.save()

let array = indexPathsToDelete
let indexSet = NSMutableIndexSet()
array.forEach(indexSet.add)

//Delete section with animation            
self.notificationsTableView.deleteSections(indexSet as IndexSet, with: .left)

这个方法可以使用,但不是最理想的。理想情况下,我们希望整个部分能够随着手指拖动(并在释放时达到某个点后离开屏幕),类似于MGSwipeTableCell。如何最好地处理这个问题?是否有其他库允许滑动删除部分(我找不到任何一个)?还是这是我自己必须创建的东西。


1
UITableView 上进行滑动手势通常会很麻烦,因为不仅 UITableView 本身会对滑动手势做出反应,而且它们的单元格也会有相应的反应。这里有一个想法,不要试图在部分单元格上滑动以启动滑动操作,而是为该部分创建一个自定义标题单元格。然后,该标题视图将包含其自己的滑动手势(或按钮)来显示“删除”按钮。当在标题中按下该按钮时,使用 .deleteSections(indexSet as IndexSet, with: .left) 方法来删除整个部分。 - Brandon A
这是一个好主意,但问题不在于滑动手势;问题在于整个部分及其嵌套表需要随手指的触摸一起拖动,如果你明白我的意思。 - Josh O'Connor
2个回答

2

我没有测试过,但下面是这个想法。查看 (self.header) 并使用 touchesBegan... 方法来检测用户在屏幕上放置手指。然后,使用 touchesMoved... 方法跟随手指并计算上一次偏移和下一次之间的差异。它应该会增加 1 (或更多),取决于用户移动手指的速度。使用此值减去单元格的 contentVieworigin.x

var header: UIView!
var tableView:UITableView!
var offset:CGFloat = 0

override public func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    // Touches Began. Disable user activity on UITableView
    if let touch = touches.first {
        // Get the point where the touch started
        let point = touch.location(in: self.header)
        offset = point.x
    }
}

override public func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {

        // Get the point where the touch is moving in header
        let point = touch.location(in: self.header)

        // Calculate the movement of finger
        let x:CGFloat = offset - point.x
        if x > 0 {
            // Move cells by offset
            moveCellsBy(x: x)
        }

        // Set new offset
        offset = point.x
    }
}

override public func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    // Reset offset when user lifts finter
    offset = 0
}

func moveCellsBy(x: CGFloat) {
    // Move each visible cell with the offset
    for cell in self.tableView.visibleCells {
        // Place in animation block for smoothness
        UIView.animate(withDuration: 0.05, animations: {
            cell.contentView.frame = CGRect(x: cell.contentView.frame.origin.x - x, y: cell.contentView.frame.origin.y, width: cell.contentView.frame.size.width, height: cell.contentView.frame.size.height)
        })
    }
}

1
谢谢Brandon,实际上在阅读你的答案之前我正要使用这个逻辑。只是希望已经有一个库可以做到这一点。 - Josh O'Connor
别担心;)。也许你可以制作一个小型的库来实现这个功能? - Brandon A
这绝对在议程中,应该不难的 :D - Josh O'Connor

0

Brandon的答案是正确的,但是当使用touches began和其他触摸委托方法时,INSPullToRefresh库存在问题。

我所做的是实现一个UIPanGestureRecognizer并在该手势识别器事件被触发时跟踪触摸。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接