简体   繁体   English

自定义按钮点击在表格页脚视图中的UIView中不起作用

[英]Custom Button Tap not working in UIView In Table Footer View

I have the most peculiar scenario that I can't seem to fix. 我有一个最奇怪的情况,我似乎无法解决。 I have a custom button that I add as a subview to a UIView . 我有一个自定义按钮,我作为子视图添加到UIView I then add the UIView to the tableFooterView of a table view and I'm not able to have the button tap be detected. 然后我将UIView添加到表视图的tableFooterView中,我无法检测到按钮点击。 Here is the code: 这是代码:

public func configureMyButton() {
        let button = CustomButton("My title")
        button.addTarget(self, action: #selector(self.buttonAction), for: .touchUpInside)
        button.isUserInteractionEnabled = true
        let buttonContainer = UIView()
        buttonContainer.addSubview(button)
        buttonContainer.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-16-[button]", options: [], metrics: [:], views: ["button":button]))
        buttonContainer.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-8-[button]-8-|", options: [], metrics: [:], views: ["button":button]))
        self.tableView.tableFooterView = buttonContainer
    } 

@objc func buttonAction(sender: UIButton!) {
    print("Button tapped")
}

Now if I change this: 现在,如果我改变这个:

self.view.addSubview(buttonContainer)

The button tap works. 按钮水龙头工作。 This leads me to believe that theres something about tableFooterView that stops the tap from working but I'm not entirely sure what it could be. 这让我相信有一些关于tableFooterView东西会阻止水龙头工作,但我不完全确定它可能是什么。 Any ideas? 有任何想法吗?

The reason why the button wasn't responding to taps was because the buttonContainers frame was completely wrong. 按钮没有响应水龙头的原因是因为buttonContainers框架完全错误。 So despite everything looking find on screen, the frame was practically none existent and hence the button wasn't responding 因此,尽管所有内容都在屏幕上找到,但框架几乎不存在,因此按钮没有响应

public func configureMyButton() {
    let button = CustomButton("My title")
    button.addTarget(self, action: #selector(self.buttonAction), for: .touchUpInside)
    button.isUserInteractionEnabled = true
    let buttonContainer = UIView()
    buttonContainer.addSubview(button)
    buttonContainer.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-16-[button]", options: [], metrics: [:], views: ["button":button]))
    buttonContainer.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-8-[button]-8-|", options: [], metrics: [:], views: ["button":button]))
    buttonContainer.layoutIfNeeded()
    buttonContainer.frame = CGRect(x: 0, y: 0, width: self.tableView.frame.size.height, height: button.frame.size.height + 16)
    self.tableView.tableFooterView = buttonContainer
}

I'm not overly happy with the solution. 我对解决方案并不满意。 I'm of the opinion I shouldn't have to have fiddled with the buttonContainer frame. 我认为我不应该摆弄buttonContainer框架。 Autolayout should have deduced it's frame to at the very least be the size of its subviews. Autolayout应该推断它的框架至少是其子视图的大小。

As you noted, the button could not be tapped because it was displayed outside the button container frame. 正如你提到的,按钮不能因为它显示的按钮容器框架之外的挖掘。

UITableView handles the layout for its header and footer views, so using auto-layout with them takes an additional step. UITableView处理其页眉和页脚视图的布局,因此使用自动布局需要额外的步骤。

Don't add your footer view in viewDidLoad() . 不要在viewDidLoad()添加页脚视图。 Instead, override viewDidLayoutSubviews() like this: 相反,覆盖viewDidLayoutSubviews()如下所示:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // manipulating the tableFooterView will trigger viewDidLayoutSubviews()
    // so only call this if we haven't added the footer view yet
    if tableView.tableFooterView == nil {
        configureMyButton()
        tableView.layoutTableFooterView()
    }
}

Change your configureMyButton() func as shown here: 更改configureMyButton()函数,如下所示:

public func configureMyButton() {

    // I don't have your CustomButton() func...
    //let button = CustomButton("My title")

    let button = UIButton()
    button.translatesAutoresizingMaskIntoConstraints = false
    button.setTitle("My Title", for: .normal)
    button.backgroundColor = .blue

    button.addTarget(self, action: #selector(self.buttonAction), for: .touchUpInside)
    button.isUserInteractionEnabled = true

    let buttonContainer = UIView()

    // set background to red so we can see it - remove after testing
    buttonContainer.backgroundColor = .red

    buttonContainer.addSubview(button)

    buttonContainer.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-16-[button]|", options: [], metrics: [:], views: ["button":button]))
    buttonContainer.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-8-[button]-8-|", options: [], metrics: [:], views: ["button":button]))

    self.tableView.tableFooterView = buttonContainer
}

And then add this extension: 然后添加此扩展名:

extension UITableView {

    func layoutTableHeaderView() {

        guard let tempView = self.tableHeaderView else { return }
        tempView.translatesAutoresizingMaskIntoConstraints = false

        let width = tempView.bounds.size.width;

        let temporaryWidthConstraints = NSLayoutConstraint.constraints(withVisualFormat: "[tempView(width)]", options: NSLayoutConstraint.FormatOptions(rawValue: UInt(0)), metrics: ["width": width], views: ["tempView": tempView])

        tempView.addConstraints(temporaryWidthConstraints)

        tempView.setNeedsLayout()
        tempView.layoutIfNeeded()

        let tempSize = tempView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
        let height = tempSize.height
        var frame = tempView.frame

        frame.size.height = height
        tempView.frame = frame

        self.tableHeaderView = tempView

        tempView.removeConstraints(temporaryWidthConstraints)
        tempView.translatesAutoresizingMaskIntoConstraints = true

    }

    func layoutTableFooterView() {

        guard let tempView = self.tableFooterView else { return }
        tempView.translatesAutoresizingMaskIntoConstraints = false

        let width = tempView.bounds.size.width;

        let temporaryWidthConstraints = NSLayoutConstraint.constraints(withVisualFormat: "[tempView(width)]", options: NSLayoutConstraint.FormatOptions(rawValue: UInt(0)), metrics: ["width": width], views: ["tempView": tempView])

        tempView.addConstraints(temporaryWidthConstraints)

        tempView.setNeedsLayout()
        tempView.layoutIfNeeded()

        let tempSize = tempView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
        let height = tempSize.height
        var frame = tempView.frame

        frame.size.height = height
        tempView.frame = frame

        self.tableFooterView = tempView

        tempView.removeConstraints(temporaryWidthConstraints)
        tempView.translatesAutoresizingMaskIntoConstraints = true

    }

}

Now your footer view will size correctly based on your auto-layout constraints -- so if you add elements to the footer view you won't have to explicitly change your height value. 现在,您的页脚视图将根据您的自动布局约束正确调整大小 - 因此,如果您向页脚视图添加元素,则不必显式更改高度值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM