【问题标题】:Center text vertically in line of NSMutableAttributedString在 NSMutableAttributedString 行中垂直居中文本
【发布时间】:2023-01-09 20:57:32
【问题描述】:

我正在使用 NSMutableAttributedString 来设置文本样式。当我设置 .minimumLineHeight 时,它将一行中的文本居中到行的底部。我想以某种方式自定义这种对齐方式,使文本垂直居中。

 let paragraphStyle = NSMutableParagraphStyle()
 paragraphStyle.minimumLineHeight = fontLineHeight // 24 for example
 attributedText.addAttribute(.paragraphStyle, value: paragraphStyle, range: fullRange)

我想得到这样的结果:

【问题讨论】:

  • 只是好奇。为什么要手动设置行高?您可以通过适当的约束和 sizeToFit 实现相同的行为
  • 我有 14 行的高度和 24 行的高度,它使文本行之间的空间更大。
  • 我已经发布了一个答案,其中包含一些可以自动为您完成的示例代码。如果我以某种方式误解了您的问题,请随时回来

标签: ios swift nsmutableattributedstring nsmutableparagraphstyle


【解决方案1】:

自动布局在大多数情况下都有解决这些问题的方法。您所需要的只是为您的标签(以及您的场景中的lineSpacing)设置适当的约束,这可以使其能够根据提供的文本自动缩放(NSAttributedStringString 值都应该有效)

这是我为模拟您的要求而编写的代码示例:

意见:

private let termsAndConditionsContainer: UIStackView = {
    let container = UIStackView()
    container.backgroundColor = .clear
    container.spacing = 16
    container.axis = .vertical
    container.alignment = .leading
    container.distribution = .fill
    container.translatesAutoresizingMaskIntoConstraints = false
    return container
}()

private let dataAgreementButton: UIButton = {
    let button = UIButton(type: .custom)
    button.setImage(UIImage(), for: .normal)
    button.layer.borderColor = UIColor.gray.cgColor
    button.layer.borderWidth = 0.5
    button.layer.cornerRadius = 16
    return button
}()

private let dataAgreementLabel: UILabel = {
    let label = UILabel()
    label.font = UIFont.systemFont(ofSize: 17, weight: .medium)
    label.numberOfLines = 0
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

private let tosAgreementButton: UIButton = {
    let button = UIButton(type: .custom)
    button.setImage(UIImage(), for: .normal)
    button.layer.borderColor = UIColor.gray.cgColor
    button.layer.borderWidth = 0.5
    button.layer.cornerRadius = 16
    return button
}()

private let tosAgreementLabel: UILabel = {
    let label = UILabel()
    label.font = UIFont.systemFont(ofSize: 17, weight: .medium)
    label.numberOfLines = 0
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

职能:

private func attributedString(with text: String) -> NSAttributedString {
    //Leave it to auto-layout to determine the line height
    let attributedString = NSMutableAttributedString(string: text)
    let style = NSMutableParagraphStyle()
    style.lineSpacing = 8 // I've just declared the spacing between lines
    attributedString.addAttribute(.paragraphStyle, value: style, range: NSRange(location: 0, length: attributedString.length))
    return attributedString
}

private func generateRowContainer() -> UIStackView {
    let container = UIStackView()
    container.backgroundColor = .clear
    container.spacing = 16
    container.axis = .horizontal
    container.alignment = .center
    container.distribution = .fill
    container.layer.borderWidth = 0.5
    container.layer.borderColor = UIColor.green.cgColor
    container.translatesAutoresizingMaskIntoConstraints = false
    return container
}

这是我在 viewDidLoad 中添加上述视图时的约束设置:

override func viewDidLoad() {
    super.viewDidLoad()
    
    let dataAgreementContainer = generateRowContainer()
    dataAgreementContainer.addArrangedSubview(dataAgreementButton)
    dataAgreementLabel.attributedText = attributedString(with: "I agree with the Information note regarding personal data processing")
    dataAgreementContainer.addArrangedSubview(dataAgreementLabel)
    termsAndConditionsContainer.addArrangedSubview(dataAgreementContainer)
    
    let tosAgreementContainer = generateRowContainer()
    tosAgreementContainer.addArrangedSubview(tosAgreementButton)
    tosAgreementLabel.attributedText = attributedString(with: "I agree with terms and conditions")
    tosAgreementContainer.addArrangedSubview(tosAgreementLabel)
    termsAndConditionsContainer.addArrangedSubview(tosAgreementContainer)
    
    view.addSubview(termsAndConditionsContainer)
    
    NSLayoutConstraint.activate([
        
        dataAgreementButton.widthAnchor.constraint(equalToConstant: 32),
        dataAgreementButton.heightAnchor.constraint(equalToConstant: 32),
        
        tosAgreementButton.widthAnchor.constraint(equalToConstant: 32),
        tosAgreementButton.heightAnchor.constraint(equalToConstant: 32),
        
        termsAndConditionsContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 32),
        termsAndConditionsContainer.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -32),
        termsAndConditionsContainer.centerYAnchor.constraint(equalTo: view.centerYAnchor)
    ])
}

我得到以下输出:

在上面的示例中,我使用了水平堆栈视图来保持文本和单选按钮的对齐方式,这对我来说似乎可以满足您的要求。但关键是,只要你的标签是在适当约束的环境中,您无需手动指定其高度。

【讨论】:

    猜你喜欢
    • 2013-10-15
    • 1970-01-01
    • 2015-09-16
    • 2015-09-10
    • 2012-09-17
    • 2013-02-01
    相关资源
    最近更新 更多