UILabel的结果行与UILineBreakModeWordWrap

Nic*_*ick 18 iphone cocoa-touch nsstring uilabel iphone-sdk-3.0

我有一个UILabel,其大小是用sizeWithFont:方法计算的.换行模式设置为UILineBreakModeWordWrap(计算大小时使用相同的标志sizeWithFont:)...

一切都很好,标签大小合适,并根据需要显示我的文字.

现在我需要知道用于显示标签的行(或sizeWithFont:使用时生成的行).我可以在技术上根据空格/插入符号返回来编写我自己的换行实现,但是它不会像Apple的实现那样得到保证,因此生成的行不会是用于计算文本大小的行,没关系重新发明轮子的事实.

理想情况下,我会传递我的字符串,指定宽度和换行符模式,并接收表示文本视觉行的字符串数组.

任何想法如何以最优雅的方式实现这一目标?

Ado*_*lfo 38

要计算UILabel包装文本后的行数,您需要找到您UILabel的字体(label.font.leading)的行距(行高),然后将多行UILabel的高度除以每行的高度,以得到行数.

这是一个例子:

- (void)viewDidLoad {

    [super viewDidLoad];

    UILabel *label = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
    label.numberOfLines = 0;
    label.lineBreakMode = UILineBreakModeWordWrap;  
    label.text = @"Some really really long string that will cause the label's text to wrap and wrap and wrap around. Some really really long string that will cause the label's text to wrap and wrap and wrap around.";

    CGRect frame = label.frame;
    frame.size.width = 150.0f;
    frame.size = [label sizeThatFits:frame.size];
    label.frame = frame;

    CGFloat lineHeight = label.font.leading;
    NSUInteger linesInLabel = floor(frame.size.height/lineHeight);
    NSLog(@"Number of lines in label: %i", linesInLabel);

    [self.view addSubview:label];

}
Run Code Online (Sandbox Code Playgroud)

或者,您可以分两行:

[label sizeToFit];
int numLines = (int)(label.frame.size.height/label.font.leading);
Run Code Online (Sandbox Code Playgroud)

  • 请注意,**"leading"**的发音为"ledding".(正如"Led Zepplin"中的那样,不像"跟随领导者"那样.)它只是意味着金属,led(即原子物质Pb) - 这个词来自排版的早期,当你真正放置LED灯条时在字母之间创建,好,ledding. (3认同)

Tom*_*ift 24

我认为没有任何灵丹妙药.

这是一个类别方法,似乎适用于我投入的几个基本测试用例.不能保证它不会破坏复杂的东西!

它的工作方式是通过字符串测试来查看一系列单词是否适合标签的宽度.当它计算出当前范围太宽时,它会将最后拟合范围记录为一条线.

我并不认为这是有效的.更好的方法可能只是实现自己的UILabel ...

@interface UILabel (Extensions)

- (NSArray*) lines;

@end

@implementation UILabel (Extensions)

- (NSArray*) lines
{
    if ( self.lineBreakMode != UILineBreakModeWordWrap )
    {
        return nil;
    }

    NSMutableArray* lines = [NSMutableArray arrayWithCapacity:10];

    NSCharacterSet* wordSeparators = [NSCharacterSet whitespaceAndNewlineCharacterSet];

    NSString* currentLine = self.text;
    int textLength = [self.text length];

    NSRange rCurrentLine = NSMakeRange(0, textLength);
    NSRange rWhitespace = NSMakeRange(0,0);
    NSRange rRemainingText = NSMakeRange(0, textLength);
    BOOL done = NO;
    while ( !done )
    {
        // determine the next whitespace word separator position
        rWhitespace.location = rWhitespace.location + rWhitespace.length;
        rWhitespace.length = textLength - rWhitespace.location;
        rWhitespace = [self.text rangeOfCharacterFromSet: wordSeparators options: NSCaseInsensitiveSearch range: rWhitespace];
        if ( rWhitespace.location == NSNotFound )
        {
            rWhitespace.location = textLength;
            done = YES;
        }

        NSRange rTest = NSMakeRange(rRemainingText.location, rWhitespace.location-rRemainingText.location);

        NSString* textTest = [self.text substringWithRange: rTest];

        CGSize sizeTest = [textTest sizeWithFont: self.font forWidth: 1024.0 lineBreakMode: UILineBreakModeWordWrap];
        if ( sizeTest.width > self.bounds.size.width )
        {
            [lines addObject: [currentLine stringByTrimmingCharactersInSet:wordSeparators]];
            rRemainingText.location = rCurrentLine.location + rCurrentLine.length;
            rRemainingText.length = textLength-rRemainingText.location;
            continue;
        }

        rCurrentLine = rTest;
        currentLine = textTest;
    }

    [lines addObject: [currentLine stringByTrimmingCharactersInSet:wordSeparators]];

    return lines;
}

@end
Run Code Online (Sandbox Code Playgroud)

使用这样:

NSArray* lines = [_theLabel lines];

int count = [lines count];
Run Code Online (Sandbox Code Playgroud)


The*_*ger 11

只需调用以下方法并传递UILabelUITextView:

-(NSInteger)getNumberOfLinesInLabelOrTextView:(id)obj
{
    NSInteger lineCount = 0;
    if([obj isKindOfClass:[UILabel class]])
    {
        UILabel *label = (UILabel *)obj;

       // This method is deprecated in iOS 7.0 or later 
       // CGSize requiredSize = [label.text sizeWithFont:label.font constrainedToSize:label.frame.size lineBreakMode:label.lineBreakMode]; 

        CGSize requiredSize = [label.text boundingRectWithSize:CGSizeMake(CGRectGetWidth(label.frame), CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:label.font} context:nil].size;

        int charSize = label.font.leading;
        int rHeight = requiredSize.height;

        lineCount = rHeight/charSize;
    }
    else if ([obj isKindOfClass:[UITextView class]])
    {
        UITextView *textView = (UITextView *)obj;
        lineCount = textView.contentSize.height / textView.font.leading;
    }

    return lineCount;
}
Run Code Online (Sandbox Code Playgroud)

现在调用这个方法: -

NSLog(@"%d",[self getNumberOfLinesInLabelOrTextView:label]);
NSLog(@"%d",[self getNumberOfLinesInLabelOrTextView:textView]);
Run Code Online (Sandbox Code Playgroud)

更新:SWIFT CODE

func getNumberOfLinesInLabelOrTextView(obj:AnyObject) -> NSInteger {

    var lineCount: NSInteger = 0
    if (obj.isKindOfClass(UILabel)) {

        let label: UILabel = obj as! UILabel
        let requiredSize: CGSize = (label.text)!.boundingRectWithSize(CGSizeMake(CGRectGetWidth(label.frame), CGFloat.max), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: label.font], context: nil).size
        let charSize: CGFloat = label.font.leading
        let rHeight: CGFloat = requiredSize.height
        lineCount = (NSInteger)(rHeight/charSize)
    }
    else if (obj.isKindOfClass(UITextView)){

        let textView: UITextView = obj as! UITextView
        lineCount = (NSInteger)(textView.contentSize.height / textView.font.leading)
    }

    return lineCount
}
Run Code Online (Sandbox Code Playgroud)

现在调用这个方法: -

println("%d \(self.getNumberOfLinesInLabelOrTextView(textView))")
println("%d \(self.getNumberOfLinesInLabelOrTextView(label))")
Run Code Online (Sandbox Code Playgroud)

注意:leading- 使用lineHeight.没有返回实际领先.将来会被正式弃用.