Я искал, как это сделать, но не нашел ответа.
Я хотел бы знать, обрезает ли мой NSTextfield
текст (... в конце) без проверки длины его stringValue
. Мне нужно сделать это, чтобы узнать, следует ли мне установить всплывающую подсказку для моего NSTextfield
(действующую как простая метка).
Причина, по которой я не хочу проверять длину stringValue
моего текстового поля, заключается в том, что некоторые символы занимают больше места, чем другие, так что это не очень точно
Спасибо!
Как проверить, обрезает ли уже NSTextfield текст (в конце)
Ответы (4)
Лучше всего использовать NSTextView
вместо NSTextField
. Если вы используете NSTextView
, вы можете получить NSTextContainer
из NSTextView
, используя свойство textContainer
. Контейнер может сообщить вам containerSize
(пространство, в котором нарисован текст).
NSString
объекты реагируют на метод sizeWithAttributes:
. Вы можете использовать полученную структуру NSSize
для захвата ширины текста, если он нарисован с заданными атрибутами. См. раздел «Константы» в Справочник по дополнениям NSAttributedString Application Kit, чтобы выяснить, какие атрибуты имеют значение.
Если ширина containerSize
меньше ширины sizeWithAttributes:
, текст будет обрезан.
EDIT: Извините, это верно только без lineFragmentPadding
, но по умолчанию lineFragmentPadding
не равно нулю. Либо вычтите textContainer.lineFragmentPadding
из containerSize.width
, либо используйте метод NSTextContainer
setLineFragmentPadding:
, чтобы установить его в 0
.
Я полагаю, вы могли бы также сделать некоторые предположения о текстовой области относительно размера NSTextField
и использовать метод sizeWithAttributes:
NSString
в сочетании с этим, но это не так чисто.
РЕДАКТИРОВАТЬ 2: я понял, что не обратил внимание на интерес ОП к усечению текста с помощью многоточий. В приведенном ниже примере кода используется усечение в NSTextView
. Я также подумал, что мог бы также добавить некоторый код, который делает NSTextView
немного более похожим по внешнему виду на NSTextField
, поместив его внутри NSBox
. Добавление проверки размера для определения необходимости отображения всплывающей подсказки было бы простым дополнением к приведенному ниже коду с использованием информации, уже упомянутой выше.
NSString* string = @"Hello World.";
// get the size the text will take up using the default font
NSSize textBounds = [string sizeWithAttributes:@{}];
// Create a border view that looks more or less like the border used around
// text fields
NSBox* borderView = [[NSBox alloc] initWithFrame:NSMakeRect(10, 10, 60, textBounds.height+4)];
[borderView setBoxType:NSBoxCustom];
[borderView setBorderType:NSBezelBorder];
[borderView setContentViewMargins:NSMakeSize(0, 0)];
[borderView setFillColor:[NSColor whiteColor]];
// Create the text view
NSTextView* textView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, 60, textBounds.height)];
[textView setTextContainerInset:NSMakeSize(2, 0)];
[textView.textContainer setLineFragmentPadding:0];
[textView setEditable:YES];
// Set the default paragraph style so the text is truncated rather than
// wrapped
NSMutableParagraphStyle* parStyle = [[NSMutableParagraphStyle alloc] init];
[parStyle setLineBreakMode:NSLineBreakByTruncatingTail];
// Do not let text get squashed to fit
[parStyle setTighteningFactorForTruncation:0.0];
[textView setDefaultParagraphStyle:parStyle];
[parStyle release];
// Set text
[textView setString:string];
// add NSTextView to border view
[borderView addSubview:textView];
[textView release];
// add NSBox to view you want text view displayed in
[self addSubview:borderView];
[borderView release];
setTighteningFactorForTruncation:
класса NSMutableParagraphStyle
.
- person Mathew; 21.01.2013
NSTextfield
свой текст. Итак, я предоставил лучшее решение для отображения редактируемого текста, усечения переполнения и определения того, произойдет ли переполнение.
- person Mathew; 20.09.2013
Для будущих посетителей вы можете использовать метод -[NSCell expansionFrameWithFrame:inView:]
, чтобы определить, имеет ли место усечение. Из заголовка:
Позволяет ячейке возвращать рамку ячейки расширения, если ячейка слишком мала для всего содержимого в представлении. ...‹snip›... Если рамка не слишком мала, верните пустой прямоугольник, и вид подсказки инструмента расширения отображаться не будет. По умолчанию NSCell возвращает NSZeroRect, в то время как некоторые подклассы (например, NSTextFieldCell) при необходимости возвращают правильный кадр.
Короче говоря, вы можете сказать, усекается ли NSTextField
следующим образом:
NSRect expansionRect = [[self cell] expansionFrameWithFrame: self.frame inView: self];
BOOL truncating = !NSEqualRects(NSZeroRect, expansionRect);
Я думаю, вы можете сделать это, посмотрев на рамку редактора полей текстового поля. Вы проверяете его ширину в controlTextDidBeginEditing, а затем снова в controlTextDidEndEditing. Если последнее значение больше, то текст был усечен. В делегате текстового поля реализовано следующее (я создал ivar для initialWidth):
- (void)controlTextDidBeginEditing:(NSNotification *)aNotification {
if (! initialWidth)
initialWidth = ((NSTextView *)aNotification.userInfo[@"NSFieldEditor"]).frame.size.width;
}
- (void)controlTextDidEndEditing:(NSNotification *)aNotification {
if (initialWidth) { //Make sure that beginEditing is called first
NSInteger finalWidth = ((NSTextView *)aNotification.userInfo[@"NSFieldEditor"]).frame.size.width;
if (finalWidth - initialWidth > 1) NSLog(@"We have truncation");
NSLog(@"Final: %ld Initial: %ld", finalWidth,initialWidth);
}
}
Кажется, это работает в большинстве случаев, в том числе, если вы вводите длинную строку, а затем удаляете ее, пока она снова не подойдет. В некоторых случаях это выдавало мне сообщение журнала, когда я был на один символ дальше конца текстового поля, но я не получал многоточие, когда редактирование заканчивалось.
Решение Swift 4 с использованием ipmcc в качестве базы
Он будет изменять размер один за другим, пока не будет соответствовать размеру шрифта или размеру шрифта = 3.
var size_not_ok = true
var conter = 0
let mininum_font_size = 3 // will resize ultil 3
while size_not_ok || conter < 15 { // will try 15 times maximun
let expansionRect = le_nstextfield.expansionFrame(withFrame: le_nstextfield.frame)
let truncated = !NSEqualRects(NSRect.zero, expansionRect)
if truncated {
if let actual_font_size : CGFloat = le_nstextfield.font?.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.size) as? CGFloat {
le_nstextfield.font = NSFont.systemFont(ofSize: actual_font_size - 1)
if actual_font_size < mininum_font_size {
break
}
}
} else {
size_not_ok = false
}
conter = conter + 1
}