代码之家  ›  专栏  ›  技术社区  ›  Paul Hadfield

设置标签的文本会导致堆栈视图布局问题

  •  0
  • Paul Hadfield  · 技术社区  · 6 年前

    如果我在操场上使用下面的代码示例,在尝试为其中一个标签设置text属性之前,一切看起来都很好。我把它限制为在将堆栈视图添加到UIView之前能够更改值。但是如果在将堆栈视图添加到父视图之后更改标签的文本值,那么两个标签最终会重叠(请参见底部的图像)。

    这是一个强调问题的基本测试工具,实际代码将在运行时设置值,可能是在加载视图之后,实际控制比这个更复杂。我知道这与自动布局/约束有关,但我很确定我已经正确地遵循了示例代码,但我看不出它们和我的示例之间的区别。

    import UIKit
    import PlaygroundSupport
    
    @IBDesignable
    public final class TestHarness : UIView {
    
        fileprivate let nameLabel: UILabel = {
            let label = UILabel()
            //label.font = UIFont.systemFont( ofSize: 20, weight: UIFont.Weight.medium)
            label.textAlignment = .center
            label.textColor = #colorLiteral(red: 0.6000000238, green: 0.6000000238, blue: 0.6000000238, alpha: 1)
            label.text = "Person's Name"
            label.adjustsFontSizeToFitWidth = true
            label.translatesAutoresizingMaskIntoConstraints = false
            return label
        }()
    
        fileprivate let jobTitleLabel: UILabel = {
            let label = UILabel()
            //label.font = UIFont.systemFont( ofSize: 20, weight: UIFont.Weight.medium)
            label.textAlignment = .center
            label.textColor = #colorLiteral(red: 0.6000000238, green: 0.6000000238, blue: 0.6000000238, alpha: 1)
            label.text = "Job Title"
            label.adjustsFontSizeToFitWidth = true
            label.translatesAutoresizingMaskIntoConstraints = false
            return label
        }()
    
    
        fileprivate lazy var stackView: UIStackView = {
            let stackView = UIStackView()
            stackView.axis = .vertical
            //stackView.distribution = .fill
            stackView.alignment = .center
            stackView.translatesAutoresizingMaskIntoConstraints = false
            stackView.addArrangedSubview(self.nameLabel)
            stackView.addArrangedSubview(self.jobTitleLabel)
            return stackView
        }()
    
        public required init?(coder: NSCoder) {
            super.init(coder: coder)
            initPhase2()
        }
    
        public override init(frame: CGRect) {
            super.init(frame: frame)
            initPhase2()
        }
    
        private func initPhase2() {
    
            layer.cornerRadius = 10
            layer.borderWidth = 2
            self.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
    
            jobTitleLabel.backgroundColor = #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1)
            // self.jobTitleLabel.text = "Developer" // <<-- Can set here no problem
    
            self.addSubview(stackView)
            // self.jobTitleLabel.text = "Developer" // << -- If I set this here, job title and name overlap
    
            NSLayoutConstraint.activate([
                {
                    let constraint = stackView.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor, constant: 8)
                    constraint.priority = UILayoutPriority(750)
                    return constraint
                }(),
                stackView.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 8),
                stackView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: -8),
                {
                    let constraint = stackView.bottomAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.bottomAnchor, constant: -8)
                    constraint.priority = UILayoutPriority(750)
                    return constraint
                }(),
                stackView.centerYAnchor.constraint(equalTo: layoutMarginsGuide.centerYAnchor)
            ])
        }
    
        @IBInspectable
        public var Name: String? {
            get{
                return self.nameLabel.text
            }
            set{
                self.nameLabel.text = newValue
            }
        }
    
        @IBInspectable
        public var JobTitle: String? {
            get{
                return self.jobTitleLabel.text
            }
            set{
                self.jobTitleLabel.text = newValue
            }
        }
    }
    
    let dimensions = (width: 200, height: 300)
    let control = TestHarness(frame: CGRect(x: dimensions.width / 2, y: dimensions.height / 2, width: dimensions.width, height: dimensions.height))
    // control.JobTitle = "Developer" // << -- If I set this here, job title and name overlap
    
    let view = UIView(frame: control.frame.insetBy(dx: -100, dy: -100))
    view.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
    view.addSubview(control)
    
    PlaygroundPage.current.liveView = view
    

    enter image description here

    这就是在将堆栈视图添加到父视图后更改标签文本的效果。职务与姓名标签重叠。

    enter image description here

    1 回复  |  直到 6 年前
        1
  •  1
  •   mxlbx    6 年前

    你的代码看起来不错,也许游乐场的渲染循环有问题, 我创建了一个Xcode项目并使用了您的代码,它在模拟器中运行良好,没有重叠:

        import UIKit
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let dimensions = (width: 200, height: 300)
        let control = TestHarness(frame: CGRect(x: dimensions.width / 2, y: dimensions.height / 2, width: dimensions.width, height: dimensions.height))
    
        control.JobTitle = "Developer b2.0" // << -- No overlap in simulator
    
        let contentView = UIView(frame: control.frame.insetBy(dx: -100, dy: -100))
        contentView.backgroundColor = #colorLiteral(red: 0.3098039329, green: 0.01568627544, blue: 0.1294117719, alpha: 1)
        contentView.addSubview(control)
        view.addSubview(contentView)
    }