使用UIPanGestureRecognizer的UITableView会导致“跳跃”触摸

时间:2015-03-31 22:31:31

标签: ios uitableview swift uiscrollview uipangesturerecognizer

案例:https://github.com/ArtworkAD/ios_jumping_y.git

enter image description here

容器

class ContainerController: UIViewController { 
    @IBOutlet weak var container: UIView!   
    @IBOutlet weak var foregroundTopSpace: NSLayoutConstraint!
    @IBOutlet weak var foregroundBottomSpace: NSLayoutConstraint!
}

容器连接到右侧的UITableViewController。

我想做什么

用户滚动桌子,当他到达顶部时,我想以相同的动作向下移动桌子。所以我只需更改容器视图的顶部/底部空间。但是这会导致表跳转。

class MainController: UITableViewController, UIGestureRecognizerDelegate {

    var panRecognizer: UIPanGestureRecognizer!

    var gotStart: Bool = true

    var startTouch: CGPoint!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.bounces = false

        self.panRecognizer = self.tableView.panGestureRecognizer
        self.panRecognizer.addTarget(self, action: "pan:")
        self.tableView.addGestureRecognizer(self.panRecognizer)
    }

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

    func pan(rec:UIPanGestureRecognizer){

        if let parent = self.parentViewController as? ContainerController {

            var y = self.tableView.contentOffset.y
            var touch = rec.locationInView(self.view)

            // JUMPING y
            println(touch.y)

            if y == -64 {

                if self.gotStart  || y < -64 || y > -64 {

                    self.startTouch = touch
                    self.gotStart = false

                } else {

                    if rec.state == .Changed {

                        var changedVerticalHeight = (self.startTouch.y - touch.y)*(-1)

                        if changedVerticalHeight <= parent.view.frame.size.height && touch.y >= changedVerticalHeight {

                            parent.foregroundTopSpace.constant = changedVerticalHeight
                            parent.foregroundBottomSpace.constant = -changedVerticalHeight
                        }

                    } else if rec.state == .Ended {

                        parent.foregroundTopSpace.constant = 0
                        parent.foregroundBottomSpace.constant = 0

                        self.gotStart = true
                    }
                }
            }
        }
    }
}

结果:

enter image description here

任何想法都错了吗?容器视图必须有一些问题,因为当我直接移动表视图时,没有跳跃。

3 个答案:

答案 0 :(得分:3)

在我提出完整的代码

之前,我将在答案中澄清一些事情
  1. 您可以使用scrollViewWillEndDragging函数来了解contentOffset的确切位置,请参阅以下代码:

    override func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
       println(targetContentOffset.memory.y)        
    }
    
  2. 您可以使用函数scrollViewDidEndDecelerating知道滚动完成的时间。

  3. 然后,您可以合并上述两个提示,以便通过以下方式实现目标:

    class MainController: UITableViewController {
    
       var position : CGFloat!
    
       override func viewDidLoad() {
          super.viewDidLoad()       
       }
    
       override func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {  
          // Save where the contentOffset go        
          position = targetContentOffset.memory.y
       }   
    
       override func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
    
           // If reach the top or more than the top when the user move the scroll
           if (position < 0) {               
               var to = scrollView.contentOffset.y + 213
               scrollView.setContentOffset(CGPoint(x: 0, y: to), animated: true)
           }        
       }    
    
       // Default table stuff, not related to problem  
    
       /* Here comes the rest of your code of TableView */    
    }
    

    我删除了与panGestureRecognizer相关的项目代码,然后跳出来进行测试。

    var to = scrollView.contentOffset.y + 213行中,您可以添加position变量或所需的值,我只会213来测试向下移动。

    我希望这对你有所帮助。

答案 1 :(得分:1)

您从self.view系统坐标打印位置。 UITableViewController使用像self.view这样的表格视图。因此,当用户滚动时,原点(x:0 y:0)开始移动。

您必须使用静态系统坐标。正确使用UIViewControllerUITableView panGestureRecognizer属性打印位置并进行滚动:

  1. 创建新的UIViewController
  2. 添加UITableview并设置AutoLayout
  3. IBOutletUITableView
  4. 相关联

    将代码添加到UIViewController类:

    var panRecognizer: UIPanGestureRecognizer!
    @IBOutlet weak var tableView: UITableView?
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        self.panRecognizer = tableView?.panGestureRecognizer;
        self.panRecognizer .addTarget(self, action: "pan:")
        tableView?.addGestureRecognizer(self.panRecognizer)
    
    }
    
    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
    
    func pan(rec:UIPanGestureRecognizer){
        println(rec.locationInView(self.view).y)
    }
    

    您可以下载项目示例here

    如果您只需要控制滚动,请记住UIScrollView delegate method

    optional func scrollViewDidScroll(_ scrollView: UIScrollView)
    

    可以帮到你。它是一个更简洁的解决方案:

    祝你好运。

答案 2 :(得分:0)

我完全相信你想要的东西:

import UIKit

class MainController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        let beginingContentOffset: CGFloat = -64
        if scrollView.contentOffset.y < beginingContentOffset {
            scrollView.bounces = false
            UIView.animateWithDuration(0.05, animations: { () -> Void in
                scrollView.contentOffset = CGPointMake(0, 0)
                }, completion: { (finished: Bool) -> Void in
                scrollView.bounces = true
            })
        }
    }

    // Default table stuff, not related to problem

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 20
    }

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell_ : UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("CELL_ID") as? UITableViewCell
        if(cell_ == nil){
            cell_ = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "CELL_ID")
        }

        cell_!.textLabel!.text = "Row " + String(indexPath.row)

        return cell_!
    }
}

P.S。那&#34; -64&#34;值。它是故事板的边缘。您可以取消选中约束的边距,它将是&#34; 0&#34;。这将是非常清楚的

相关问题