以编程方式根据行数动态调整 UILabel 的大小

Posted

技术标签:

【中文标题】以编程方式根据行数动态调整 UILabel 的大小【英文标题】:Dynamically adjust size of UILabel according to the number of lines programmatically 【发布时间】:2017-02-18 20:01:48 【问题描述】:

我有一个 View,我在其中创建了一个 numberOfLines 为零的 UILabel。我希望根据我的标签内容(根据 numberOfLines)调整标签大小。但是,我尝试了很多东西,包括所有this,但它仍然对我不起作用。我为 AutoLayot 使用 Neon 库。

这是我对View的全部内容:

import UIKit
import Neon

class AdditionalDescriptionView: UIView 

    lazy var locationLabel = UILabel()
    lazy var seasonLabel = UILabel()
    lazy var quantityLabel = UILabel()
    lazy var durationLabel = UILabel()
    lazy var requirementsLabel = UILabel()
    var height: CGFloat = 0
    var text = NSString()
    var size = CGSize()

    override init(frame: CGRect) 
        super.init(frame: frame)
        setup()
    

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

    func setup() 
        locationLabel.textAlignment = .left
        locationLabel.text = "Локация: Каркаралинск (200км от Караганды)"
        locationLabel.textColor = .black
        locationLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        locationLabel.numberOfLines = 0
        seasonLabel.textAlignment = .left
        seasonLabel.textColor = .black
        seasonLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        seasonLabel.text = "Сезоны: все"
        quantityLabel.textAlignment = .left
        quantityLabel.textColor = .black
        quantityLabel.text = "Количество людей: 5-25"
        quantityLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        durationLabel.textAlignment = .left
        durationLabel.textColor = .black
        durationLabel.text = "Длительность тура: 3 суток"
        durationLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        requirementsLabel.textAlignment = .left
        requirementsLabel.textColor = .black
        requirementsLabel.text = "Требования: удобная обувь, дополнительный груз не более 3кг, минимум 1л питьевой воды. Лицам с кардио- и дыхательными проблемами не рекомендуется участие в туре."
        requirementsLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        requirementsLabel.numberOfLines = 0
        requirementsLabel.lineBreakMode = .byWordWrapping
        requirementsLabel.sizeToFit()

        self.addSubview(locationLabel)
        self.addSubview(seasonLabel)
        self.addSubview(quantityLabel)
        self.addSubview(durationLabel)
        self.addSubview(requirementsLabel)

        updateConstraints()
    

    override func updateConstraints() 
        locationLabel.anchorToEdge(.top, padding: 0, width: self.frame.width, height: AutoHeight)
        seasonLabel.align(.underCentered, relativeTo: locationLabel, padding: 0, width: self.frame.width, height: AutoHeight)
        seasonLabel.alignAndFillWidth(align: .underCentered, relativeTo: locationLabel, padding: 0, height: AutoHeight)
        quantityLabel.alignAndFillWidth(align: .underCentered, relativeTo: seasonLabel, padding: 0, height: AutoHeight)
        durationLabel.alignAndFillWidth(align: .underCentered, relativeTo: quantityLabel, padding: 0, height: AutoHeight)
        // fix requirementsLabel height
        requirementsLabel.alignAndFillWidth(align: .underCentered, relativeTo: durationLabel, padding: 0, height: AutoHeight)
        height = locationLabel.frame.height+seasonLabel.frame.height+quantityLabel.frame.height+durationLabel.frame.height+requirementsLabel.frame.height
    

使用它来实际添加视图:

self.view.addSubview(additional)
additional.anchorAndFillEdge(.top, xPad: 0, yPad: 0, otherSize: additional.height)
additional.updateConstraints()

【问题讨论】:

