使用monospacedDigitSystemFont导致剪切文本的UITextField的intrinsicContentSize(width)错误

时间:2017-11-29 16:35:35

标签: ios fonts autolayout uitextfield

我有一个UITextField,其中包含带有数字的文本,我在尝试使用该视图的自动布局时遇到了很糟糕的时间。根据数字,它有时会太窄,所以所有文本都没有显示。只有在我使用monospacedDigitSystemFont时才会发生这种情况。此外,如果我使用UILabel而不是UITextField,则不会发生这种情况。它发生在文本中有几个“窄”数字(例如1)时,而不是当数字都是“宽”时(例如5)。似乎UITextField计算其intrinsicContentSize而不渲染等宽数字。如何解决这个问题?

此图说明了问题。橙色背景显示UILabel,而黄色背景显示UITextField。问题只出现在顶部的黄色框中(其中有一个较窄的数字“111111”)。

Yellow for UITextField, orange for UILabel

我有一个解决方法:使用attributedString属性而不是直接将字体分配给UITextField,但是我希望有人有更好的解决方案。图形的游乐场代码在这里:

import UIKit
import PlaygroundSupport

func place(subview:UIView, on view:UIView, x:CGFloat, y:CGFloat) {
    view.addSubview(subview)
    subview.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint(item: subview, attribute: .left, relatedBy: .equal, toItem: view, attribute: .left, multiplier: 1, constant: x).isActive = true
    NSLayoutConstraint(item: subview, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1, constant: y).isActive = true
    subview.setContentCompressionResistancePriority(.required, for: .horizontal)
}

let numericFont = UIFont.monospacedDigitSystemFont(ofSize: 18, weight: .regular)

let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 170))
containerView.backgroundColor = .lightGray

let textWithNarrowDigits = "111111 narrow digits"
let textWithWideDigits = "555555 wide digits"

func show(text:String, topOffset:CGFloat) {
    // Using UILabel - works as expected
    let label = UILabel()
    label.font = numericFont
    label.text = text
    label.backgroundColor = .orange
    print("Label intrinsicContentSize:\(label.intrinsicContentSize)") // width = 177 for narrow digits
    place(subview: label, on:containerView, x: 20, y: topOffset)

    // Using UITextField - width is too small (as if not monospaced)
    let field = UITextField()
    field.font = numericFont
    field.text = text
    field.backgroundColor = .yellow
    print("Field intrinsicContentSize:\(field.intrinsicContentSize)") // width = 161  for narrow digits
    place(subview: field, on:containerView, x: 20, y: topOffset + 30)

}

show(text: textWithNarrowDigits, topOffset: 10)
show(text: textWithWideDigits, topOffset: 100)

PlaygroundPage.current.liveView = containerView

1 个答案:

答案 0 :(得分:1)

这是我的解决方法。而不是:

field.font = numericFont
field.text = text

使用:

field.attributedText = NSAttributedString(string: text, attributes: [NSAttributedStringKey.font : numericFont])

这样做,即使使用等宽的窄数字,UITextField似乎也能正确计算其intrinsicContentSize。但我仍然希望有一个真正的解决方案。