2015-02-07 134 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

相关问题