我很难理解你真正想要完成的事情,但我马上就看到了一些绝对错误的东西。 height: requirementsLabel.frame.size.height 没有意义,因为该参数是一个常数。您传递的是从sizeToFit 获得的恒定高度,因此它不会在事后针对任何其他变化进行调整。 @Dima 我实际上一直在使用 Neon 库的AutoHeight 属性,它“应该”自动调整大小。但是,它只给了我一个线号。所以,我只是没有太注意我在那里写的东西,因为那是我需要找出的属性。 我查了一下,我看到了AutoHeight。在没有更多详细信息的情况下仍然不确定您的问题的答案,但您应该编辑您的问题以获得您正在使用的代码。 @Dima 我已经为该视图添加了整个代码 我会尽力帮助你的。您看到的实际行为是什么? 【参考方案1】:

我放弃了尝试使用 Neon 来解决这个问题。问题本质上是你试图为你的容器视图定义一个具体的高度,同时试图将其中的元素锚定到彼此及其边缘。我最终只使用了使用布局锚的标准自动布局 API。然后,您需要做的就是指定容器的宽度,它的高度将根据它包含的标签的大小自动设置。解决方法如下:

import UIKit

class AdditionalDescriptionView: UIView 

    lazy var locationLabel = UILabel()
    lazy var seasonLabel = UILabel()
    lazy var quantityLabel = UILabel()
    lazy var durationLabel = UILabel()
    lazy var requirementsLabel = UILabel()
    var text = NSString()
    var size = CGSize()

    override init(frame: CGRect) 
        super.init(frame: frame)
        setup()
    

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

    func setup() 
        self.translatesAutoresizingMaskIntoConstraints = false
        backgroundColor = UIColor.blue
        locationLabel.textAlignment = .left
        locationLabel.text = "Локация: Каркаралинск (200км от Караганды)"
        locationLabel.textColor = .black
        locationLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        locationLabel.numberOfLines = 0
        seasonLabel.textAlignment = .left
        seasonLabel.textColor = .black
        seasonLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        seasonLabel.text = "Сезоны: все"
        quantityLabel.textAlignment = .left
        quantityLabel.textColor = .black
        quantityLabel.text = "Количество людей: 5-25"
        quantityLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        durationLabel.textAlignment = .left
        durationLabel.textColor = .black
        durationLabel.text = "Длительность тура: 3 суток"
        durationLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        requirementsLabel.textAlignment = .left
        requirementsLabel.textColor = .black
        requirementsLabel.text = "Требования: удобная обувь, дополнительный груз не более 3кг, минимум 1л питьевой воды. Лицам с кардио- и дыхательными проблемами не рекомендуется участие в туре."
        requirementsLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        requirementsLabel.numberOfLines = 0
        requirementsLabel.lineBreakMode = .byWordWrapping

        self.addSubview(locationLabel)
        locationLabel.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(seasonLabel)
        seasonLabel.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(quantityLabel)
        quantityLabel.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(durationLabel)
        durationLabel.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(requirementsLabel)
        requirementsLabel.translatesAutoresizingMaskIntoConstraints = false

        locationLabel.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        seasonLabel.topAnchor.constraint(equalTo: locationLabel.bottomAnchor).isActive = true
        quantityLabel.topAnchor.constraint(equalTo: seasonLabel.bottomAnchor).isActive = true
        durationLabel.topAnchor.constraint(equalTo: quantityLabel.bottomAnchor).isActive = true
        requirementsLabel.topAnchor.constraint(equalTo: durationLabel.bottomAnchor).isActive = true
        requirementsLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true

        locationLabel.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
        seasonLabel.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
        quantityLabel.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
        durationLabel.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
        requirementsLabel.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true

        locationLabel.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
        seasonLabel.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
        quantityLabel.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
        durationLabel.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
        requirementsLabel.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
    



class ViewController: UIViewController 

    override func viewDidLoad() 
        super.viewDidLoad()
        let additional = AdditionalDescriptionView()
        self.view.addSubview(additional)
        additional.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true
        additional.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
    

【讨论】:

以上是关于以编程方式根据行数动态调整 UILabel 的大小的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式动态调整 uilabel 宽度的约束

自动布局以动态调整 UILabel 大小不起作用

如何根据 UILabel 动态调整 CollectionViewCell 的大小

调整 UILabel 字体大小以适合文本

根据 UILabel 动态调整 uitableViewCell 大小(带段落间距)

在 Objective-C 中以动态和编程方式调整 UIView 的大小