it-swarm.com.ru

Не удается получить UITextField для автоматического сжатия текста

У меня есть UITextField в ячейке табличного представления, и когда текст становится слишком длинным, я бы хотел, чтобы размер шрифта уменьшился. Я хочу пояснить, что я имею в виду UITextField, а не UILabel или UITextView. Причина, по которой я так говорю, заключается в том, что я видел этот вопрос несколько раз, и все ответы были основаны на UILabel вместо UITextField. Например, кто-то спросил: «Я не могу заставить мою UITextField автоматически сжиматься», и ответ был «убедитесь, что для numberOfLines установлено 1». Насколько мне известно, UITextField даже не обладает этим свойством и является однострочным элементом управления.

Я пытался:

  • в IB установите шрифт для системы 14.0, minFontSize в 7 и установите флажок «настроить, чтобы соответствовать»
  • в коде в tableView:cellForRowAtIndexPath:
ptCell.name.font = [UIFont systemFontOfSize: 14.0];
ptCell.name.adjustsFontSizeToFitWidth = YES;
ptCell.name.minimumFontSize = 7.0;

но ни один из них не сработал. Под этим я подразумеваю, что вместо сокращения текста он обрезает хвост.

Кто-нибудь знает, чего мне не хватает? Предположительно это должно работать, потому что я видел другие вопросы, жалующиеся на то, что он делает это, когда пользователь этого не хочет.

19
hvanbrug

Я использовал ответ, опубликованный @Purva, в качестве отправной точки, чтобы придумать этот метод, который дает требуемый размер шрифта, начиная с настроенного размера шрифта, и не опускается ниже настроенного минимального размера шрифта. В то время как @Purva проверил высоту текста, мне потребовалась ширина, чтобы соответствовать. Этот метод может быть помещен в категорию или подкласс UITextField. У меня есть это в подклассе, который также захватывает UITextFieldTextDidChangeNotification. Из этого обработчика уведомлений я вызываю новый метод и при необходимости изменяю размер шрифта. Я также называю это, когда я назначаю новый текст текстовому полю, чтобы удостовериться, что он будет соответствовать, подклассом - (void)setText: (NSString*)text.

В каждом случае, когда я звоню, я использую следующий код:

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

Вот новый метод:

- (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 );
}
10
hvanbrug

У меня такая же проблема. UITextField прекратил сокращать текст, когда он был слишком длинным, но вместо этого он изменил размеры и вышел за пределы своих «границ».

Решением, которое мне помогло, было установить ограничение ширины для данного UITextField. После этого он больше не рос, вместо этого текст внутри стал меньше, как и предполагалось ... (конечно, вы должны установить minFontSize и установить флажок «подгонять под» в раскадровке).

Я знаю, что это немного поздно, но если кто-то еще найдет этот вопрос через Google, как я сделал ... это может просто помочь.

14
micromanc3r

Я думаю, что вы хотите установить свойство adjustsFontSizeToFitWidth для вашего UITextField в YES и указать minimumFontSize. У меня работает, но я добавляю UITextField программно - проблема IB?

8
Matt Powlson

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
        }
    }
}
1
Jim Conroy

Попробуйте это работает для меня (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
    }
1
vijay
-(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; 
}
1
Purva

Моим скромным решением этой проблемы было следующее ... (найти правильный размер шрифта самостоятельно - чтобы он соответствовал размеру фрейма) Я сделал это внутри метода делегата shouldChangeCharactersInRange: replaceString:

-(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;
    }


  }
0
Marek Manduch

У меня была такая же проблема с UITextFields, созданным в StoryBoard в Xcode 5.0.2, под управлением iOS 7.0.4. Я выяснил, что свойство .minimumFontSize не может быть изменено StoryBoard, или viewDidLoad, или viewWillAppear, но что оно можно изменить в viewDidAppear. Таким образом, следующий код решил мою проблему:

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

Протестировано с 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
        }
    }
}

Я использовал viewDidLayoutSubviews, чтобы получить все текстовые поля и автоматически сжимать текст.

Может быть, кому-то понадобится этот код.

Для меня это работает идеально.

Код от @ Marek Manduch на этом сайте и от 

@ Кунал Кумар на этом сайте: Как получить все текстовые поля из представления в Swift

0
Skyborg