Uitextfield在必要之前收缩文本

发布于 2025-02-12 23:07:22 字数 822 浏览 0 评论 0原文

我有一个uitextfield我已经设置了autoAdjustSizetSizEtofItwidth true and MinimumFontsize 0 。问题是设置比实际应更早地缩小文本。例如,这是上述设置的uitextfield的图像:

“在此处输入图像说明”

绿色是uitextfield的背景颜色。在此示例中,文本尚未缩小,但是无论我输入的内容是下一个字符,文本字段总是开始缩小。尽管显然在左侧足够的空间,还有几个字符。这是另一个带有其他字符的图像:

”在此处输入图像描述

如您所见,左侧有一个相对较大的区域自动调整时,文本字段不会将文本放入中。这是一个正确的对齐文本字段。中心对齐文本字段也可以说,左侧有空间,右侧有空间,似乎自动调整文本字段不会将文本字段放在其中。

如何获得它,以便自动调整文本字段使用整个可用空间?

I have a UITextField for which I've set autoAdjustFontSizeToFitWidth to true and minimumFontSize to 0. The problem is the setting shrinks the text noticeably sooner than it really should. For example, here is an image of a UITextField with the above settings:

enter image description here

The green is the background color of the UITextField. In this example, the text has not shrunk yet, but no matter what I type as the next character the text field always begins shrinking; despite clearly being enough room on the left side for a few more characters. Here is another image with additional characters entered:

enter image description here

As you can see, there is a relatively large area on the left side that the text field won't place text in when auto adjusting. This is for a right aligned text field. The same can be said of center aligned text fields as well, where there is space on the left and right that seems as if an auto adjusting text field won't place text inside.

How do I get it so that auto adjusting text fields use the entire available space?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风透绣罗衣 2025-02-19 23:07:22

更新:

您可以手动进行文本计算和字体调整。通过这样做,您将避免黑客和将来的兼容性问题。
一个简单的实现看起来像这样:


import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!
    
    var originalFont: UIFont!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.textField.font = self.textField.font?.withSize(44)
        self.textField.adjustsFontSizeToFitWidth = false
        self.originalFont = textField.font
        self.textField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)

    }

    @objc
    func textFieldDidChange(sender: UITextField) {
        
        let textRect = sender.textRect(forBounds: sender.bounds)
        let textWidth = textRect.width
        
        var currentFont = self.originalFont!
        var i = 0
        while (i < 10) {
            let unrestrictedTextWidth = sender.text!.boundingRect(with: CGSize(width: .greatestFiniteMagnitude,
                                                                               height: textRect.height),
                                                                  attributes: [.font : currentFont],
                                                                  context: nil).width
            if unrestrictedTextWidth <= textWidth {
                break
            }
            
            let factor = textWidth / max(textWidth, unrestrictedTextWidth)
            let originalSize = currentFont.pointSize
            currentFont = self.originalFont!.withSize(originalSize * factor)
            i += 1
        }
        sender.font = currentFont
    }
}

有趣的是,文本rect和字体大小之间的实际关系是非线性的,不平凡。因此,我添加了多个迭代步骤以近似正确的尺寸。我最多选择了10次迭代,以避免在很小的尺寸和圆形错误上无限循环。

原始答案:

uitextfieldaCTICTSFONTSIZETSIZETSIZETSETOFITWIDTH上总是有一些魔术。例如,请参阅2015年的这篇文章有关初始字体大小如何影响最小字体大小的信息:
https://stackoverflow.com/a/30881385/921573

uitextfield with:
字体尺寸17,如果需要的话,最小尺寸15将降至15
字体尺寸17,最小尺寸10只能降低至14
字体尺寸13,最小尺寸4将保持在13

,将IB中的最小字体大小设置为0,只是被忽略了 - 因此,请参阅收缩效果,必须像1一样小的值。

将其设置为代码为0。

因此,我认为可以肯定地说,uitextfieldapchsfontsizetsizetofitwidth方面可能被认为是有障碍的。

话虽如此,我为您找到了一个解决方法:

class FixedTextField: UITextField {

    override func textRect(forBounds bounds: CGRect) -> CGRect {

        let magicNumber = -15.0
        
        if self.adjustsFontSizeToFitWidth {
            return CGRect(
                x: bounds.origin.x + magicNumber,
                y: bounds.origin.y,
                width: bounds.size.width - magicNumber,
                height: bounds.size.height
            )
        } else {
            return super.textRect(forBounds: bounds)
        }
    }

    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return self.textRect(forBounds: bounds)
    }
}

