Не удается получить 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;
но ни одна из них не сработала. Под этим я подразумеваю, что вместо сокращения текста он обрезает хвост.
Кто-нибудь знает, что мне не хватает? Предположительно это должно работать, потому что я видел другие вопросы, жалующиеся на то, что он делает это, когда пользователь этого не хочет.
Ответы
Ответ 1
Я использовал ответ, отправленный @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 );
}
Ответ 2
У меня была та же проблема. UITextField остановил сжатие текста, когда он был слишком длинным, но вместо этого он изменил размер и вырос за пределами своих границ.
Решение, которое помогло мне, заключалось в установке ограничения ширины на заданный UITextField. После этого он больше не рос, вместо этого текст внутри стал меньше, чем предполагалось.
(Конечно, вам нужно установить minFontSize и установить флажок "отрегулировать по размеру" в раскадровке.)
Я знаю это как-то поздно, но если кто-то еще найдет этот вопрос через google, как я, это может просто помочь.
Ответ 3
Я думаю, вы хотите установить для свойства adjustsFontSizeToFitWidth
для UITextField
значение YES и указать minimumFontSize
. Работает для меня, но я добавляю UITextField
программно - проблема IB?
Ответ 4
-(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;
}
Ответ 5
Попробуйте это для меня для меня (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
}
Ответ 6
У меня была такая же проблема с 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];
}
Ответ 7
Моим скромным решением для этой проблемы было это.... (найти подходящий размер шрифта самостоятельно - чтобы соответствовать размеру фрейма) Я сделал это внутри метода делегата 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;
}
}
Ответ 8
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
}
}
}
Ответ 9
Протестировано с помощью 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 на этом сайте и от
@Кунал Кумар на этом сайте:
Как получить все текстовые поля из представления в быстром
Ответ 10
Может быть решена путем выбора Line Breaks = Clip в IB
Ответ 11
Ловушка здесь заключается в том, что minimumFontSize является отношением и должен быть между 0 и 1:)
f.adjustsFontSizeToFitWidth = true
f.minimumFontSize = 0.5
отлично работает:)