2014-07-16 3 views
4

Я использую представление таблицы, чтобы отобразить список книг, где каждая ячейка имеет UILabel, который показывает название книги и другое UILabel показывает автор (ы) книгиОкругление UILabel в определенном месте

Мой вопрос о автор (ы) лейбл. Книга может иметь несколько авторов, и я хочу, чтобы вести себя следующим образом:

  • Если книга имеет одного автора («Джон Колман») метка должна быть: «Джон Колман»
  • Если книга имеет более один из авторов («Джон Колман», «Боб Ночь», «Майкл») должен быть следующим: «Джон Колман +2 автора»

Теперь проблема заключается в том, что я хочу, чтобы метка была усечена перед символом ' +». Так, например, если первое имя автора давно, позволяет сказать, «Benjamin Walter Jackson», я хочу, чтобы метка, чтобы выглядеть следующим образом:

"Benjamin Walter Ja... +2 authors" 

поведение по умолчанию, конечно, обрезает метку в конце концов, так что выглядит следующим образом:

"Benjamin Walter Jackson +2 au..." 

Если я использую средний TRUNCATE, нет никакого обещания, что он будет укоротить метку в нужном месте (до «+»)

Я ищу способ сделать это и максимально эффективно, не влияя на характеристики прокрутки табличного вида ,

+0

Возможно, самый простой способ - использовать 2 ярлыка. Один для имени и другого для +2 .... Так что, если ваше имя не подходит, оно будет ... в конце, и если это произойдет, то вы измените размер первой метки на размер строки и переместите вторую метку в конце первого. Я вижу много расчетов, если вы попробуете это по-другому;) – AntonijoDev

ответ

5

Редактировать: Обобщение решения для работы с любой строкой «усечение местоположения». Предыдущая версия только усекается в экземпляре строки @" +". Редактировать позволяет определить, где вы хотите, чтобы усечение произошло.


Я взял мой ответ от this question (который был ответ модифицированного от ответа на this site) и с учетом его в соответствии с вашими потребностями. Создайте новый интерфейс NSString, где вы можете отправить свою строку, которая будет урезана пользователем.

ПРИМЕЧАНИЕ. Это решение предназначено только для iOS 7+. Для использования в iOS 6 используйте sizeWithFont: вместо sizeWithAttributes: в файле NSString + TruncateToWidth.m.

NSString + TruncateToWidth.h

@interface NSString (TruncateToWidth) 
- (NSString*)stringByTruncatingAtString:(NSString *)string toWidth:(CGFloat)width withFont:(UIFont *)font; 
@end 

NSString + TruncateToWidth.m

#import "NSString+TruncateToWidth.h" 

#define ellipsis @"…" 

@implementation NSString (TruncateToWidth) 

- (NSString*)stringByTruncatingAtString:(NSString *)string toWidth:(CGFloat)width withFont:(UIFont *)font 
{ 
    // If the string is already short enough, or 
    // if the 'truncation location' string doesn't exist 
    // go ahead and pass the string back unmodified. 
    if ([self sizeWithAttributes:@{NSFontAttributeName:font}].width < width || 
     [self rangeOfString:string].location == NSNotFound) 
     return self; 

    // Create copy that will be the returned result 
    NSMutableString *truncatedString = [self mutableCopy]; 

    // Accommodate for ellipsis we'll tack on the beginning 
    width -= [ellipsis sizeWithAttributes:@{NSFontAttributeName:font}].width; 

    // Get range of the passed string. Note that this only works to the first instance found, 
    // so if there are multiple, you need to modify your solution 
    NSRange range = [truncatedString rangeOfString:string]; 
    range.length = 1; 

    while([truncatedString sizeWithAttributes:@{NSFontAttributeName:font}].width > width 
      && range.location > 0) 
    { 
     range.location -= 1; 
     [truncatedString deleteCharactersInRange:range]; 
    } 

    // Append ellipsis 
    range.length = 0; 
    [truncatedString replaceCharactersInRange:range withString:ellipsis]; 

    return truncatedString; 
} 

@end 

С его помощью:

