2012-07-31 41 views
1

我有一个标题,我把它放到UILabel中。我把它弄成两行,但通常第二行只有一个小词。有没有办法告诉系统更平稳地包裹线条?iOS字包装更均匀吗?

标题是动态提取的,所以我不相信我可以提前确定。

回答

1

你可以计算出一条线上的长度,然后取这个宽度除以2,并将该结果用作2行标签的宽度约束。这可能会让你获得更好的视觉效果,但如果你有很长的单词会导致你的标签为3行(除非有2行以上),你可能必须稍微调整一下。

这种方法的缺点是做了一些额外的工作,但它可能会伎俩。例如:

 
    NSString *text = @"This is my very long title I want evenly on 2 lines"; 
    UILabel *theLabel = [[UILabel alloc] init]; 
    theLabel.text = text; 
    // ...other label setup here, like font, etc 
    [theLabel sizeToFit]; 

    CGSize constraint = CGSizeMake(theLabel.frame.size.width/2.0, 1000); 
    CGSize labelSize = [theLabel.text sizeWithFont:theLabel.font constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap]; 

    theLabel.numberOfLines = 0; 
    theLabel.lineBreakMode = UILineBreakModeWordWrap; 
    CGRect frame = theLabel.frame; 
    frame.size = labelSize; 
    theLabel.frame = frame; 

应该这样做。警告:从内存中写入。 :-)

1

我不相信有这样做的简单方法。 NSString中增加了UIKit,允许您确定显示具有特定字体的字符串所需的尺寸。你可以做的是使用所有可用的宽度计算所需的高度,然后在循环中运行相同的计算,从而减小宽度直到它需要额外的垂直空间。然后,使用以前的值作为标签的宽度并进行适当的对齐。

+0

如果在给定的字体,标签只需要一行,那就很好。我真正想要避免的是非常重要的标签,其中除了一个单词外的所有内容都位于顶部,然后底部有一个小字。基本上,标题不必包装,但如果要包装,我希望它更平整一些。 – s73v3r 2012-07-31 21:28:20

+0

是的,这就是我描述的方法。你的初始计算会产生一个高的高度。当它溢出到两行时,你的循环会退出。您可以使用先前的宽度值,这是可以使内容保持一行的最窄宽度。 – Jim 2012-07-31 21:30:09

0

对于一个多语言的应用程序,我需要修正以及完全相同的问题。该应用程序可以用9种不同的语言显示其用户界面,并且语言之间的消息长度有很大差异。正因为如此,我结束了对一些多行消息的一些不幸的默认文字换行。例如,有几种情况下,日文翻译最后只有一行文字,后面只有一个或两个字符。

我在我的Layout Utility类中添加了以下两种方法来解决这个问题(请参阅下面的代码)。此解决方案适用于具有任意数量行(1,2,3,更多......)和任何语言的标签。 (更改ECLayoutUtility到自己的类名。)

的基本思路是这样的:

  1. 给出一个UILabel显示文本,检测其当前高度。

  2. 做一个二进制搜索的最小宽度为而不是增加那个高度。

在下面我的代码,你可以通过while循环与granularity可变控制精度和匝数之间的权衡。此修复程序之前有问题的日本品牌的

例子:

enter image description here

认为修补后同日本标签:

enter image description here

这是两种方法,我加入到我的布局实用程序类。我将它们分割成这样,所以你也可以查询获得新的尺寸,例如你使用Autolayout,并且想要使用尺寸信息来操纵约束条件而不是直接调整标签本身的尺寸:

+ (void)wordWrapEvenlyTextInUILabel:(UILabel *)uiLabel 
         forMaxWidth:(CGFloat)maxLabelWidth 
{ 
    [ECLayoutUtility resizeView:uiLabel 
         toSize:[self getLabelSizeWithMinimumWidthForLabel:uiLabel 
                   forMaxWidth:maxLabelWidth]]; 
} 


