swift - 试图理解 UILabel 的行为。

标签 swift autolayout uilabel autoresize uistackview

我正在尝试复制 Apple 的计算器 UI 布局。

这是一个gif到目前为止我所拥有的。

我遇到的问题大多与 UILables 有关。 如上面的 gif 所示,我遇到了以下问题:

  • 在设备旋转时,标签“L1”和“L2”弹出,而不是平滑过渡。

  • 棕色按钮上的标签在转换回纵向时消失。

对于标签“L1”和“L2”,我已尝试使用内容模式和约束进行试验,但是,我仍然遇到笨拙的过渡。

至于消失的标签,我没有隐藏/取消隐藏堆栈 View 以使布局通过它的隐藏属性出现和消失,而是尝试使用堆栈 View 上的约束来处理转换,但是,结果仍然是一样。

我也在网上查看并尝试了一些建议,但是,大多数答案都已过时或根本不起作用。

代码非常简单,主要包括设置 View 及其约束。

extension UIStackView {
    convenience init(axis: UILayoutConstraintAxis, distribution: UIStackViewDistribution = .fill) {
        self.init()
        self.axis = axis
        self.distribution = distribution
        self.translatesAutoresizingMaskIntoConstraints = false
    }
}

class Example: UIView {
    let mainStackView = UIStackView(axis: .vertical, distribution: .fill)
    let subStackView = UIStackView(axis: .horizontal, distribution: .fillProportionally)
    let portraitStackView = UIStackView(axis: .vertical, distribution: .fillEqually)
    let landscapeStackView = UIStackView(axis: .vertical, distribution: .fillEqually)

    var containerView: UIView = {
        $0.backgroundColor = .darkGray
        $0.translatesAutoresizingMaskIntoConstraints = false
        return $0
    }(UIView(frame: .zero))

    let mainView: UIView = {
        $0.backgroundColor = .blue
        $0.translatesAutoresizingMaskIntoConstraints = false
        return $0
    }(UIView(frame: .zero))

    let labelView: UIView = {
        $0.backgroundColor = .red
        $0.translatesAutoresizingMaskIntoConstraints = false
        return $0
    }(UIView(frame: .zero))

    var labelOne: UILabel!
    var labelTwo: UILabel!

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .red
        autoresizingMask = [.flexibleWidth, .flexibleHeight]

        labelOne = createLabel(text: "L1")
        labelOne.translatesAutoresizingMaskIntoConstraints = false
        labelOne.backgroundColor = .darkGray
        labelTwo = createLabel(text: "L2")
        labelTwo.translatesAutoresizingMaskIntoConstraints = false
        labelTwo.backgroundColor = .black

        landscapeStackView.isHidden = true

        mainView.addSubview(labelView)
        labelView.addSubview(labelOne)
        labelView.addSubview(labelTwo)
        addSubview(mainStackView)
        mainStackView.addArrangedSubview(mainView)

        setButtonStackView()
        setStackViewConstriants()
        setDisplayViewConstriants()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setStackViewConstriants() {
        mainStackView.translatesAutoresizingMaskIntoConstraints = false
        mainStackView.topAnchor.constraint(equalTo: topAnchor).isActive = true
        mainStackView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
        mainStackView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
        mainStackView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
    }

    func setDisplayViewConstriants() {
        mainView.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 288/667).isActive = true

        labelView.heightAnchor.constraint(equalTo: mainView.heightAnchor, multiplier: 128/288).isActive = true
        labelView.centerYAnchor.constraint(equalTo: mainView.centerYAnchor).isActive = true
        labelView.leadingAnchor.constraint(equalTo: mainView.leadingAnchor, constant: 24).isActive = true
        labelView.trailingAnchor.constraint(equalTo: mainView.trailingAnchor, constant: -24).isActive = true

        labelOne.heightAnchor.constraint(equalTo: labelTwo.heightAnchor, multiplier: 88/32).isActive = true
        labelOne.trailingAnchor.constraint(equalTo: labelView.trailingAnchor).isActive = true
        labelOne.leadingAnchor.constraint(equalTo: labelView.leadingAnchor).isActive = true
        labelOne.topAnchor.constraint(equalTo: labelView.topAnchor).isActive = true