// Make sure to import the header file where you want to use it 
myLabel.text = [@"Benjamin Walker Jackson + 2 authors" stringByTruncatingAtString:@" +" toWidth:myLabel.frame.size.width withFont:myLabel.font]; 
// Sample Result: Benjamin Walte... + 2 authors 
+0

спасибо за ваш ответ, у меня только одна проблема с вашим решением, что, если имя автора содержит «+»? строка будет усечена преждевременно, чем – Eyal

+0

. Я просто заметил, что вы упомянули об этом в своем комментарии, какие-либо идеи о том, как преодолеть эту проблему? – Eyal

+2

Никогда не решайте это, выполнив [truncatedString rangeOfString: @ "+" options: NSBackwardsSearch]; – Eyal

0

UILabel не может обрабатывать такую ​​функцию усечения, отличную от iOS 7. либо вы должны урезать строку в соответствии с фиксированной (рассчитанной с размером шрифта uilabel) длиной, но это головная боль, или вы можете использовать два UILabels. 1-й uilabel с фиксированным размером для первого автора. он будет автоматически усекать в конце, как вы уже знаете. то вторая uilabel должна быть нарисована точно на первой стороне первой метки с «+ 2 другими авторами».

Edit: посмотрите на @ Stonz2 ответить

0

Этот ответ основан на https://stackoverflow.com/a/30813691/2123122. Вот пример кода.

@interface CustomLabel() 

    @property (nonatomic, retain) NSLayoutManager *layoutManager; 
    @property (nonatomic, retain) NSTextContainer *textContainer; 
    @property (nonatomic, retain) NSTextStorage *textStorage; 

@end 

@implementation CustomLabel 

- (instancetype)initWithCoder:(NSCoder *)aDecoder { 
     self = [super initWithCoder:aDecoder]; 
     if (self) { 
     [self configureTextkitStack]; 
     } 
     return self; 
} 
- (instancetype)initWithFrame:(CGRect)frame { 
     self = [super initWithFrame:frame]; 
     if (self) { 
     [self configureTextkitStack]; 
     } 
     return self; 
    } 

- (void)configureTextkitStack { 
     _textContainer = [[NSTextContainer alloc] init]; 
     _textContainer.lineFragmentPadding = 0; 
     _textContainer.maximumNumberOfLines = self.numberOfLines; 
     _textContainer.lineBreakMode = self.lineBreakMode; 
     _textContainer.widthTracksTextView = YES; 

     _layoutManager = [[NSLayoutManager alloc] init]; 
     [_layoutManager addTextContainer:self.textContainer]; 

     [_textContainer setLayoutManager:self.layoutManager]; 

     _textStorage = [[NSTextStorage alloc] init]; 
     [_textStorage addLayoutManager:self.layoutManager]; 
     [self.layoutManager setTextStorage:_textStorage]; 
} 

- (NSRange)rangeForTokenInsertion { 
     self.textContainer.size = self.bounds.size; 
     if (self.attributedText.length > 0){ 
     [self.textStorage setAttributedString:[[NSMutableAttributedString alloc]initWithAttributedString:self.attributedText]]; 
     } 
     if (self.text.length == 0) { 
     return NSMakeRange(NSNotFound, 0); 
     } 

     NSInteger glyphIndex = [self.layoutManager glyphIndexForCharacterAtIndex:self.textStorage.length - 1]; 
     NSRange range = [self.layoutManager truncatedGlyphRangeInLineFragmentForGlyphAtIndex:glyphIndex]; 

     return range; 
    } 

Теперь вы можете использовать это следующим образом:

NSRange range = [self.label rangeForTokenInsertion]; 
NSString *token = @"...+2 authors"; 
if (range.location != NSNotFound) { 
    range.length += token.length; 
    range.location -= token.length; 
} 
if (range.location != NSNotFound) { 
    NSString *finalString = [self.label.text stringByReplacingCharactersInRange:range withString:token]; 
    self.label.text = finalString; 
} 

Я создал подкласс UILabel под названием ResponsiveLabel, который обрабатывает пользовательский усечение маркер, а также применения стилей к моделям, как userhandles, URL, Хештеги и т.д.

Смежные вопросы