试图弄清楚UILabel的行为。

时间:2017-09-09 07:11:16

标签: swift autolayout uilabel autoresize uistackview

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

这是我目前所拥有的gif

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

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

  • 转换回肖像时,棕色按钮上的标签消失。

对于标签“L1”和“L2”我尝试过内容模式和约束,但是,我仍然会得到笨重的过渡。

对于消失的标签,不是隐藏/取消隐藏堆栈视图以使布局显示并通过它消失隐藏属性,而是尝试在堆栈视图上使用约束来处理转换,但是,结果仍然是相同。

我也看过网上并尝试了一些建议,然而,大多数答案都已过时或根本无效。

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

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()
    }
}

1 个答案:

答案 0 :(得分:0)

概述:

  • 使用单独的组件/视图控制器(更易于调试)逐步执行操作
  • 以下解决方案仅适用于标签L1和L2。
  • 对于计算器按钮,最好使用UICollectionViewController。 (我还没有实现它,添加为子视图控制器)

代码:

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)
}