UITabBarController issue – something (UINavigationBarContentView?) overlays the button on child UIViewController so the button can't be pressed

huangapple go评论70阅读模式
英文:

UITabBarController issue - something (UINavigationBarContentView?) overlays the button on child UIViewController so the button can't be pressed

问题

我使用UIViewController实现了UITabBarController,其中包含一个由UIViewController制作的选项卡。它由两个部分组成 - 一个包含UIButton的UIView,以及一个UITableView。我没有使用UITableViewController,因为无法向其标题栏添加自定义按钮:

final class ContactsController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    @objc func buttonTapped(sender: UIButton) {
        print("Button tapped!")
    }
    
    lazy var addButton: UIButton = { [weak self] in
        guard let self = self else { return UIButton() }
        let button = UIButton(type: .custom)
        button.backgroundColor = .systemBlue
        button.tintColor = .white
        button.layer.cornerRadius = 8
        button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
        return button
    }()
    
    lazy var buttonBarView: UIView = {
        let barView = UIView()
        barView.clipsToBounds = true
        return barView
    }()
    
    lazy var tableView: UITableView = {
        let tableView = UITableView()
        return tableView
    }()
    
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 50
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(ContactCell.self)
        
        addButton.setTitle("Add", for: .normal)
        tableView.dataSource = self
        tableView.delegate = self
        
        view.backgroundColor = .systemBackground
        title = "Contacts"
        tableView.rowHeight = 125
        
        self.view.bringSubviewToFront(addButton)
        
        setUpViews()
    }
    
    private func setUpViews() {
        
        self.view.addSubview(buttonBarView)
        buttonBarView.addConstraints(
            .alignTopWithTop(of: self.view),
            .alignLeadingWithLeading(of: view),
            .alignWidth(with: view, mult: 1),
            .alignHeight(with: view, mult: 0.045)
        )
        
        buttonBarView.addSubview(addButton)
        addButton.addConstraints(
            .alignTopWithTop(of: buttonBarView),
            .alignBottomWithBottom(of: buttonBarView),
            .alignTrailingWithTrailing(of: buttonBarView, const: 8),
            .setAspectWidth(ratio: 1)
        )
        
        self.view.addSubview(tableView)
        tableView.addConstraints(
            .alignTopWithBottom(of: buttonBarView),
            .alignLeadingWithLeading(of: view),
            .alignWidth(with: view, mult: 1),
            .alignBottomWithBottom(of: view)
        )
    }
}

请忽略lazy var与setUpViews函数结合使用的部分 - 这是因为我花了一些时间来调试它。

一切看起来都很正常,但存在一个问题 - 无法按下按钮"...":

UITabBarController issue – something (UINavigationBarContentView?) overlays the button on child UIViewController so the button can't be pressed

如果我更改了约束并将其移到"Contacts"标题下方,那么它就可以按下。

我使用了调试视图工具,并注意到可能是UINavigationBarContentView覆盖了按钮(这里已选择):

UITabBarController issue – something (UINavigationBarContentView?) overlays the button on child UIViewController so the button can't be pressed

我尝试通过代码访问它,但无法访问它。

此外,我使用了view.bringSubviewToFront()将按钮移到前台,但没有改变任何东西。

我打印了该UIViewController的所有子视图,并对每个子视图执行了相同的操作。但是打印只显示我创建的视图。

请帮助解决这个问题。我查看了UIViewController的Apple文档,但不幸的是没有找到有用的信息。

.toolBarItems属性与UINavigationController一起使用,因此我认为在我的情况下不能使用它。

谢谢。

英文:

I implemented UITabBarController with a tab made of UIViewController. It consists of two parts - UIView with UIButton placed into, and a UITableView. I didn't used UITableViewController because it's not possible to add custom buttons to its title:

final class ContactsController: UIViewController, UITableViewDelegate, UITableViewDataSource {

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

lazy var addButton = { [weak self] in
    guard let self = self else { return UIButton()}
    let button = UIButton(type: .custom)
    button.backgroundColor = .systemBlue
    button.tintColor = .white
    button.layer.cornerRadius = 8
    button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
    return button
}()

lazy var buttonBarView = {
    let barView = UIView()
    barView.clipsToBounds = true
    // barView.isUserInteractionEnabled = true
    return barView
}()

lazy var tableView = {
    let tableView = UITableView()
    return tableView
}()
	
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 50 }

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(ContactCell.self)
    
    addButton.setTitle("Add", for: .normal)
    tableView.dataSource = self
    tableView.delegate = self

    view.backgroundColor = .systemBackground
    title = "Contacts"
    tableView.rowHeight = 125
    
    self.view.bringSubviewToFront(addButton)

    setUpViews()
}

