ios 无法让 UITextField 自动收缩文本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16350045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 23:26:11  来源:igfitidea点击:

Can't get UITextField to autoshrink text

iphoneiosobjective-cuitextfield

提问by hvanbrug

I have a UITextFieldon a table view cell, and when it's text becomes too long I would like the font size to decrease. I want to make it very clear that I am talking about a UITextField, not a UILabelor a UITextView. The reason I say this is because I have seen this question pop up several times and the answers were all based on UILabelinstead of UITextField. For example, someone asked "I can't get my UITextFieldto autoshrink" and the answer was "make sure it's numberOfLinesis set to 1". To the best of my knowledge, a UITextFielddoes not even have that property and is a single line control.

我有一个UITextField表格视图单元格,当它的文本变得太长时,我希望减小字体大小。我想清楚地表明我在谈论 a UITextField,而不是 aUILabel或 a UITextView。我这样说的原因是因为我已经多次看到这个问题出现并且答案都是基于UILabel而不是UITextField. 例如,有人问“我无法UITextField自动收缩”,答案是“确保将其numberOfLines设置为1”。据我所知, aUITextField甚至没有该属性并且是单行控件。

I have tried:

我试过了:

  • in IB setting the font to system 14.0, minFontSizeto 7 and checking the "adjust to fit" box
  • in code in tableView:cellForRowAtIndexPath:
  • 在 IB 中将字体设置为系统 14.0,设置minFontSize为 7 并选中“调整以适合”框
  • 在代码中 tableView:cellForRowAtIndexPath:
ptCell.name.font = [UIFont systemFontOfSize: 14.0];
ptCell.name.adjustsFontSizeToFitWidth = YES;
ptCell.name.minimumFontSize = 7.0;

but neither of these have worked. By that I mean that instead of the text shrinking it truncates the tail.

但这些都没有奏效。我的意思是,不是文本缩小,而是截断了尾部。

Does anyone know what I am missing? Presumably this should work because I have seen other questions complaining that it is doing that when the user does not want it to.

有谁知道我错过了什么?大概这应该有效,因为我已经看到其他问题抱怨它在用户不想要的时候这样做。

采纳答案by hvanbrug

I used the answer posted by @Purva as a starting point to come up with this method that gives the required font size starting at the configured font size, and not to drop below the configured minimum font size. Whereas @Purva tested for the height of the text I required the width to fit. This method can be put in either a category or a subclass of UITextField. I have it in a subclass which also captures the UITextFieldTextDidChangeNotification. From this notification handler I call the new method and resize the font if required. I also call it when I am assigning new text to the textfield to make sure it will fit by subclassing - (void)setText: (NSString*)text.

我使用@Purva 发布的答案作为起点来提出这种方法,该方法从配置的字体大小开始提供所需的字体大小,而不是低于配置的最小字体大小。而@Purva 测试了文本的高度,我需要宽度来适应。此方法可以放在 UITextField 的类别或子类中。我将它放在一个子类中,它也捕获UITextFieldTextDidChangeNotification. 我从这个通知处理程序调用新方法并根据需要调整字体大小。当我将新文本分配给文本字段以确保它适合子类化时,我也会调用它- (void)setText: (NSString*)text

In each case, when I call it I am using the following code:

在每种情况下,当我调用它时,我都使用以下代码:

    CGFloat requiredFontSize = self.requiredFontSize;
    if( self.font.pointSize != requiredFontSize )
    {
        self.font = [self.font fontWithSize: requiredFontSize];
    }

Here is the new method:

这是新方法:

- (CGFloat)requiredFontSize
{
    const CGRect  textBounds = [self textRectForBounds: self.frame];
    const CGFloat maxWidth   = textBounds.size.width;

    if( _originalFontSize == -1 ) _originalFontSize = self.font.pointSize;

    UIFont* font     = self.font;
    CGFloat fontSize = _originalFontSize;

    BOOL found = NO;
    do
    {
        if( font.pointSize != fontSize )
        {
            font = [font fontWithSize: fontSize];
        }

        CGSize size = [self.text sizeWithFont: font];
        if( size.width <= maxWidth )
        {
            found = YES;
            break;
        }

        fontSize -= 1.0;
        if( fontSize < self.minimumFontSize )
        {
            fontSize = self.minimumFontSize;
            break;
        }

    } while( TRUE );

    return( fontSize );
}

