tableView上的UIPanGestureRecognizer不会滚动表项

时间:2018-05-31 07:24:02

标签: ios swift uigesturerecognizer uipangesturerecognizer

UIPanGesture(Swift 4.0)上使用UITableView来拖动tableview位置(即原点)。 UIPanGestureRecognizer检测触摸事件并使用它们。在某些时候,我想将事件委托给表,以便它将滚动其项目。我怎么能这样做?

我尝试了什么:

@objc func tableViewDragged(gestureRecognizer: UIPanGestureRecognizer) {

        if gestureRecognizer.state == UIGestureRecognizerState.began || gestureRecognizer.state == UIGestureRecognizerState.changed {

            let translation = gestureRecognizer.translation(in: self.view)

// if origin moved to map origin it should not scroll above but cell should scroll normally. But returning does not help scrolling cells
            if self.tableView.frame.origin == self.mapContainer.frame.origin && translation.y < 0 {

                return
            }

            var frame = self.tableView.frame
            let nHeight = (frame.origin.y + translation.y)

            if (nHeight < self.view.frame.size.height) {

                frame.origin.y = nHeight
                self.tableView.frame = frame
                gestureRecognizer.setTranslation(CGPoint(x: 0, y: 0), in: self.view)
            }
        }
}

添加到tableView的手势

let gesture = UIPanGestureRecognizer(target: self, action: #selector(self.tableViewDragged(gestureRecognizer:)))
self.tableView.addGestureRecognizer(gesture)
self.tableView.isUserInteractionEnabled = true
gesture.delegate = self

问题摘要:

对于在tableview的任何一点(即在任何单元格上)进行相同的平移手势,我需要在将tableviews原点固定在容器的左上角时滚动项目。否则我必须移动tableview,直到它附加到左上角。此外,如果没有什么可以向下滚动我需要再次移动下面的表格进行平移手势。

*问题用例:*

  1. 初始条件 - tableview原点位于屏幕中间, 即(0,高度/ 2)
  2. 平移手势 - 桌子垂直向上移动,但没有项目滚动,直到原点卡住(0,0)
  3. 向上平移手势 - 单元格项目向上移动但不是自己表格
  4. 向上平移手势 - 单元格项目向上移动直到单元格结束
  5. 向下平移手势 - 单元格项目向下移动直到索引0,让我们说为0索引
  6. 向下平移手势 - 桌面视图垂直向下移动,直到其原点到达屏幕中间(0,高度/ 2)

3 个答案:

答案 0 :(得分:1)

我不知道比继承tableView并在其contentOffset中阻止其layoutSubviews更好的解决方案。类似的东西:

class MyTableView: UITableView {
    var blocksOffsetAtZero = false
    override func layoutSubviews() {
        super.layoutSubviews()
        guard blocksOffsetAtZero else { return }
        contentOffset = .zero
    }
}

我认为这是地图应用中使用的解决方案。当用户在主屏幕上拖动tableView时,它不会滚动但会提升直到它到达屏幕顶部然后再次滚动。

为此,您需要向tableview添加一个手势,该手势同时识别tableView的识别器,并在每次识别器移动tableView的帧时阻止tableView的contentOffset

<强>更新 https://github.com/gaetanzanella/mapLike

您是否正确实施了委托?

// MARK: - UIGestureRecognizerDelegate

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
                       shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

尝试类似:

@objc func tableViewDragged(gestureRecognizer: UIPanGestureRecognizer) {

    if gestureRecognizer.state == UIGestureRecognizerState.began || gestureRecognizer.state == UIGestureRecognizerState.changed {

        let translation = gestureRecognizer.translation(in: self.view)

        var frame = self.tableView.frame
        let nHeight = (frame.origin.y + translation.y)

        if (nHeight < self.view.frame.size.height) {
            frame.origin.y = nHeight
            self.tableView.frame = frame
            gestureRecognizer.setTranslation(CGPoint(x: 0, y: 0), in: self.view)
            tableView.blocksOffsetAtZero = true
        } else {
            tableView.blocksOffsetAtZero = false
        }
    }
}

主要思想:当你改变框架时,阻止滚动。

你也可以使用kamaldeep singh bhatia提供的委托技巧,但是你将无法移动第一个tableView,然后在一个手势中滚动。

查看示例here

答案 1 :(得分:1)

如果我理解正确,那么你想在滚动时取消PanGesture。

试试这个:

func isItemAvailabe(gesture: UISwipeGestureRecognizer) -> Bool {
    if gesture.direction == .down {
        // check if we have some values in down if yes return true else false
    } else if gesture.direction == .up {
        // check if we have some values in up if yes return true else false
    }
    return false
}

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
                       shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    if gestureRecognizer == self.panGesture && otherGestureRecognizer == self.scrollGesture && isItemAvailabe(gesture: otherGestureRecognizer) {
        return true
    }
    return false
}

如果这可以解决您的问题,或者我没有正确理解,请告诉我。

还记得加上这个:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

您可以查看更多here

答案 2 :(得分:1)

使用tableView自己的panGestureRecognizer(不添加新的gestureRecognizer)的最佳方法,例如:

tableView.panGestureRecognizer.addTarget(self, action: #selector(self.tableViewDragged(gestureRecognizer:))

动作

@objc func tableViewDragged(gestureRecognizer: UIPanGestureRecognizer) {
    guard tableView.contentOffset.y < 0 else { return }
    if gestureRecognizer.state == UIGestureRecognizerState.began || gestureRecognizer.state == UIGestureRecognizerState.changed {

    let translation = gestureRecognizer.translation(in: self.view)

    // if origin moved to map origin it should not scroll above but cell should scroll normally. But returning does not help scrolling cells
    if self.tableView.frame.origin == self.mapContainer.frame.origin && translation.y < 0 {

        return
    }

    var frame = self.tableView.frame
    let nHeight = (frame.origin.y + translation.y)

    if (nHeight < self.view.frame.size.height) {

        frame.origin.y = nHeight
        self.tableView.frame = frame
        gestureRecognizer.setTranslation(CGPoint(x: 0, y: 0), in: self.view)
    }
}
}