首页 文章

tableView上的UIPanGestureRecognizer不会滚动表项

提问于
浏览
1

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

What have I tried:

@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)
            }
        }
}

Gesture added to tableView

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

Problem Summary:

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

***Problem Usecases: ***

  • 初始条件 - tableview原点位于屏幕中间,即(0,Height / 2)

  • 平移手势 - table 垂直向上移动,但没有项目滚动,直到原点卡住(0,0)

  • pan up gesture - 单元格项目向上移动但不是表格本身

  • pan up gesture - 单元格项目向上移动直到单元格结束

  • 平移下来手势 - 单元格项目向下移动直到索引0,让我们说为0索引

  • pan down gesture - tableview垂直向下移动,直到其原点到达屏幕中间(0,Height / 2)

3 回答

  • 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

  • 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)
        }
    }
    }
    
  • 1

    我不知道一个比子类化tableView更好的解决方案,并在 layoutSubviews 中阻止它 contentOffset . 就像是 :

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

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

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

    UPDATE 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

相关问题