ios - 使用等宽数字系统字体的 UITextField 的错误 intrinsicContentSize(宽度)导致剪切文本

标签 ios fonts autolayout uitextfield

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

这张图说明了这个问题。橙色背景显示 UILabel,而黄色背景显示 UITextField。该问题仅出现在顶部的黄色框中(具有窄数字“111111”)。

Yellow for UITextField, orange for UILabel

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

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

最佳答案

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

field.font = numericFont
field.text = text

使用:

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

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

关于ios - 使用等宽数字系统字体的 UITextField 的错误 intrinsicContentSize(宽度)导致剪切文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47557568/

相关文章:

ios - 为所有页面添加导航栏和标签栏

iphone - 在 ViewController 上找不到属性

ios - 进行本地化时使用自动布局取消自动 RTL 翻转

ios - 如何让自动布局覆盖 UIImageView 的固有大小?

ios - 无法触摸包含 AVPlayerLayer 的 UIView

ios - 如何在 if-else 条件语句中使用 AlertController

java.awt.font 字母间距

java - 无法在 WebSphere 上加载以下字体

emacsclient 字体检查不起作用

ios - 以编程方式在 UINavigationBar 中添加布局约束