        labelTwo.topAnchor.constraint(equalTo: labelOne.bottomAnchor).isActive = true
        labelTwo.trailingAnchor.constraint(equalTo: labelView.trailingAnchor).isActive = true
        labelTwo.leadingAnchor.constraint(equalTo: labelOne.leadingAnchor).isActive = true
        labelTwo.bottomAnchor.constraint(equalTo: labelView.bottomAnchor).isActive = true
    }

    func createLabel(text: String) -> UILabel {
        let label = UILabel(frame: .zero)
        label.text = text
        label.font = UIFont.init(name: "Arial-BoldMT", size: 60)
        label.textColor = .white
        label.textAlignment = .right
        label.contentMode = .right
        label.minimumScaleFactor = 0.1
        label.adjustsFontSizeToFitWidth = true
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }

    func createButton(text: String) -> UIButton {
        let button = UIButton(type: .custom)
        button.setTitle(text, for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.layer.borderColor = UIColor.white.cgColor
        button.layer.borderWidth = 1
        button.titleLabel?.font = UIFont.init(name: "Arial-BoldMT", size: 60)
        button.titleLabel?.minimumScaleFactor = 0.1
        button.titleLabel?.adjustsFontSizeToFitWidth = true
        button.titleLabel?.translatesAutoresizingMaskIntoConstraints = false
        button.titleLabel?.leadingAnchor.constraint(equalTo: button.leadingAnchor).isActive = true
        button.titleLabel?.trailingAnchor.constraint(equalTo: button.trailingAnchor).isActive = true
        button.titleLabel?.topAnchor.constraint(equalTo: button.topAnchor).isActive = true
        button.titleLabel?.bottomAnchor.constraint(equalTo: button.bottomAnchor).isActive = true
        button.titleLabel?.textAlignment = .center
        button.titleLabel?.contentMode = .scaleAspectFill
        button.titleLabel?.numberOfLines = 0
        return button
    }

    func setButtonStackView() {
        for _ in 1...5 {
            let stackView = UIStackView(axis: .horizontal, distribution: .fillEqually)
            for _ in 1...4 {
                let button = createButton(text: "0")
                button.backgroundColor = .brown
                stackView.addArrangedSubview(button)
            }
            landscapeStackView.addArrangedSubview(stackView)
        }

        for _ in 1...5 {
            let stackView = UIStackView(axis: .horizontal, distribution: .fillEqually)
            for _ in 1...4 {
                let button = createButton(text: "0")
                button.backgroundColor = .purple
                stackView.addArrangedSubview(button)
            }
            portraitStackView.addArrangedSubview(stackView)
        }

        subStackView.addArrangedSubview(landscapeStackView)
        subStackView.addArrangedSubview(portraitStackView)
        mainStackView.addArrangedSubview(subStackView)
    }

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        if UIDevice.current.orientation.isLandscape && landscapeStackView.isHidden == true {
            self.landscapeStackView.isHidden = false
        }
        if UIDevice.current.orientation.isPortrait && landscapeStackView.isHidden == false {
            self.landscapeStackView.isHidden = true
        }
        self.layoutIfNeeded()
    }
}

最佳答案

概述:

  • 使用单独的组件/ View Controller 以增量方式执行操作(更易于调试)
  • 以下解决方案仅适用于标签 L1 和 L2。
  • 对于计算器按钮,最好使用 UICollectionViewController。 (我没有实现,添加为 subview Controller )

代码:

private func setupLabels() {
    
    view.backgroundColor = .red
    
    let stackView           = UIStackView()
    stackView.axis          = .vertical
    stackView.alignment     = .fill
    stackView.distribution  = .fill
    
    stackView.translatesAutoresizingMaskIntoConstraints = false
    
    view.addSubview(stackView)
    
    stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    stackView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true
    
    
    let label1 = UILabel()
    label1.text             = "L1"
    label1.textColor        = .white
    label1.backgroundColor  = .darkGray
    label1.textAlignment    = .right
    label1.font = UIFont.preferredFont(forTextStyle: .title1)
    
    
    let label2 = UILabel()
    label2.text             = "L2"
    label2.textColor        = .white
    label2.backgroundColor  = .black
    label2.textAlignment    = .right
    label2.font = UIFont.preferredFont(forTextStyle: .caption1)
    
    stackView.addArrangedSubview(label1)
    stackView.addArrangedSubview(label2)
}

关于swift - 试图理解 UILabel 的行为。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46128100/

相关文章:

ios - 从 Table View controller 到 Tab Bar Controller

ios - 以编程方式使用 addSubview 时,Swift 3 UIView 不呈现 UILabel

ios - 如何在堆栈 View 中居中对齐 View ,而不是拉伸(stretch)任何 View 或分布?

swift - 将数组计数分配给 tableviewcell 标签

ios - 具有多个链接的 UILabel

iOS 只旋转 subview Controller 之一

ios - Swift 准备 Segue : How to know If a button or a table row initiated Segue

json - Swift Siesta 编辑获取的实体

ios - 使用下一个上层对象的 anchor

ios - 使用自动布局自动调整 UIPopoverController 的大小