2012-07-31 20 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