Objective c 字符串容器大小,计算给定最大高度的最小宽度
大多数安装格式化字符串的需求都需要计算一个容器的高度,该容器给定字符串的最大宽度。cocoa API中的此类函数反映了这一点,例如Objective c 字符串容器大小,计算给定最大高度的最小宽度,objective-c,string,cocoa,swift,Objective C,String,Cocoa,Swift,大多数安装格式化字符串的需求都需要计算一个容器的高度,该容器给定字符串的最大宽度。cocoa API中的此类函数反映了这一点,例如 NSTextField.sizeThatFits() 此方法将最大宽度视为固定宽度,并调整高度以包含文本 你会如何做与上述相反的事情-给定高度限制,计算出包含文本的最小宽度 我首先想到的一种方法是,首先创建一个估计值,将一行文本的面积除以所需的高度,得到一个估计的宽度。但这永远是对高度的高估,因为单词会被包裹起来,推动其他单词前进和下降。该算法的下一阶段,获取该多
NSTextField.sizeThatFits()
此方法将最大宽度视为固定宽度,并调整高度以包含文本
你会如何做与上述相反的事情-给定高度限制,计算出包含文本的最小宽度
我首先想到的一种方法是,首先创建一个估计值,将一行文本的面积除以所需的高度,得到一个估计的宽度。但这永远是对高度的高估,因为单词会被包裹起来,推动其他单词前进和下降。该算法的下一阶段,获取该多余高度并将其添加到虚拟矩形的末端,直到最大高度限制被打破,从而给出宽度的上下估计值。算法的最后部分通过一种二进制搜索收敛,直到达到某个像素容差。当我可以的时候,我会把这个作为一个答案发布
我觉得一定有更好的办法?ObjC或Swift获取属性字符串的高度和宽度,然后找出字符串高度符合您的高度限制的多少倍,然后将字符串宽度除以,如下所示:
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);
这将为您提供一个具有正确宽度的文本字段,以适应高度有限的字符串。在这种情况下,您将有两行可用,因此需要50的宽度。计算给定最大高度的文本宽度:
这是一个对我来说很好的代码,当公差设置为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
}
这是一个开始,但将是准确的,因为单词包装使一些行必然更长,我还检查了单个长度字符串的高度并没有准确地划分为高度限制,因为多行之间由于间隔而具有更大的高度。谢谢你的回答!