Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 为什么我的StackView不工作?元素被完全置换_Swift_Constraints_Uistackview - Fatal编程技术网

Swift 为什么我的StackView不工作?元素被完全置换

Swift 为什么我的StackView不工作?元素被完全置换,swift,constraints,uistackview,Swift,Constraints,Uistackview,嘿,我的StackView什么都没做,有两个问题: 首先,当我转动模拟器或更换设备时,VC上的元素完全移位,因此StackView没有做它应该做的事情! 第二件事是StackView覆盖了导航栏,我不知道如何使其可见。 有人能帮我吗 import UIKit class RegisterViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

嘿,我的StackView什么都没做,有两个问题: 首先,当我转动模拟器或更换设备时,VC上的元素完全移位,因此StackView没有做它应该做的事情! 第二件事是StackView覆盖了导航栏,我不知道如何使其可见。 有人能帮我吗

import UIKit


class RegisterViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
    let stackView = UIStackView()
    
    
    var profilePicture = UIButton()
    var profileIcon = UIImage()
    let usernameTextField = UITextField()
    let emailTextField = UITextField()
    let passswordTextField = UITextField()
    let signInButton = UIButton()
    
    
   
    

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationController?.navigationBar.prefersLargeTitles = true
        navigationItem.title = "Create an Account"
        view.backgroundColor = .white
        
        
        
        
        
        // SetUp StackView:
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .vertical
        stackView.alignment = .center
        stackView.distribution = .fillEqually
        stackView.spacing = 50
        view.addSubview(stackView)
       
        
        // SetUp Stack View Constraints:
       
        stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
        stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
               
        
        //Add Elements
        
        stackView.addArrangedSubview(profilePicture)
        stackView.addArrangedSubview(usernameTextField)
        stackView.addArrangedSubview(passswordTextField)
        stackView.addArrangedSubview(signInButton)
        
        
    
    