回答by micromanc3r

I had the same problem. The UITextField stoped shrinking the text when it was too long, but instead it resized itself and grew outside its 'bounds'.

我有同样的问题。UITextField 在文本太长时停止缩小文本,而是调整自身大小并超出其“边界”。

The solution that helped me was to set width constrainton given UITextField. After that it did not grew anymore, instead the text inside got smaller as intended. (Of course you have to set minFontSize and check the "adjust to fit" box in storyboard.)

帮助我的解决方案是在给定的 UITextField 上设置宽度约束。之后就没有再增长,而是按照预期的方式缩小了里面的文字。(当然,您必须设置 minFontSize 并选中故事板中的“调整以适合”框。)

I know it's kind of a late, but if anyone else will find this question via google as I did...it might just help.

我知道这有点晚了,但是如果其他人会像我一样通过谷歌找到这个问题......它可能会有所帮助。

回答by Matt Powlson

I think you want to set the adjustsFontSizeToFitWidthproperty for your UITextFieldto YES, and specify a minimumFontSize. Works for me, but I add the UITextFieldprogrammatically - IB issue?

我认为您想将您的adjustsFontSizeToFitWidth属性设置UITextField为 YES,并指定一个minimumFontSize. 对我有用,但我以UITextField编程方式添加- IB 问题?

回答by Jim Conroy

Swift 3.0 way to resize the font to fit:

调整字体大小以适应的 Swift 3.0 方法:

let startFontSize = 14.0
let minFontSize = 7.0

func resizeFont() {
    guard let font = self.font, let text = self.text else {
        return
    }

    let textBounds = self.textRect(forBounds: self.bounds)
    let maxWidth = textBounds.size.width

    for fontSize in stride(from: startFontSize, through: minFontSize, by: -0.5) {
        let size = (text as NSString).size(attributes: [NSFontAttributeName: font.withSize(CGFloat(fontSize))])
        self.font = font.withSize(CGFloat(fontSize))
        if size.width <= maxWidth {
            break
        }
    }
}

回答by vijay

Try this its working for me (swift 3.0)

试试这个对我有用(swift 3.0)

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        // bla bla ... anything inside method you want to do
        // reset font size of textfield
        textField.font = UIFont.systemFont(ofSize: CGFloat(15.0))
        var widthOfText: CGFloat = textField.text!.size(attributes: [NSFontAttributeName: textField.font!]).width
        var widthOfFrame: CGFloat = textField.frame.size.width
        // decrease font size until it fits (25 is constant that works for me)
        while (widthOfFrame - 25) < widthOfText {
            let fontSize: CGFloat = textField.font!.pointSize
            textField.font = textField.font?.withSize(CGFloat(fontSize - 0.5))
            widthOfText = (textField.text?.size(attributes: [NSFontAttributeName: textField.font!]).width)!
            widthOfFrame = textField.frame.size.width
        }
        return true
    }

回答by Purva

-(BOOL)sizeFontToFit:(NSString*)aString minSize:(float)aMinFontSize maxSize:(float)aMaxFontSize 
{   
float fudgeFactor = 16.0;
float fontSize = aMaxFontSize;

self.font = [self.font fontWithSize:fontSize];

CGSize tallerSize = CGSizeMake(self.frame.size.width-fudgeFactor,kMaxFieldHeight);
CGSize stringSize = [aString sizeWithFont:self.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap];

while (stringSize.height >= self.frame.size.height)
       {
       if (fontSize <= aMinFontSize) // it just won't fit
           return NO;

       fontSize -= 1.0;
       self.font = [self.font fontWithSize:fontSize];
       tallerSize = CGSizeMake(self.frame.size.width-fudgeFactor,kMaxFieldHeight);
       stringSize = [aString sizeWithFont:self.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap];
       }

return YES; 
}

