2015-02-07 133 views
0

擬合格式化字符串的大多數需求需要計算給定字符串的最大寬度的容器的高度。可可API中的這種功能反映了這一點。字符串容器大小,計算給定最大高度的最小寬度

NSTextField.sizeThatFits() 

此方法將採用固定的最大寬度並調整高度以包含文本。

你會如何做與上述相反的 - 給定的高度限制,計算最小的寬度以包含文本?

我首先想到的一種方法是首先通過將單行文本的面積除以所需的高度以獲得估計的寬度來創建估計。但是這樣做總是高估了高度,因爲單詞會纏繞,並且會沿着另一個單詞推動其他單詞。算法的下一個階段將這個多餘的高度添加到虛構的矩形的末端,直到最大高度限制被打破,給出寬度的上限和下限估計值。算法的最後部分收斂於一種二進制搜索,直到達到某個像素容差。我會盡可能地發佈這個答案。

我覺得必須有更好的方法來做到這一點? (ObjC或Swift)

回答

0

計算文本寬度給出的最大高度:

這裏是當容差設置爲5。平均起來計算3點或4的大小對我來說效果很好,您可以與任何尺寸計算功能替換代碼你喜歡,例如你的功能在上面。根據您想要的程度設置公差。希望這有助於 - 它絕對可以優化(如果你犧牲可讀性多一點)

func setLabelSize { 

    var max_height = CGFloat(200) //This is the maximum height 
    var big_float = CGFloat(99999) 
    var width_estimate = big_float //This is the initial estimate 

    var old_size = label.sizeThatFits(NSSize(width: width_estimate, height: big_float)) 

    width_estimate = old_size.width * old_size.height/max_height 

    var new_size = label.sizeThatFits(NSSize(width: width_estimate, height: big_float)) 
    var old_width_estimate = width_estimate 

    //first estimate will always be short, so loop until upper bound is found 
    while (new_size.height < max_height) { 
     old_width_estimate = width_estimate 
     old_size = new_size 

     var surpless_area = (new_size.height - max_height) * width_estimate 
     width_estimate += (surpless_area/new_size.height) 

     new_size = label.sizeThatFits(NSSize(width: width_estimate, height: big_float)) 
     println("estimate: \(width_estimate) old_estimate: \(old_width_estimate) new_size: \(new_size) old_size: \(old_size)") 
    } 

    //value is inbetween old_width_estimate and width_estimate 
    //width_estimate should be lower estimate, old should be higher 
    var upper_estimate = old_width_estimate 
    var lower_estimate = width_estimate 
    var upper_estimate_size = old_size 
    var tolerance = CGFloat(5) 

    while(true) { 

     var diff = (upper_estimate - lower_estimate)/2 
     println("upper: \(upper_estimate) lower: \(lower_estimate) diff: \(diff)") 
     if diff <= tolerance { 
      break 
     } else { 
      var half_estimate = lower_estimate + diff 
      new_size = label.sizeThatFits(NSSize(width: half_estimate, height: big_float)) 
      if new_size.height>max_height { 
       lower_estimate = half_estimate 
      } else { 
       upper_estimate = half_estimate 
       upper_estimate_size = new_size 
      } 
     } 
    } 

    println("Final size \(upper_estimate_size)") 

    label.frame.size = upper_estimate_size 
} 
0

如何獲取屬性字符串的高度和寬度,然後找到字符串的高度與您的高度限制相匹配的次數,然後按如下方式劃分字符串的寬度:

NSAttributedString *myString = /*an attributed string*/ 
NSSize rawSize = myString.size; /*imagine a size of h20w100*/ 
int heightLimit = 40; /*example height limit*/ 
int linesAvailable = heightLimit/rawSize.height; /*gets the max number of lines available for the text*/ 
int neededWidth = rawSize.width/linesAvailable; /*gets the width of field needed to fit the whole text in the available height*/ 
NSSize fieldSize = NSMakeSize(needeWidth,heightLimit); 

這應該爲您提供一個正確寬度的文本字段,以適合高度有限的字符串(在這種情況下,您將有2行可用,因此需要寬度爲50)。

+0

這是一個開始,但將是準確的,由於自動換行一定不再做一些線,我也查了一下高度單一長度的絃線不能準確地分成高度限制,因爲多條線條由於其間的間距而具有較高的高度。儘管謝謝你的回答! – 2015-02-11 09:18:56

相關問題