根据标签的字体大小和图像的纵横比调整超级视图的大小

Resize superview according to label's font size and image's aspect ratio

这是一个自动布局相关的问题。我有 containerView,它有两个子视图:imageViewlabel。我想让label的fontsize根据imageView的纵横比来决定containerView的大小。

当字体大小增加时,containerViewimageView 应该变大,保持纵横比并保持 label 居中并留出一些边距,如下图所示。

而且我想以编程方式实现它。

任何帮助将不胜感激

您可以通过以下方式完成此操作:

  • 将图像视图限制在容器的所有 4 个边
  • 约束标签在容器中居中
  • 将图像视图限制为 16:9 比率
  • 将图像视图的高度限制为标签的高度 + 所需 "padding"

这是一个示例,包括增加/减小字体大小的按钮:

class WalterViewController: UIViewController {

    let theContainerView: UIView = {
        let v = UIView()
        v.backgroundColor = .blue
        return v
    }()

    let theImageView: UIImageView = {
        let v = UIImageView()
        v.backgroundColor = .red
        v.contentMode = .scaleToFill
        return v
    }()

    let theLabel: UILabel = {
        let v = UILabel()
        v.backgroundColor = .yellow
        v.textAlignment = .center
        v.text = "TEST"
        // content vertical hugging REQUIRED !!!
        v.setContentHuggingPriority(.required, for: .vertical)
        return v
    }()

    let btnUp: UIButton = {
        let b = UIButton(type: .system)
        b.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
        b.setTitle("Increase", for: .normal)
        return b
    }()

    let btnDn: UIButton = {
        let b = UIButton(type: .system)
        b.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
        b.setTitle("Decrease", for: .normal)
        return b
    }()

    let btnStack: UIStackView = {
        let v = UIStackView()
        v.axis = .horizontal
        v.spacing = 12
        v.distribution = .fillEqually
        return v
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        // we'll be using constraints
        [theContainerView, theImageView, theLabel, btnUp, btnDn, btnStack].forEach {
            [=10=].translatesAutoresizingMaskIntoConstraints = false
        }

        // add buttons to the stack
        btnStack.addArrangedSubview(btnUp)
        btnStack.addArrangedSubview(btnDn)

        // add imageView and label to container
        theContainerView.addSubview(theImageView)
        theContainerView.addSubview(theLabel)

        // add button stack and container view to view
        view.addSubview(btnStack)
        view.addSubview(theContainerView)

        // respect safe area
        let g = view.safeAreaLayoutGuide

        NSLayoutConstraint.activate([

            // horizontal button stack 20-points from top, 40-points on each side
            btnStack.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
            btnStack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
            btnStack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),

            // container view centered in view safeArea
            theContainerView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            theContainerView.centerYAnchor.constraint(equalTo: g.centerYAnchor),

            // constrain image view to its superView (container view)
            // 8-pts on all 4 sides
            theImageView.topAnchor.constraint(equalTo: theContainerView.topAnchor, constant: 8.0),
            theImageView.leadingAnchor.constraint(equalTo: theContainerView.leadingAnchor, constant: 8.0),
            theImageView.trailingAnchor.constraint(equalTo: theContainerView.trailingAnchor, constant: -8.0),
            theImageView.bottomAnchor.constraint(equalTo: theContainerView.bottomAnchor, constant: -8.0),

            // label is centered in its superView (container view)
            theLabel.centerXAnchor.constraint(equalTo: theContainerView.centerXAnchor),
            theLabel.centerYAnchor.constraint(equalTo: theContainerView.centerYAnchor),

            // constrain imageView to 16:9 ratio
            theImageView.widthAnchor.constraint(equalTo: theImageView.heightAnchor, multiplier: 16.0 / 9.0),

            // constrain imageView's height to label's height +40
            // will result in 20-pts on top and bottom
            theImageView.heightAnchor.constraint(equalTo: theLabel.heightAnchor, constant: 40.0),

        ])

        // load an image
        if let img = UIImage(named: "bkg640x360") {
            theImageView.image = img
        }

        // add targets to buttons to increase / decrease the label's font size
        btnUp.addTarget(self, action: #selector(increaseTapped(_:)), for: .touchUpInside)
        btnDn.addTarget(self, action: #selector(decreaseTapped(_:)), for: .touchUpInside)

    }

    @objc func increaseTapped(_ sender: Any?) -> Void {
        theLabel.font = theLabel.font.withSize(theLabel.font.pointSize + 1.0)
    }

    @objc func decreaseTapped(_ sender: Any?) -> Void {
        theLabel.font = theLabel.font.withSize(theLabel.font.pointSize - 1.0)
    }

}

启动时的外观(容器视图在根视图中居中):

然后,在点击增加一堆之后: