在超级视图中嵌入的自定义UIView中未收到Tap Gesture Recognizer

时间:2016-05-03 15:00:37

标签: ios swift events uiview uitapgesturerecognizer

我正在尝试创建一个名为MyScrollView的自定义UIView / Scrollview,其中包含一些标签(UILabel),这些标签会接收点击手势/事件,以响应用户的选择See the below screen shot for the custom UIView

为了让点击事件在UILabel上运行,我确保他们都有userIteractionEnabled = true,我创建了一个委托,如下所示:

protocol MyScrollViewDelegate {
    func labelClicked(recognizer: UITapGestureRecognizer)
}

自定义UIView正在我创建的ScrollViewController中使用,此ScrollViewController也实现了委托方法:

import UIKit
import Neon
class ScrollViewController: UIViewController, MyScrollViewDelegate {

var curQuestion: IPQuestion?
var type: QuestionViewType?
var lastClickedLabelTag: Int = 0 //

init(type: QuestionViewType, question: IPQuestion) {
    super.init(nibName: nil, bundle: nil)
    self.curQuestion = question
    self.type = type
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.automaticallyAdjustsScrollViewInsets = false
}

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

override func loadView() {
    view = MyScrollView(delegate: self, q: curQuestion!)
    view.userInteractionEnabled = true
}
}

// implementations for MyScrollViewDelegate
extension ScrollViewController {

func labelTitleArray() -> [String]? {
    print("labelTitleArray called in implemented delegate")

    return ["Comments", "Answers"]
}

func labelClicked(recognizer: UITapGestureRecognizer) {
    print("labelClicked called in implemented delegate")
    let controller = parentViewController as? ParentViewController
    controller?.labelClicked(recognizer)
    lastClickedLabelTag = recognizer.view!.tag
    }
}

// MARK: - handle parent's ViewController event
extension QuestionDetailViewController {
    func updateActiveLabelsColor(index: Int) {
        print("updating active labels color: \(index)")
        if let view = view as? MyScrollView {
            for label in (view.titleScroll.subviews[0].subviews as? [UILabel])! {
                if label.tag == index {
                    label.transform = CGAffineTransformMakeScale(1.1,1.1)
                    label.textColor = UIColor.purpleColor()
                }
                else {
                    label.transform = CGAffineTransformMakeScale(1,1)
                    label.textColor = UIColor.blackColor()
                }
            }
        }
    }
}

以上ScrollViewController作为子视图控制器添加到父视图控制器,并定位到父视图的顶部:

override func viewDidLoad() {
        super.viewDidLoad()
        self.automaticallyAdjustsScrollViewInsets = false
        self.view.backgroundColor = UIColor.whiteColor()
        addChildViewController(scrollViewController) // added as a child view controller here
        view.addSubview(scrollViewController.view) // here .view is MyScrollView
        scrollViewController.view.userInteractionEnabled = true
        scrollViewController.view.anchorToEdge(.Top, padding: 0, width: view.frame.size.width, height: 100)
    }

该应用可以在视图中加载所有内容,但点击手势/事件不会传递到自定义MyScrollView中的标签。为此,我做了一些谷歌搜索并在Apple Developer网站上阅读了Event Delivery: Responder Chain并进行了热门测试。可以在hitTest

中触发下面的MyScrollView功能
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
        print("hit test started, point: \(point), event: \(event)")
        return self
    }

我对hitTest的观察是touchesBegan()touchesEnded()方法在hitTest函数存在时仅在视图触发。如果没有hitTest,则不会通过点击调用这两个函数。

但没有运气让UILabel回应Tap手势。所以我在这里与SO专家联系。谢谢你的帮助!

3 个答案:

答案 0 :(得分:4)

我想我发现了UILabel在经过多次努力后没有回应的原因:标签的.addGestureRecognizer()方法是在我的自定义init()方法中运行的{1}}组件,错误,因为视图/标签可能尚未呈现。相反,我将该代码移动到生命周期方法UIView,一切都开始运作良好:

layoutSubviews()

此外,我不需要实现任何UIGestureRecognizer委托方法,也不需要创建容器视图或滚动视图var lastLabel: UILabel? = nil for i in 0..<scrollTitleArr.count { let label = UILabel() label.text = scrollTitleArr[i] ?? "nothing" print("label: \(label.text)") label.font = UIFont(name: "System", size: 15) label.textColor = (i == 0) ? MaterialColor.grey.lighten2 : MaterialColor.grey.darken2 label.transform = (i == 0) ? CGAffineTransformMakeScale(1.1, 1.1) : CGAffineTransformMakeScale(0.9, 0.9) label.sizeToFit() label.tag = i // for tracking the label by tag number label.userInteractionEnabled = true label.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.labelClicked(_:)))) titleContainer.addSubview(label) if lastLabel == nil { label.anchorInCorner(.TopLeft, xPad: 0, yPad: 0, width: 85, height: 40) // label.anchorToEdge(.Left, padding: 2, width: 85, height: 40) } else { label.align(.ToTheRightMatchingTop, relativeTo: lastLabel!, padding: labelHorizontalGap, width: 85, height: 40) } lastLabel = label } 。更重要的是,在将自定义UIView嵌入到superview时,我配置了它的大小并设置了userInteractionEnabled

我想我应该在Apple Developer网站上阅读更多clipsToBounds = true文档。希望这将有助于我这样的人!谢谢大家!

答案 1 :(得分:0)

您必须设置属性userInteractionEnabled = YES

答案 2 :(得分:0)

出于某种原因,我的模拟器在点击手势识别器不工作时被冻结了。所以,当我重新启动应用程序时,它再次起作用。我不知道这是否适用于此,但这对我来说很有用。