UIScrollView 不会将点击手势传播到其 children

UIScrollView does not propagate tap gesture to its children

我被困在这个问题上,没有其他关于 SO 的问题帮助我...

我有视图控制器,它实现了 UIGestureRecognizerDelegate。有几个视图,其中一个是 contentView,在那个 contentView 里面,有一个 UIScrollView。在那个滚动视图中,还有一个 scrollContentView,它是一个简单的 UIView,但它包含更多的子视图,我没有将它们包含在代码示例中只是因为 space。一切正常(经过很多时间),但看起来没有传播点击手势将 UIScrollView 扔到 child 视图..

我没有使用故事板。

我什么都试过了,如有任何帮助,我们将不胜感激。

class MyController: PopoverController, UITableViewDelegate, UIGestureRecognizerDelegate
{
    var scrollPane: UIScrollView!

    var myContentView: UIView!

    var bottomPane: EditOrderItemBottomPaneView!


    var quantityPaneView: QuantityPaneView!

    var optionsTable: OptionsTableView!

    var modificationsTable: ModificationsTableView!

    var specialPricingsTable: SpecialPricingsTableView!


    override func viewDidLoad()
    {
        super.viewDidLoad()

        categoriesModel = DIContainer.get().getCategoriesModel()
        activeOrderModel = DIContainer.get().getActiveOrderModel()
        modificationModel = DIContainer.get().getProductModificationsModel()

        orderItem = popoverModel.get("orderItem") as! OrderItem!
        let category: ProductCategory = categoriesModel.getCategoryById(orderItem.categoryId)!

        titleLabel.text = category.name

        // scroll view
        scrollPane = UIScrollView()
        scrollPane.translatesAutoresizingMaskIntoConstraints = false
        scrollPane.delegate = self
        contentView.addSubview(scrollPane)

        // bottom pane
        bottomPane = EditOrderItemBottomPaneView()
        contentView.addSubview(bottomPane)

        contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[scrollView][bottomView]|", options: [], metrics: nil, views: ["scrollView": scrollPane, "bottomView": bottomPane]))
        contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[scrollView]|", options: [], metrics: nil, views: ["scrollView": scrollPane]))
        contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[bottomView]|", options: [], metrics: nil, views: ["bottomView": bottomPane]))

        // scroll content view
        myContentView = UIView()
        myContentView.translatesAutoresizingMaskIntoConstraints = false
        scrollPane.addSubview(myContentView)
        scrollPane.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[content]|", options: [], metrics: nil, views: ["content": myContentView]))
        scrollPane.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[content]|", options: [], metrics: nil, views: ["content": myContentView]))

        contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[content]|", options: [], metrics: nil, views: ["content": myContentView]))
        contentView.addConstraint(NSLayoutConstraint(item: myContentView, attribute: NSLayoutAttribute.Trailing,
                relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing,
                multiplier: 1, constant: 0))
        contentView.addConstraint(NSLayoutConstraint(item: myContentView, attribute: NSLayoutAttribute.Leading,
                relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading,
                multiplier: 1, constant: 0))

        // quantity pane
        quantityPaneView = QuantityPaneView()
        myContentView.addSubview(quantityPaneView)

        // options table
        let optionsDataSource: OrderItemOptionsTableViewDataSource = DIContainer.get().getOrderItemOptionsTableViewDataSource()
        optionsDataSource.orderItem = orderItem
        if optionsDataSource.getNumberOfOptions() > 0 {
            optionsTable = OptionsTableView(delegate: DIContainer.get().getOrderItemOptionsTableViewDelegate(),
                    dataSource: optionsDataSource, orderItem: orderItem)
            myContentView.addSubview(optionsTable)
        }

        // modifications table
        modificationsTable = ModificationsTableView(
        delegate: DIContainer.get().getOrderItemModificationsTableViewDelegate(),
                dataSource: DIContainer.get().getOrderItemModificationsTableViewDataSource(),
                orderItem: orderItem)
        myContentView.addSubview(modificationsTable)

        // special pricing table
        specialPricingsTable = SpecialPricingsTableView(
        delegate: DIContainer.get().getOrderItemSpecialPricingsTableViewDelegate(),
                dataSource: DIContainer.get().getOrderItemSpecialPricingsTableViewDataSource(),
                orderItem: orderItem)
        myContentView.addSubview(specialPricingsTable)

        var views = [
                "quantityPane": quantityPaneView,
                "modifications": modificationsTable,
                "specialPricings": specialPricingsTable
        ]

        myContentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-25-[quantityPane]-25-|", options: [], metrics: nil, views: views))
        myContentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-25-[modifications]-25-|", options: [], metrics: nil, views: views))
        myContentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-25-[specialPricings]-25-|", options: [], metrics: nil, views: views))

        if optionsDataSource.getNumberOfOptions() > 0 {
            views["options"] = optionsTable
            myContentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-25-[options]-25-|", options: [], metrics: nil, views: views))
            myContentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[quantityPane]-25-[options]-25-[modifications]-25-[specialPricings]", options: [], metrics: nil, views: views))
        }
        else {
            myContentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[quantityPane]-25-[modifications]-25-[specialPricings]", options: [], metrics: nil, views: views))
        }
    }

    override func viewDidLayoutSubviews()
    {
        super.viewDidLayoutSubviews()

        var h: CGFloat = 0.0
        for view: UIView in myContentView.subviews {
            h += view.frame.size.height;
        }

        scrollPane.contentSize = CGSizeMake(myContentView.frame.size.width, h)
    }

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

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool
    {
        if touch.view != scrollPane {
            return false
        }

        return true
    }
}

实现 UIGestureRecognizer 委托方法。

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if (touch.view != yourScrollView) { 
        return NO;
    }
    return YES;
}

才发现整个画面设计的真的很烂。我没有解决问题,但我重新实现了整个控制器。我仍然认为有可能解决这个问题,但是有更简单的方法。

重点是,我在该滚动内容视图中有更多 table 视图。但当然,可以只创建一个 table 并包含更多部分。这样做的副作用是一个 table 视图本身是可滚动的,因此不需要使用自定义 UIScrollView。

因此,对于开始 iOS 开发的每个人,请尽可能使用包含更多部分的 UITableView。