如何以编程方式在导航栏正下方添加视图?

Posted

技术标签:

【中文标题】如何以编程方式在导航栏正下方添加视图?【英文标题】:How do I programmatically add a view right under the navigation bar? 【发布时间】:2017-07-07 09:05:24 【问题描述】:

我正在尝试向UINavigationController 添加一个视图,其顶部与导航栏的底部对齐。

我尝试通过将以下内容添加到我的 UINavigationController 子类来使用约束:

override func viewDidAppear(_ animated: Bool) 
           self.label = UILabel()
    self.label?.translatesAutoresizingMaskIntoConstraints = false
    self.label?.backgroundColor = UIColor.red
    self.label?.text = "label text"
    self.view.addSubview(self.label!)
    let horConstraint = NSLayoutConstraint(item: label!, attribute: .top, relatedBy: .equal,
                                           toItem: topLayoutGuide, attribute: .bottom,
                                           multiplier: 1.0, constant: 0.0)
    let widthConstr = NSLayoutConstraint(item: label!, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 100)

    let heightConstr = NSLayoutConstraint(item: label!, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 100)
    view.addConstraints([horConstraint, widthConstr, heightConstr])

结果如下:

我尝试设置子视图的框架:

override func viewDidAppear(_ animated: Bool) 

    self.label = UILabel(frame: CGRect(x: 0, y: navigationBar.frame.height, width: 300, height: 100))
    self.label?.translatesAutoresizingMaskIntoConstraints = false
    self.label?.backgroundColor = UIColor.red
    self.label?.text = "label text"
    self.view.addSubview(self.label!)


结果出来了:

在这两种情况下,我的标签都覆盖了导航栏的一部分。我该如何解决这个问题?

【问题讨论】:

尝试给 y 位置 64 【参考方案1】:

斯威夫特

NSLayoutConstraint 试试这个代码。 newView 将出现在NavigationBar 的正下方

        self.edgesForExtendedLayout = []//Optional our as per your view ladder

        let newView = UIView()
        newView.backgroundColor = .red
        self.view.addSubview(newView)
        newView.translatesAutoresizingMaskIntoConstraints = false
        if #available(ios 11.0, *) 
            let guide = self.view.safeAreaLayoutGuide
            newView.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
            newView.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
            newView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
            newView.heightAnchor.constraint(equalToConstant: 50).isActive = true
         else 
            NSLayoutConstraint(item: newView,
                               attribute: .top,
                               relatedBy: .equal,
                               toItem: view, attribute: .top,
                               multiplier: 1.0, constant: 0).isActive = true
            NSLayoutConstraint(item: newView,
                               attribute: .leading,
                               relatedBy: .equal, toItem: view,
                               attribute: .leading,
                               multiplier: 1.0,
                               constant: 0).isActive = true
            NSLayoutConstraint(item: newView, attribute: .trailing,
                               relatedBy: .equal,
                               toItem: view,
                               attribute: .trailing,
                               multiplier: 1.0,
                               constant: 0).isActive = true

                newView.heightAnchor.constraint(equalToConstant: 50).isActive = true
        
    

【讨论】:

它工作得很好,但我注意到当你推到下一个视图控制器时,导航控件下会显示黑色背景..可以解决这个问题吗? 我一直在寻找这种方法,因为一天在 swift 5 中完美运行 确认在 iOS 13+ 和 Xcode 11.3 上的工作就像一个魅力。 这也适用于 Objective-C 和 iOS 14,使用 safeAreaLayoutGuide 可以避免那些数学问题。一开始我无法确定 UIView 的顶部锚点应该连接到哪里。【参考方案2】:

状态栏的高度为 20。您在分配标签的y 时也应考虑状态栏。你的viewDidAppear 应该是

override func viewDidAppear(_ animated: Bool) 

    self.label = UILabel(frame: CGRect(x: 0, y: navigationBar.frame.height+20, width: navigationBar.frame.width, height: 100))
    self.label?.translatesAutoresizingMaskIntoConstraints = false
    self.label?.backgroundColor = UIColor.red
    self.label?.text = "label text"
    self.view.addSubview(self.label!)
 

希望对您有所帮助。快乐编码!

【讨论】:

最好设置标签的y:navigationBar.frame.height + navigationBar.frame.y【参考方案3】:

您没有使用导航栏计算状态栏的高度。总共有 64、44 导航栏和 20 状态栏

【讨论】:

【参考方案4】:

navigationBar的Frame是(0 20; 375 44),可以设置label的y位置为64。

【讨论】:

【参考方案5】:

替换这个

self.label = UILabel(frame: CGRect(x: 0, y: navigationBar.frame.height, width: 300, height: 100))

self.label = UILabel(frame: CGRect(x: 0, y: 64, width: 300, height: 100))

导航栏和状态栏的高度为 64。将其设为 y 位置

【讨论】:

【参考方案6】:
override func viewDidAppear(_ animated: Bool) 
let label = UILabel(frame: CGRect(x: 0, y: (navigationController?.navigationBar.frame.height)! + 20, width: UIScreen.main.bounds.width, height: 40))
label.translatesAutoresizingMaskIntoConstraints = true
label.text = "Hello"
label.backgroundColor = UIColor.red
self.view.addSubview(label)


【讨论】:

以上是关于如何以编程方式在导航栏正下方添加视图?的主要内容,如果未能解决你的问题,请参考以下文章

在导航栏iOS 11安全区域下定位视图

如何在 UISplitViewController 的导航栏下方添加搜索栏?

如何以编程方式设置导航栏的标题?

如何以编程方式创建标签栏控制器后添加导航界面(Swift)

iOS v10 或更低版本:如何以编程方式在导航栏底部添加 UISearchController

以编程方式获取导航栏的高度