Я уже обыскал и не нашел решения. Любая идея?
Ответ 2
Это не правильно:
lblTemp.lineBreakMode = NSLineBreakByWordWrapping | NSLineBreakByTruncatingTail
lblTemp.numberOfLines = 0;
NSLineBreakMode определяется в NSParagraphStyle.h как:
typedef NS_ENUM(NSInteger, NSLineBreakMode) { /* What to do with long lines */
NSLineBreakByWordWrapping = 0, /* Wrap at word boundaries, default */
NSLineBreakByCharWrapping, /* Wrap at character boundaries */
NSLineBreakByClipping, /* Simply clip */
NSLineBreakByTruncatingHead, /* Truncate at head of line: "...wxyz" */
NSLineBreakByTruncatingTail, /* Truncate at tail of line: "abcd..." */
NSLineBreakByTruncatingMiddle /* Truncate middle of line: "ab...yz" */
} NS_ENUM_AVAILABLE_IOS(6_0);
Обратите внимание, что это NS_ENUM, а не NS_OPTION, поэтому он не предназначен для использования в качестве маски. Для получения дополнительной информации см. this.
В действительности использование оператора | по этим константам приводит к маскировке, соответствующей NSLineBreakByTruncatingTail:
(NSLineBreakByWordWrapping | NSLineBreakByTruncatingTail) == 4
NSLineBreakByTruncatingTail == 4
Насколько я знаю, обрезание последней строки в основном тексте, а также выполнение переносимости слов не могут быть выполнены с помощью простых API CTFramesetterCreateWithAttributedString и CTFrameDraw, но это может быть сделано с построением строки за строкой, который должен выполнять UILabel.
iOS 6 упрощает это, открывая новые API-интерфейсы рисования в NSStringDrawing.h:
typedef NS_ENUM(NSInteger, NSStringDrawingOptions) {
NSStringDrawingTruncatesLastVisibleLine = 1 << 5, // Truncates and adds the ellipsis character to the last visible line if the text doesn't fit into the bounds specified. Ignored if NSStringDrawingUsesLineFragmentOrigin is not also set.
NSStringDrawingUsesLineFragmentOrigin = 1 << 0, // The specified origin is the line fragment origin, not the base line origin
NSStringDrawingUsesFontLeading = 1 << 1, // Uses the font leading for calculating line heights
NSStringDrawingUsesDeviceMetrics = 1 << 3, // Uses image glyph bounds instead of typographic bounds
} NS_ENUM_AVAILABLE_IOS(6_0);
@interface NSAttributedString (NSExtendedStringDrawing)
- (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);
- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);
@end
Итак, если вы используете UILabel, вы хотите, чтобы ваш NSAttributedString NSParagraphStyle или lineBreakMode на самой этикетке устанавливали:
NSLineBreakByTruncatingTail
И свойство numberOfLines на ярлыке должно установить на 0.
Из заголовков UILabel на numberOfLines:
// if the height of the text reaches the # of lines or the height of the view is less than the # of lines allowed, the text will be
// truncated using the line break mode.
Из документации UILabel:
This property controls the maximum number of lines to use in order to fit the label’s text into its bounding rectangle. The default value for this property is 1. To remove any maximum limit, and use as many lines as needed, set the value of this property to 0.
If you constrain your text using this property, any text that does not fit within the maximum number of lines and inside the bounding rectangle of the label is truncated using the appropriate line break mode.
Единственная проблема, которая возникает с этой несколько неясной особенностью UILabel, заключается в том, что вы не можете получить размер перед рисованием (что необходимо для некоторых динамических макетов UITableView + UITableViewCell), не прибегая к модификации NSAttributedString NSParagraphStyle на лету.
Как и в iOS 6.1.4, вызов -boundingRectWithSize: options: context с NSAttributedString, который имеет режим прерывания строки NSLineBreakByTruncatingTail (для UILabel), возвращает неверную высоту одной строки, даже если следующие параметры передаются в:
(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine)
(Обратите внимание, что NSStringDrawingUsesLineFragmentOrigin является необходимостью для многострочных строк.)
Что еще хуже, так это то, что UILabel lineBreakMode делает не переопределять стиль абзаца NSAttributedStrings, поэтому вам нужно изменить стиль атрибута строки атрибута для расчета размера, а затем передать его в UILabel, чтобы он может нарисовать его.
То есть NSLineBreakByWordWrapping для -boundingRectWithSize: options: context и NSLineBreakByTruncatingTail для UILabel (чтобы он мог, использовать NSStringDrawingTruncatesLastVisibleLine внутри или что бы он ни делал, чтобы обрезать последнюю строку)
Единственная альтернатива, если вы не хотите изменять стиль абзаца строк более чем один раз, - это сделать простой подкласс UIView, который переопределяет -drawRect: (с соответствующим набором contentMode, который также будет перерисовываться), и использует iOS 6 новый API для рисования:
- (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);
Вспомним использование NSLineBreakByWordWrapping и передачу (NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine) в качестве параметров.
Наконец, перед iOS 6, если вы хотите сделать перенос слов + укорочение хвоста для атрибутной строки, вам придется выполнять линейную компоновку самостоятельно с помощью Core Text.