Длина строки с заданным шрифтом, чтобы соответствовать UITextView - PullRequest
6 голосов
/ 12 мая 2009

Мне нужно переместить текст, который пользователь ввел в большую многострочную UITextView, в меньшую (но все же многострочную) UITextView*. Если пользователь ввел больше текста, чем будет отображаться в меньшем виде, я хочу обрезать текст так, чтобы он соответствовал всему видимому (усеченному) тексту. (Ни большой UITextView, ни меньший не должны прокручиваться.)

Какой лучший способ сделать это?

Я могу использовать цикл, каждый раз сокращая строку на символ, а затем использовать NSString sizeWithFont: constrainedToSize: lineBreakMode:, чтобы узнать высоту, которая понадобится этой более короткой строке, а затем сравнить ее с высотой, имеющейся у меня в моем меньшем UITextView, заканчивающем цикл, когда строка будет соответствовать - но это кажется медленным и неловким. Должен быть лучший способ.

Я хотел бы просто сказать адресату UITextView обрезать его элемент displayText, поскольку он отображает его на экране, но я не смог найти способ сделать это.

* Более подробно об этом, из комментария, который я сделал ниже:

У меня есть приложение для ландшафта. Я изменяю расположение вида в зависимости от фотографии, которую выбирает пользователь. Если это пейзажная фотография, заголовок меньше - просто линия внизу фотографии. Если она выберет портретную фотографию, тогда у меня будет достаточно места для подписи сбоку фотографии, поэтому она будет больше.

Если пользователь меняет ориентацию своей фотографии с книжной на альбомную, то я хочу обрезать текст, а затем разрешить ему редактировать его, чтобы он имел смысл. Я мог бы просто убрать это, но я предпочел бы сохранить это, чтобы минимизировать ее печатание.

Ответы [ 4 ]

3 голосов
/ 08 июля 2009

Я написал следующий рекурсивный метод и публичный API, чтобы сделать это правильно. Уродливый фактор выдумки является предметом этого вопроса .

#define kFudgeFactor 15.0
#define kMaxFieldHeight 9999.0

// recursive method called by the main API
-(NSString*) sizeStringToFit:(NSString*)aString min:(int)aMin max:(int)aMax
{
if ((aMax-aMin) <= 1)
    {
    NSString* subString = [aString substringToIndex:aMin];
    return subString;
    }

int mean = (aMin + aMax)/2; 
NSString* subString = [aString substringToIndex:mean];

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

if (stringSize.height <= self.frame.size.height)
    return [self sizeStringToFit:aString min:mean max:aMax]; // too small
else    
        return [self sizeStringToFit:aString min:aMin max:mean];// too big
}

-(NSString*)sizeStringToFit:(NSString*)aString
{

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

// if it fits, just return
if (stringSize.height < self.frame.size.height)
    return aString; 

// too big - call the recursive method to size it       
NSString* smallerString = [self sizeStringToFit:aString min:0 max:[aString length]];
return smallerString;   
}
2 голосов
/ 14 мая 2009

На самом деле это не исправление, но оно обеспечивает хорошее начальное положение для расчета.

Если вы используете sizeWithFont: constrainedToSize: lineBreakMode: NSString, вы получите вертикальную высоту для вашего текста. Если вы разделите это на начальную высоту шрифта, вы получите количество строк во всей строке. Разделив [NSString count] на это число, вы получите приблизительное количество символов в строке. При этом предполагается, что строка является однородной и будет неточной, если кто-то напечатает (например, «iiiiiiiiiii ...», как «МММММММММ ...».

Вы также можете разделить ограничивающий прямоугольник на высоту leading соответствующего шрифта, чтобы получить количество строк, которые вписываются в ограничивающий прямоугольник.

Умножение символов на строку на количество строк дает вам отправную точку для поиска подходящего текста.

Вы можете рассчитать запас для ошибки на этом рисунке, выполнив те же вычисления для этих строк 'iiiiii ...' и "MMMMMM ... '".

1 голос
/ 14 мая 2009

Я думаю, что Джонатан был кое-что о UILabel ...

Итак, пользователь заканчивает редактирование UITextView, вы получаете строку текста и передаете ее в UILabel. Вы изменяете альфа UITextView на 0 и / или удаляете его из суперпредставления. Возможно, хранить не усеченный полный текст в иваре.

UILabel не являются «редактируемыми», однако вы можете обнаружить прикосновение с помощью UILabel (или его суперпредставления). Когда вы обнаруживаете прикосновение к UILabel, вы просто восстанавливаете скрытый UITextView и восстанавливаете сохраненную вами строку.

Иногда SDK - это боль, но он почти всегда побеждает в битве. Во многих случаях лучше адаптировать свой дизайн к соглашениям UIKit

1 голос
/ 12 мая 2009

Я бы предложил немного другой подход и посмотреть, можете ли вы использовать UILabel вместо меньшего UITextView.

UILabels можно настроить как многострочный, как UITextView, с помощью свойства numberOfLines.

UILabels также имеет свойство lineBreakMode, и я считаю, что значение по умолчанию этого свойства будет иметь именно тот эффект усечения, который вы ищете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...