// MARK: - Set-Up View-Elements
    
    
    // SetUp ProfileIcon:
        profileIcon = UIImage(named: "characteer")!
        profilePicture.setImage(profileIcon, for: .normal)
        profilePicture.imageView?.contentMode = .scaleAspectFill
        let cornerRadius: CGFloat
         cornerRadius = 75 // half of widht/height
        profilePicture.layer.cornerRadius = cornerRadius
        profilePicture.layer.masksToBounds = true
        profilePicture.layer.borderWidth = 1
        profilePicture.layer.borderColor = UIColor.white.cgColor
        profilePicture.addTarget(self, action: #selector(handleSelectedPhoto), for: .touchUpInside)
        
        
        view.addSubview(profilePicture)
        
       profilePicture.translatesAutoresizingMaskIntoConstraints = false
       profilePicture.heightAnchor.constraint(equalToConstant: 150).isActive = true
       profilePicture.widthAnchor.constraint(equalToConstant: 150).isActive = true
       profilePicture.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        profilePicture.topAnchor.constraint(equalTo: view.topAnchor, constant: 110).isActive = true
        
     
        
        // SetUp UsernameTextfield:
    usernameTextField.backgroundColor = .white
    usernameTextField.attributedPlaceholder = NSAttributedString(string: "Username", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
    usernameTextField.textAlignment = NSTextAlignment.center
    usernameTextField.layer.cornerRadius = 8
    usernameTextField.layer.borderWidth = 1
    usernameTextField.layer.borderColor = UIColor.lightGray.cgColor
    self.view.addSubview(usernameTextField)
    let username = usernameTextField.text
    
    usernameTextField.translatesAutoresizingMaskIntoConstraints = false
    
    usernameTextField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
    usernameTextField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
    usernameTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
    usernameTextField.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    
        
    
// SetUpEmailTextfield:
    emailTextField.backgroundColor = .white
           emailTextField.attributedPlaceholder = NSAttributedString(string: "Email", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
           emailTextField.textAlignment = NSTextAlignment.center
           emailTextField.layer.cornerRadius = 8
           emailTextField.layer.borderWidth = 1
           emailTextField.layer.borderColor = UIColor.lightGray.cgColor
           self.view.addSubview(emailTextField)
           
           emailTextField.translatesAutoresizingMaskIntoConstraints = false
           emailTextField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
           emailTextField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
           emailTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
           emailTextField.topAnchor.constraint(equalTo: usernameTextField.bottomAnchor, constant: 20).isActive = true
        
        ```

我认为你的约束有问题

profilePicture.centerXAnchor.constraint(equalTo:view.centerXAnchor).isActive=true profilePicture.topAnchor.constraint(equalTo:view.topAnchor,常量:110)。isActive=true


正在尝试使屏幕居中,但它们位于堆栈视图内。在这种情况下,您还必须为堆栈视图提供一个静态高度。

我只是为profilePicture和usernameTextField设置了一个静态高度,但对于其他视图,它是相同的。代码错误的一面是关于约束的,您将对象添加到两个不同的视图中。有一个解决办法

    let stackView = UIStackView()
    
    
    var profilePicture = UIButton()
    var profileIcon = UIImage()
    let usernameTextField = UITextField()
    let emailTextField = UITextField()
    let passswordTextField = UITextField()
    let signInButton = UIButton()
    
    
   
    

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationController?.navigationBar.prefersLargeTitles = true
        navigationItem.title = "Create an Account"
        view.backgroundColor = .white
        
        
        
        
        
        // SetUp StackView:
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .vertical
        stackView.alignment = .center
        stackView.distribution = .fillEqually
        stackView.spacing = 50
        view.addSubview(stackView)
       
        
        // SetUp Stack View Constraints:
       
        stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
        stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
        stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
               
        
        //Add Elements
        
        stackView.addArrangedSubview(profilePicture)
        stackView.addArrangedSubview(usernameTextField)
        
        
    
    
// MARK: - Set-Up View-Elements
    
    
    // SetUp ProfileIcon:
       profileIcon = UIImage(named: "characteer")!
        profilePicture.setImage(profileIcon, for: .normal)
        profilePicture.imageView?.contentMode = .scaleAspectFill
        let cornerRadius: CGFloat
         cornerRadius = 75 // half of widht/height
        profilePicture.layer.cornerRadius = cornerRadius
        profilePicture.layer.masksToBounds = true
        profilePicture.layer.borderWidth = 1
        profilePicture.layer.borderColor = UIColor.white.cgColor
        //profilePicture.addTarget(self, action: #selector(handleSelectedPhoto), for: .touchUpInside)
        
        
       profilePicture.translatesAutoresizingMaskIntoConstraints = false
       profilePicture.heightAnchor.constraint(equalToConstant: 150).isActive = true
       profilePicture.widthAnchor.constraint(equalToConstant: 150).isActive = true
        
     
        
        // SetUp UsernameTextfield:
    usernameTextField.backgroundColor = .white
    usernameTextField.attributedPlaceholder = NSAttributedString(string: "Username", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
    usernameTextField.textAlignment = NSTextAlignment.center
    usernameTextField.layer.cornerRadius = 8
    usernameTextField.layer.borderWidth = 1
    usernameTextField.layer.borderColor = UIColor.lightGray.cgColor
    let username = usernameTextField.text
    
    usernameTextField.translatesAutoresizingMaskIntoConstraints = false
        usernameTextField.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width-40).isActive = true
    usernameTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true

你做了很多错事。。。阅读一些关于自动布局和使用
UIStackView
的教程是非常值得的

首先,如果将视图(图像视图、文本字段、标签、按钮等)添加到堆栈视图中,也会为这些视图提供位置约束。这就是堆栈视图所做的

其次,添加视图后:

stackView.addArrangedSubview(profilePicture)
不要然后将其添加为子视图,如下所示:

view.addSubview(profilePicture)
这样做将从堆栈视图中删除
profilePicture

查看您的代码--查看我所做更改的注释:

class RegisterViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
    let stackView = UIStackView()
    
    var profilePicture = UIButton()
    var profileIcon = UIImage()
    let usernameTextField = UITextField()
    let emailTextField = UITextField()
    let passswordTextField = UITextField()
    let signInButton = UIButton()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationController?.navigationBar.prefersLargeTitles = true
        navigationItem.title = "Create an Account"
        view.backgroundColor = .white
        
        
        // SetUp StackView:
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .vertical
        stackView.alignment = .center
        
        // distribution should be .fill  NOT  .fillEqually
        stackView.distribution = .fill
        
        stackView.spacing = 50
        view.addSubview(stackView)
        
        // SetUp Stack View Constraints:
        
        stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
        stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        
        //Add Elements
        
        stackView.addArrangedSubview(profilePicture)
        stackView.addArrangedSubview(usernameTextField)
        stackView.addArrangedSubview(emailTextField)
        stackView.addArrangedSubview(passswordTextField)
        stackView.addArrangedSubview(signInButton)
        
        // MARK: - Set-Up View-Elements
        
        // SetUp ProfileIcon:
        //profileIcon = UIImage(named: "characteer")!
        profileIcon = UIImage(named: "pro1")!
        profilePicture.setImage(profileIcon, for: .normal)
        profilePicture.imageView?.contentMode = .scaleAspectFill
        let cornerRadius: CGFloat
        cornerRadius = 75 // half of widht/height
        profilePicture.layer.cornerRadius = cornerRadius
        profilePicture.layer.masksToBounds = true
        profilePicture.layer.borderWidth = 1
        profilePicture.layer.borderColor = UIColor.white.cgColor
        //profilePicture.addTarget(self, action: #selector(handleSelectedPhoto), for: .touchUpInside)
        
        // NO - it's already in the stack view
        //view.addSubview(profilePicture)
        
        // Set Only Width and Height - position is managed by the stack view
        profilePicture.heightAnchor.constraint(equalToConstant: 150).isActive = true
        profilePicture.widthAnchor.constraint(equalToConstant: 150).isActive = true
        
        // SetUp UsernameTextfield:
        usernameTextField.backgroundColor = .white
        usernameTextField.attributedPlaceholder = NSAttributedString(string: "Username", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
        usernameTextField.textAlignment = NSTextAlignment.center
        usernameTextField.layer.cornerRadius = 8
        usernameTextField.layer.borderWidth = 1
        usernameTextField.layer.borderColor = UIColor.lightGray.cgColor

        // NO - it's already in the stack view
        //  self.view.addSubview(usernameTextField)
        let username = usernameTextField.text
        
        // Set Only Width and Height - position is managed by the stack view
        usernameTextField.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
        usernameTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
        
        // SetUpEmailTextfield:
        emailTextField.backgroundColor = .white
        emailTextField.attributedPlaceholder = NSAttributedString(string: "Email", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
        emailTextField.textAlignment = NSTextAlignment.center
        emailTextField.layer.cornerRadius = 8
        emailTextField.layer.borderWidth = 1
        emailTextField.layer.borderColor = UIColor.lightGray.cgColor

        // NO - it's already in the stack view
        //  self.view.addSubview(emailTextField)
        
        // Set Only Width and Height - position is managed by the stack view
        emailTextField.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
        emailTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
        
        // SetUp PasswordTextfield:
        passswordTextField.backgroundColor = .white
        passswordTextField.attributedPlaceholder = NSAttributedString(string: "Password", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
        passswordTextField.textAlignment = NSTextAlignment.center
        passswordTextField.layer.cornerRadius = 8
        passswordTextField.layer.borderWidth = 1
        passswordTextField.layer.borderColor = UIColor.lightGray.cgColor

        // NO - it's already in the stack view
        //  self.view.addSubview(emailTextField)
        
        // Set Only Width and Height - position is managed by the stack view
        passswordTextField.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
        passswordTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
        
        signInButton.setTitle("Sign In", for: [])
        signInButton.backgroundColor = .blue

        // Set Only Width and Height - position is managed by the stack view
        signInButton.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
        signInButton.heightAnchor.constraint(equalToConstant: 50).isActive = true

    }

}
当然,使用这种布局——您指定了50个点的元素之间的垂直间距,并且为每个元素设置了明确的高度,您可能会发现它在不同的设备/屏幕尺寸上“不太合适”

因此,正如您在前面的问题中指出的:-您可能希望将堆栈视图的分布更改为等间距,并添加底部约束:

    stackView.distribution = .equalSpacing
    stackView.spacing = 0

    stackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20).isActive = true
这可能会也可能不会给你想要的,但这是一个起点