此自定义文本字段使用反魔法来减轻问题。
您可能必须根据字体,尺寸或设备使用MagicNumber。对我来说15作品还可以:

”文本字段已修复”

Update:

You can do the text calculations and font resizing manually. By doing so you will avoid hacks and future compatibility issues.
A simple implementation looks like this:


import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!
    
    var originalFont: UIFont!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.textField.font = self.textField.font?.withSize(44)
        self.textField.adjustsFontSizeToFitWidth = false
        self.originalFont = textField.font
        self.textField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)

    }

    @objc
    func textFieldDidChange(sender: UITextField) {
        
        let textRect = sender.textRect(forBounds: sender.bounds)
        let textWidth = textRect.width
        
        var currentFont = self.originalFont!
        var i = 0
        while (i < 10) {
            let unrestrictedTextWidth = sender.text!.boundingRect(with: CGSize(width: .greatestFiniteMagnitude,
                                                                               height: textRect.height),
                                                                  attributes: [.font : currentFont],
                                                                  context: nil).width
            if unrestrictedTextWidth <= textWidth {
                break
            }
            
            let factor = textWidth / max(textWidth, unrestrictedTextWidth)
            let originalSize = currentFont.pointSize
            currentFont = self.originalFont!.withSize(originalSize * factor)
            i += 1
        }
        sender.font = currentFont
    }
}

Interestingly the actual relationship between text rect and font size is non-linear and non-trivial. So I added multiple iteration steps to approximate the correct size. I chose a maximum of 10 iterations to avoid infinite loops on very small sizes and rounding errors.

Original Answer:

There has always been some magic around UITextField and adjustsFontSizeToFitWidth. See for example this post from 2015 about how the initial font size affects the minimum font size:
https://stackoverflow.com/a/30881385/921573

A UITextField with:
Font size 17, minimum size 15 will go down to 15 if need be
Font size 17, minimum size 10 will only go down to 14
Font size 13, minimum size 4 will stay at 13

In my tests, setting the minimum font size in IB to 0 just gets ignored – in order so see the shrinking effect it has to be a small value like 1.
Setting it in code to 0 works fine.

So I think it is safe to say that UITextField might be considered historically buggy when it comes to adjustsFontSizeToFitWidth.

That being said, I found a workaround for you:

class FixedTextField: UITextField {

    override func textRect(forBounds bounds: CGRect) -> CGRect {

        let magicNumber = -15.0
        
        if self.adjustsFontSizeToFitWidth {
            return CGRect(
                x: bounds.origin.x + magicNumber,
                y: bounds.origin.y,
                width: bounds.size.width - magicNumber,
                height: bounds.size.height
            )
        } else {
            return super.textRect(forBounds: bounds)
        }
    }

    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return self.textRect(forBounds: bounds)
    }
}

This custom text field uses countermagic to mitigate the issue.
You may have to play with the magicNumber according to your font or dimensions or device. For me 15 works ok:

text field fixed

梦里梦着梦中梦 2025-02-19 23:07:22

这对我有效,textfield.textalignment将设置为.right(这取决于您在TextField中放置多少个字符):

“在此处输入图像说明”

class TextFieldOne: UITextField {


override func alignmentRect(forFrame frame: CGRect) -> CGRect {
    
  //  let newWidth = frame.width + 10 // if you want to reduce the right side too.
    
    let x = frame.origin.x - 15 // suit yourself here
    
    let newFrame = CGRect(x: x, y: frame.origin.y, width: frame.width, height: frame.height)
    
    return newFrame
    
   
}


override func editingRect(forBounds bounds: CGRect) -> CGRect {
       return self.alignmentRect(forFrame: self.bounds)
    }


override func textRect(forBounds bounds: CGRect) -> CGRect {
    return self.alignmentRect(forFrame: self.bounds)
     }



}

This works for me and the textField.textAlignment is set to .right (it will depend on how many characters you put in the textField though) :

enter image description here

class TextFieldOne: UITextField {


override func alignmentRect(forFrame frame: CGRect) -> CGRect {
    
  //  let newWidth = frame.width + 10 // if you want to reduce the right side too.
    
    let x = frame.origin.x - 15 // suit yourself here
    
    let newFrame = CGRect(x: x, y: frame.origin.y, width: frame.width, height: frame.height)
    
    return newFrame
    
   
}


override func editingRect(forBounds bounds: CGRect) -> CGRect {
       return self.alignmentRect(forFrame: self.bounds)
    }


override func textRect(forBounds bounds: CGRect) -> CGRect {
    return self.alignmentRect(forFrame: self.bounds)
     }



}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文