private func setUpViews() {
    
    self.view.addSubview(buttonBarView)
    buttonBarView.addConstraints(
        .alignTopWithTop(of: self.view),
            .alignLeadingWithLeading(of: view),
            .alignWidth(with: view, mult: 1),
        .alignHeight(with: view, mult: 0.045)
        )
    
    buttonBarView.addSubview(addButton)
    addButton.addConstraints(
               .alignTopWithTop(of: buttonBarView),
               .alignBottomWithBottom(of: buttonBarView),
               .alignTrailingWithTrailing(of: buttonBarView, const: 8),
               .setAspectWidth(ratio: 1))
    
    
    self.view.addSubview(tableView)
    tableView.addConstraints(
        .alignTopWithBottom(of: buttonBarView),
        .alignLeadingWithLeading(of: view),
        .alignWidth(with: view, mult: 1),
        .alignBottomWithBottom(of: view)
    )

Please ignore lazy var combined with setUpViews function - this is done because I spent some hours trying to debug it.

All looks fine, but there's an issue - the button "..." can not be pressed:

UITabBarController issue – something (UINavigationBarContentView?) overlays the button on child UIViewController so the button can't be pressed

If I changed constraints and moved it below "Contacts" title, it can be pressed.

I used debug views tool and noticed that may be UINavigationBarContentView overlays the button (here it is selected):

UITabBarController issue – something (UINavigationBarContentView?) overlays the button on child UIViewController so the button can't be pressed

I tried to access it via code, but it isn't accessible.

Also, I used view.bringSubviewToFront() to bring the button to front, but it changed nothing.

I printed all subviews of that UIViewController and for each subview, I did the same. But print only showed me only those views that I created.

Please help resolving this issue. I checked Apple documentation on UIViewController but, unfortunately, didn't find anything useful.

.toolBarItems property is used together with UINavigationController so I think it can't be used in my case.

Thank you.

答案1

得分: 1

问题出在你对 buttonBarView 的使用上。你将其约束设置在视图控制器的视图顶部。但该视图的顶部位于导航栏之后。这正是在视图层次结构调试视图中看到的情况。

最简单的解决方法是摆脱 buttonBarViewUINavigationBar 已经提供了一种在导航栏上添加按钮(和视图)的方法。这是通过 UIViewController 的 API - navigationItem 来实现的。

甚至不需要将你的 addButton 创建为 UIButton。可以使用标准的 UIBarButtonItem 来创建,带有标准的 + 符号。

let btnAdd = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addTapped))
navigationItem.rightBarButtonItem = btnAdd

如果你不想要标准的添加图标,也可以通过标题或图像来创建 UIBarButtonItem。如果你确实想使用自定义按钮,那么可以将按钮创建为自定义视图的 UIBarButtonItem

let btnAdd = UIBarButtonItem(customView: addButton)
navigationItem.rightBarButtonItem = btnAdd

不需要额外的视图或约束。

英文:

The problem is your use of buttonBarView. You set its constraints to be at the very top of the view controller's view. But the top of that view is behind the nav bar. And that's exactly what you see in the view hierarchy debug view.

The simplest solution is to get rid of your buttonBarView. UINavigationBar already provides ways to add buttons (and views) to the nav bar. This is done via UIViewController APIs - navigationItem.

You don't even need your addButton as a UIButton. Create a standard UIBarButtonItem with a standard +.

let btnAdd = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addTapped))
navigationItem.rightBarButtonItem = btnAdd

There are ways to create the UIBarButtonItem with a title or image if you don't want the standard add icon. If you really want to use your custom button then you can create the UIBarButtonItem with the button as a custom view:

let btnAdd = UIBarButtonItem(customView: addButton)
navigationItem.rightBarButtonItem = btnAdd

No need for the extra views or the constraints.

huangapple
  • 本文由 发表于 2023年6月26日 01:57:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76551748.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定