+ (CGSize)getLabelSizeWithMinimumWidthForLabel:(UILabel *)uiLabel 
            forMaxWidth:(CGFloat)maxLabelWidth 
{ 
    NSLog(@"Current size for label \"%@\" is %@", uiLabel.text, NSStringFromCGSize(uiLabel.frame.size)); 

    // Start off by determining what height the label would get for the given maximum width: 
    CGSize labelSize = [uiLabel.text boundingRectWithSize:CGSizeMake(maxLabelWidth, MAXFLOAT) 
                options:NSStringDrawingUsesLineFragmentOrigin 
               attributes:@{ NSFontAttributeName:uiLabel.font } 
                context:nil].size; 

    // Constraining the label to that height, now figure out the mimumum width for 
    // which this label still shows its text within that given height. We find 
    // that height with a binary search for the smallest label width that does 
    // not increment the label height. 

    CGFloat maxWidth = maxLabelWidth; 
    CGFloat testWidth = 0.5 * maxWidth; 
    CGFloat minWidth = 0; 
    CGFloat granularity = 1; 

    while (maxWidth > testWidth + granularity) 
    { 
     CGFloat newHeight = [uiLabel.text boundingRectWithSize:CGSizeMake(testWidth, MAXFLOAT) 
                 options:NSStringDrawingUsesLineFragmentOrigin 
                attributes:@{ NSFontAttributeName:uiLabel.font } 
                 context:nil].size.height; 

     NSLog(@"H: %.2f, min W: %.2f, mid W: %.2f, max W: %.2f", newHeight, minWidth, testWidth, maxWidth); 

     if (newHeight > labelSize.height) 
     { 
      // Width reduction lead to height increase, so new width is too small. 
      // Now set the new width to mid-point between what we just tried and 
      // the last known acceptable width: 
      minWidth = testWidth;       // increase the lower bound 
      testWidth += 0.5 * (maxWidth - testWidth);  // increase width for next test 
     } 
     else 
     { 
      // Height not affected by the width reduction, so lets try to reduce it even more: 
      maxWidth = testWidth;       // reduce the upper bound 
      testWidth -= 0.5 * (testWidth - minWidth);  // reduce width for next test 
     } 
    } 

    CGSize newSize = CGSizeMake(maxWidth, labelSize.height); 
    NSLog(@"New size for label \"%@\" is %@", uiLabel.text, NSStringFromCGSize(newSize)); 

    return newSize; 
} 

我打电话从-viewWillLayoutSubviews+wordWrapEvenlyTextInUILabel:forMaxWidth:方法在我的视图控制器如下:

// Make sure that any text in the promo message that is wrapped over multiple lines 
// is wrapped evenly, so we don't get very uneven lines that look ugly: 
[ECLayoutUtility wordWrapEvenlyTextInUILabel:_promoMessageLabel 
           forMaxWidth:_promoMessageLabel.frame.size.width]; 

我已经在不同的语言测试,这为不同的标签,它看起来是完全做的工作。这里有一个越南例如:

enter image description here

我希望这可以帮助别人以及:-)

感谢,

埃里克

1

我继续创建了一个名为CocoaPod是EvenlyWrappedLabel受到了Erik van der Neut的回答的启发。它有几个整洁的功能:

  1. 防止单个单词孤儿占据整个底线。

    实施例:

    This sentence has a single 
    orphan. 
    

    变成:从顶部向上分组,感觉头重脚轻

    This sentence has 
    a single orphan. 
    
  2. 防止文本。

    例子:

    This sentence has a lot of words on 
    the top line. 
    

    变为:

    This sentence has a lot 
    of words on the top line. 
    
  3. 选项在可用每行均匀地分布文本。

    实施例:

    This only takes up one line. 
    

    变为*:

    This only 
    takes up 
    one line. 
    

    * numberOfLines = 3useEveryLine = true

  4. 作品与自动布局约束和方面固有上浆。

  5. 极易于集成,只需将let label = UILabel()替换为let label = EvenlyWrappedLabel()即可。

  6. 一个糟糕的屁股示例应用程序。

Example Project Screenshot

如果你不使用的CocoaPods,你可以找到GitHub的源代码。请享用!

+1

这真了不起。谢谢! – 2017-10-11 03:12:08