【问题标题】:What is wrong with this StackView?这个 StackView 有什么问题?
【发布时间】:2021-02-27 21:14:20
【问题描述】:

我的 StackView 有什么问题? 这是代码:

class PushUpViewController: UIViewController {

        override func viewDidLoad() {
            super.viewDidLoad()
            
            view.backgroundColor = .white
            setUpStackView()
        }
        
            func setUpStackView() {
            // SetUp StackView:
            stackView.translatesAutoresizingMaskIntoConstraints = false
            stackView.axis = .vertical
                stackView.alignment = .center
                stackView.distribution = .fillProportionally
            stackView.spacing = 50
            view.addSubview(stackView)
            
            // SetUp StackView Constraints:
                stackView.pin(to: view)
                stackView.setCustomSpacing(50, after: PushUpButton)
                stackView.setCustomSpacing(100, after: TimeLabel)
            
            // Set Elements to StackView:
            stackView.addArrangedSubview(TimeLabel)
            stackView.addArrangedSubview(PushUpButton)
            stackView.addArrangedSubview(secondStackView)
            

       // SetUp PushUpButton:
           PushUpButton.backgroundColor = .white
           PushUpButton.setTitle("\(count)", for: .normal)
           PushUpButton.setTitleColor(.systemGray, for: .normal)
           PushUpButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 70)
           
           
           PushUpButton.translatesAutoresizingMaskIntoConstraints = false
           
                PushUpButton.heightAnchor.constraint(equalToConstant: 300).isActive = true
                PushUpButton.widthAnchor.constraint(equalToConstant: 150).isActive = true
           
       
    // SetUp TimeLabel
           TimeLabel.textAlignment = .center
                   TimeLabel.text = "\(counter)"
                   TimeLabel.textColor = .black
                   TimeLabel.font = .boldSystemFont(ofSize: 30)
                   self.view.addSubview(TimeLabel)
                   
                   TimeLabel.translatesAutoresizingMaskIntoConstraints = false
                   
       
                TimeLabel.widthAnchor.constraint(equalToConstant: 300).isActive = true
                TimeLabel.heightAnchor.constraint(equalToConstant: 200).isActive = true
        
      
            
            
            // SetUp SecondStackView
            secondStackView.translatesAutoresizingMaskIntoConstraints = false
            secondStackView.axis = .horizontal
            secondStackView.alignment = .center
            secondStackView.distribution = .fillEqually
                secondStackView.spacing = 20
            
            
            // SetUp SecondStackView Constrains
                secondStackView.heightAnchor.constraint(equalToConstant: 50).isActive = true
                secondStackView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -15).isActive = true
            
            
            // Set Elements:
            secondStackView.addArrangedSubview(breakButton)
            secondStackView.addArrangedSubview(stopbutton)
            
            //SetUp BreakButton
                  breakButton.backgroundColor = .lightGray
                  breakButton.setTitle("Break", for: .normal)
                  breakButton.setTitle("Start", for: .selected)
            breakButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
                  breakButton.setTitleColor(.white, for: .normal)
                  breakButton.layer.cornerRadius = 12
                  breakButton.layer.borderWidth = 1
                  breakButton.layer.borderColor = UIColor.white.cgColor
//               breakButton.addTarget(self, action: #selector(BreakButtonTapped), for: .touchUpInside)
                  
                  
                  breakButton.translatesAutoresizingMaskIntoConstraints = false
                  
               NSLayoutConstraint.activate([
                  breakButton.widthAnchor.constraint(equalToConstant: 150),
                  breakButton.heightAnchor.constraint(equalToConstant: 50)
               ])
              
                
               
              
              // SetUp StopButton:
                  stopbutton.backgroundColor = .systemRed
                  stopbutton.setTitle("Stop", for: .normal)
                  stopbutton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
                  stopbutton.setTitleColor(.white, for: .normal)
                  stopbutton.layer.cornerRadius = 12
                  stopbutton.layer.borderWidth = 1
                  stopbutton.layer.borderColor = UIColor.white.cgColor
//               stopbutton.addTarget(self, action: #selector(stopButtonTapped), for: .touchUpInside)
                  
                  
                  stopbutton.translatesAutoresizingMaskIntoConstraints = false
                  
               NSLayoutConstraint.activate([
                  stopbutton.widthAnchor.constraint(equalToConstant: 150),
                  stopbutton.heightAnchor.constraint(equalToConstant: 50)
                  ])
            
            
            }
    }
        
    
    
   

这就是它的外观:

但它应该是这样的:

这是我在 StackView VC 上时控制台中出现的内容:

我不知道这意味着什么或者我应该怎么做才能解决这个问题

我不了解 StackViews...我看了很多 yt 教程,但它们都一样,对我没有帮助。我最大的问题是StackView的分布:不知道区别在哪里

【问题讨论】:

  • 您是否希望您的“时间标签”位于(或接近)顶部...您的按钮位于底部...并且您的“PushUpButton”(大零?)为 300x150并在它们之间垂直居中?
  • @DonMag 我想要第二张图片

标签: swift autolayout constraints uistackview


【解决方案1】:

第一个提示:忘记在堆栈视图中使用.fillProportionally。它几乎从未使用过……当它使用时,它是出于非常特定的原因而使用的。

第二个提示:在开发过程中,为您的 UI 元素提供对比鲜明的背景颜色,以便在运行时轻松查看框架。

