【问题标题】:Why is my StackView not working? Elements are completely displaced为什么我的 StackView 不工作?元素完全移位
【发布时间】:2020-10-27 10:03:55
【问题描述】:

嘿,我的 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
        
        ```

【问题讨论】:

    标签: swift constraints uistackview


    【解决方案1】:

    我只是为 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
    

    【讨论】:

      【解决方案2】:

      您做错了很多事情...阅读一些有关自动布局和使用 UIStackView 的教程非常值得。

      首先,如果您将视图(图像视图、文本字段、标签、按钮等)添加到堆栈视图,不要也给这些视图位置约束.这就是堆栈视图正在做的事情。

      其次,添加视图后:

      stackView.addArrangedSubview(profilePicture)
      

      不要然后像这样将其添加为子视图:

      view.addSubview(profilePicture)
      

      这样做将从堆栈视图中删除 profilePicture

      查看您的代码——查看我进行更改的 cmets:

      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 磅的垂直间距,并且为每个元素设置了明确的高度,您可能会发现它并不“完全适合”不同的设备/屏幕尺寸。

      因此,正如您在上一个问题中向您指出的那样:Why is my VC displaced after changing the Simulator? AutoLayout - 您可能希望将堆栈视图的分布更改为等间距并添加底部约束:

          stackView.distribution = .equalSpacing
          stackView.spacing = 0
      
          stackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20).isActive = true
      

      这可能会或可能不会完全满足您的需求,但这是一个起点。

      【讨论】:

        【解决方案3】:

        我认为你的约束有问题。

        profilePicture.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true profilePicture.topAnchor.constraint(equalTo: view.topAnchor, constant: 110).isActive = true

        试图在屏幕的中心,但它们在堆栈视图内。在这种情况下,您还必须为堆栈视图提供静态高度。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-05-26
          • 1970-01-01
          • 2011-04-07
          • 2020-10-11
          • 1970-01-01
          • 2022-06-13
          • 2012-05-12
          • 1970-01-01
          相关资源
          最近更新 更多