首页 > 解决方案 > 尽管使用了 safeAreaLayoutGuide,但以编程方式在视图中创建约束并不是导航控制器的原因

问题描述

我创建了一个 UINavigationController 类,它允许用户注销并显示应用程序的标题。然后,我在其 viewControllers 数组中添加了一个 UITabController 作为其唯一的 viewController:

let homeController = HomeController()

viewControllers = [homeController]

这个 UITabController (HomeController()) 然后填充了一些 UIViewControllers - 其中一个将显示一个 Profile 页面。这是我的第一个项目,我不会使用故事板,所以事情是一个很大的挑战!

我在类中和我的个人资料页面的 viewDidLoad 中创建了一个 UIImageView 对象,我使用:self.view.addSubview(imageView)添加到视图,然后:imageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true试图将图像锚定到屏幕顶部的 UINavigationController 栏的底部。然而,结果将图像放在屏幕的最顶部,就好像导航栏不被识别为可见一样。我在这篇文章中读到:https ://medium.com/@amlcurran/a-quick-guide-to-laying-out-views-in-ios-471e92deb74,'.topLayoutGuide.bottomAnchor' 代表导航的底部吧,但这现在已经贬值到我上面的例子了。有没有人知道什么是错的?还有任何好的资源让我完全理解以编程方式约束我的元素!谢谢大家!

https://gist.github.com/JoeMcGeever/a5ce3be94fc49a8f27b1a2867bd9495b

该链接显示了到目前为止的一些代码 - 我知道其他元素也固定在顶部;我只是想先解决这个关于导航栏的错误。

显示当前视图显示内容的图像

标签: iosswift

解决方案


您真的应该阅读几个自动布局教程。那里有很多很多。在你完成了十几个工作之后,你应该对需要做什么有一个很好的了解。

与此同时,这是您的ProfileViewController 编辑,让您了解自己做错了什么:

class ProfileViewController : UIViewController {
    
    let imageView : UIImageView = { //creates an image view with the name "imageView"
        let image = UIImage(named: "logo")
        let imageView = UIImageView(image: image)
        return imageView
    }()
    
    let usernameLabel = UILabel()
    
    // if you're addint a target referring to "self", this must be a lazy var
    lazy var editProfileButton : UIButton = {
        let editButton = UIButton()
        editButton.backgroundColor = .orange
        editButton.setTitle("Edit Profile", for: .normal)
        editButton.setTitleColor(.white, for: .normal)
        editButton.addTarget(self, action: #selector(handleEdit), for: .touchUpInside)
        return editButton
    }()
    
    @objc func handleEdit(){
        //edit handle button
        print("Edit profile")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = UIColor.white
        
        self.title = "Profile"
        
        usernameLabel.text = "Username Here"
        
        // we're going to use auto-layout
        [imageView, usernameLabel, editProfileButton].forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
        }
        
        self.view.addSubview(imageView)
        self.view.addSubview(usernameLabel)
        self.view.addSubview(editProfileButton)
        
        // need FULL sets of constraints, not just TOP anchors
        
        // respect safe-area
        let g = view.safeAreaLayoutGuide
        
        NSLayoutConstraint.activate([
            
            // image view at upper-left
            // image view 8-pts from top of safe area
            imageView.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
            // and 8-pts from left
            imageView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
            // give it a width of, for example, one-quarter the view width
            imageView.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.25),
            // give it a 1:1 ratio (square)
            imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor),
            
            // button at upper-right
            editProfileButton.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
            editProfileButton.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
            // no width or height... let the button size itself
            
            // label below the image view
            usernameLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 8.0),
            usernameLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
            // no width or height... let the label size itself

        ])
        
        // give the name label a background color so we can see its frame
        usernameLabel.backgroundColor = .cyan
        
    }
    
}

查看代码中的注释以了解我做了什么。

结果看起来像这样(我使用了一个随机图像作为徽标):

在此处输入图像描述


推荐阅读