第三个技巧:使用leadingLowerCase 作为变量和函数名...使用LeadingUpperCase 作为类名。

第四个技巧:将相似的代码组合在一起 - 例如设置视图属性、设置约束等 - 并包含逻辑 cmets 以便更轻松地跟踪您的代码正在执行的操作。

看看这个:

class PushUpViewController: UIViewController {
    
    let stackView = UIStackView()
    let secondStackView = UIStackView()
    let pushUpButton = UIButton()
    let breakButton = UIButton()
    let stopbutton = UIButton()
    let timeLabel = UILabel()
    
    var count: Int = 0
    var counter: Float = 0.0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .white
        setUpStackView()
    }
    
    func setUpStackView() {
        
        // SetUp StackView:
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .vertical
        stackView.alignment = .fill
        stackView.distribution = .fill

        // SetUp timeLabel
        timeLabel.textAlignment = .center
        timeLabel.text = "\(counter)"
        timeLabel.textColor = .black
        timeLabel.font = .boldSystemFont(ofSize: 30)

        // SetUp pushUpButton:
        pushUpButton.backgroundColor = .white
        pushUpButton.setTitle("\(count)", for: .normal)
        pushUpButton.setTitleColor(.systemGray, for: .normal)
        pushUpButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 70)
        
        // SetUp secondStackView
        secondStackView.axis = .horizontal
        secondStackView.alignment = .fill
        secondStackView.distribution = .fillEqually
        secondStackView.spacing = 20
        
        //SetUp breakButton
        breakButton.backgroundColor = .lightGray
        breakButton.setTitle("Break", for: .normal)
        breakButton.setTitle("Start", for: .selected)
        breakButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
        breakButton.setTitleColor(.white, for: .normal)
        breakButton.layer.cornerRadius = 12
        breakButton.layer.borderWidth = 1
        breakButton.layer.borderColor = UIColor.white.cgColor
        
        // SetUp stopButton:
        stopbutton.backgroundColor = .systemRed
        stopbutton.setTitle("Stop", for: .normal)
        stopbutton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
        stopbutton.setTitleColor(.white, for: .normal)
        stopbutton.layer.cornerRadius = 12
        stopbutton.layer.borderWidth = 1
        stopbutton.layer.borderColor = UIColor.white.cgColor

        // add buttons to horizontal second stack view
        secondStackView.addArrangedSubview(breakButton)
        secondStackView.addArrangedSubview(stopbutton)

        // if we want the center PushUpButton to be 300 x 150
        //  and centered vertically
        //  we need to embed it in a clear view
        let holderView = UIView()
        
        // add PushUpButton to holderView
        holderView.addSubview(pushUpButton)

        // views added as arrangedSubviews of a stack view automatically get
        //  .translatesAutoresizingMaskIntoConstraints = false
        // but, because we're adding the PushUpButton as a subview
        //  of holderView, we need to set it here
        pushUpButton.translatesAutoresizingMaskIntoConstraints = false
        

        // add views to stack view
        stackView.addArrangedSubview(timeLabel)
        stackView.addArrangedSubview(holderView)
        stackView.addArrangedSubview(secondStackView)

        // add stackView to view
        view.addSubview(stackView)
        
        // SetUp StackView Constraints:
        //stackView.pin(to: view)
        
        // respect safe-area
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            
            // constrain stackview to full view (safe-area)
            
            // to bottom with Zero extra space
            stackView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),

            // to top with 20-pts "padding"
            stackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
            
            // and 8-pts "padding" on each side
            stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
            stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
            
            // pushUpButton should be 300x150
            pushUpButton.widthAnchor.constraint(equalToConstant: 300.0),
            pushUpButton.heightAnchor.constraint(equalToConstant: 150.0),
            
            // pushUpButton should be centered in holderView
            pushUpButton.centerXAnchor.constraint(equalTo: holderView.centerXAnchor),
            pushUpButton.centerYAnchor.constraint(equalTo: holderView.centerYAnchor),
            
            // bottom buttons should have Height: 50
            secondStackView.heightAnchor.constraint(equalToConstant: 50.0),
            
        ])

        // break and stop button actions
        //breakButton.addTarget(self, action: #selector(BreakButtonTapped), for: .touchUpInside)
        //stopbutton.addTarget(self, action: #selector(stopButtonTapped), for: .touchUpInside)

        // during development, so we can see the layout easily
        //holderView.backgroundColor = .yellow
        //PushUpButton.backgroundColor = .green
        //TimeLabel.backgroundColor = .cyan
        
    }
}

iPhone 11 上的结果:

在 iPhone 8 上:

以及在开发过程中提供帮助的背景颜色:

附加提示:

在学习自动布局(尤其是堆栈视图)时,请在 Storyboard / Interface Builder 中处理您的布局。您可以立即看到它的外观以及更改值/属性时会发生什么。您还可以更改 View as: 以立即查看它在不同设备/屏幕尺寸上的外观。如果您想将所有内容保存在代码中,一旦您的布局看起来像您想要的那样,然后在代码中复制这些约束和设置。

【讨论】:

  • 太好了,非常感谢!
猜你喜欢
  • 2012-05-26
  • 2021-08-20
  • 2015-09-23
  • 2012-03-10
  • 2010-11-01
  • 2011-08-26
  • 2020-04-16
  • 1970-01-01
  • 2016-06-28
相关资源
最近更新 更多