回答by user955853

I had this same problem with UITextFields created in StoryBoard in Xcode 5.0.2, running iOS 7.0.4. I figured out that the .minimumFontSize property could not be changed by StoryBoard, or viewDidLoad, or viewWillAppear, but that it couldbe changed in viewDidAppear. So the following code solved my problem:

我在运行 iOS 7.0.4 的 Xcode 5.0.2 的 StoryBoard 中创建的 UITextFields 遇到了同样的问题。我发现 .minimumFontSize 属性不能被 StoryBoard、viewDidLoad 或 viewWillAppear改变,但它可以在 viewDidAppear 中改变。所以下面的代码解决了我的问题:

- (void) viewDidAppear:(BOOL)animated  {
    [super viewDidAppear:animated];
    self.myTextField.minimumFontSize = 4.0;
    [self.myTextField setNeedsLayout];
    [self.myTextField layoutIfNeeded];
}

回答by Marek Manduch

My humble solution for this problem was this.... (find the proper size of font on my own - to fit the size of frame) I made it inside delegate method of shouldChangeCharactersInRange:replacementString:

我对这个问题的简陋解决方案是这样的......(自己找到合适的字体大小 - 以适应框架的大小)我在 shouldChangeCharactersInRange:replacementString 的委托方法中做了它:

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string

 {

    // bla bla ... anything inside method you want to do

    // reset font size of textfield
    textField.font = [FONT_PROXY fontNormalOfSizeNormal];

    CGFloat widthOfText = [textField.text sizeWithAttributes:@{NSFontAttributeName:textField.font}].width;
    CGFloat widthOfFrame = textField.frame.size.width;

    // decrease font size until it fits (25 is constant that works for me)
    while((widthOfFrame - 25) < widthOfText){
        CGFloat fontSize = textField.font.pointSize;
        textField.font = [textField.font fontWithSize:fontSize - 0.5f];
         widthOfText = [textField.text sizeWithAttributes:@{NSFontAttributeName:textField.font}].width;
         widthOfFrame = textField.frame.size.width;
    }


  }

回答by Skyborg

Tested with XCode8 and Swift 3.0.1

使用 XCode8 和 Swift 3.0.1 测试

func getTextfield(view: UIView) -> [UITextField] {
    var results = [UITextField]()
    for subview in view.subviews as [UIView] {
        if let textField = subview as? UITextField {
            results += [textField]
        } else {
            results += getTextfield(view: subview)
        }
    }
    return results
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    let allTextFields = getTextfield(view: self.view)
    for textField in allTextFields
    {
        textField.font = UIFont.boldSystemFont(ofSize: 14)
        var widthOfText: CGFloat = textField.text!.size(attributes: [NSFontAttributeName: textField.font!]).width
        var widthOfFrame: CGFloat = textField.frame.size.width
        while (widthOfFrame - 15) < widthOfText { // try here to find the value that fits your needs
            let fontSize: CGFloat = textField.font!.pointSize
            textField.font = textField.font?.withSize(CGFloat(fontSize - 0.5))
            widthOfText = (textField.text?.size(attributes: [NSFontAttributeName: textField.font!]).width)!
            widthOfFrame = textField.frame.size.width
        }
    }
}

I used viewDidLayoutSubviews to get all textfields and autoshrink the text.

我使用 viewDidLayoutSubviews 来获取所有文本字段并自动收缩文本。

Maybe someone will need this code.

也许有人会需要这个代码。

For me it works perfect.

对我来说它完美无缺。

The Code is from@ Marek Manduch on this site and from

代码来自本网站上的@ Marek Manduch 和来自

@Kunal Kumar on this site: How to get all the textfields from a view in swift

本网站上的@Kunal Kumar: 如何快速从视图中获取所有文本字段

回答by sachadso

The catch here is that minimumFontSize is a ratio and should be between 0 and 1 :)

这里的问题是 minimumFontSize 是一个比率,应该在 0 和 1 之间:)

f.adjustsFontSizeToFitWidth = true
f.minimumFontSize = 0.5

works perfectly :)

完美运行:)