iOS 无论字体如何,UILabel 都会自动将文本调整为框架
iOS UILabel autoresize text to frame no matter the font
我有一件不寻常的事情需要完成,但不知道如何完成。
我有一个 UILabel,想将其设置为特定高度,然后调整其中文本的大小,以便第一个字符等于该特定高度,其余字符仅获得计算出的字体大小。
我尝试使用 myLabel.adjustsFontSizeToFitWidth = YES;
但它并没有真正解决我的问题,因为它在文本中使用了伟大的字符,它仍然添加了字体可能具有的垂直 padding/spacing。
图片应该描述我想要完成的事情。你可以看到高度应该是 200px 并且第一个字符正好是 200px 没有任何垂直添加 padding/spacing 。
有人知道如何解决这个问题吗?
提前致谢
瓦坦
如果您希望 UILabel 的高度始终与第一个字符的高度匹配,您可以使用 sizeToFit
但不要包含整个字符串,只包含第一个字符。然后,在计算出 UILabel 的框架后,仅根据第一个字母,您可以添加其余文本,标签仍处于所需的高度。
希望对您有所帮助。祝你好运!
编辑: 您可以根据这些 UIFont 特性获得所需字符的确切高度。图像很好地解释了这一点。您可能需要根据您当前正在处理的字符进行稍微不同的计算,但是,正如您在图像中看到的那样,您拥有计算所需的所有数据:A great visualization of UIFont properties
[labelAutoResizeCheck setFont:[UIFont fontWithName:labelAutoResizeCheck.font.fontName size:90]];
设置字体后,执行此操作..
CGSize sizeAsPerText = [labelAutoResizeCheck.text sizeWithFont:labelAutoResizeCheck.font];
[labelAutoResizeCheck setFrame:CGRectMake(labelAutoResizeCheck.frame.origin.x, labelAutoResizeCheck.frame.origin.y, sizeAsPerText.width, sizeAsPerText.height)];
基于渲染图像的解决方案,其中标签以字体大小显示,我们可以获得字符的开始位置和结束位置。这样我们就可以确定当前字符的高度(以像素为单位)。下一步是给标签一个新的字体大小,然后通过渲染图像重复上一步。无论字体如何,这都会给出相同大小的字符。
要使用它,您需要将以下代码添加到您的控制器,然后只需调用方法 setSizeFont (sizeFont: CGFloat, center:CGPoint)
,其中 sizeFont 是字符所需的大小,中心是放置标签的位置(我需要这个参数在我的程序中,它可能对其他人没有用)
如果解决方案可以改进,请随时编辑
extension UIImage {
func getPixelColor(pos: CGPoint) -> UIColor {
var pixelData = CGDataProviderCopyData(CGImageGetDataProvider(self.CGImage))
var data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
var pixelInfo: Int = ((Int(self.size.width) * Int(pos.y)) + Int(pos.x)) * 4
var r = CGFloat(data[pixelInfo]) / CGFloat(255.0)
var g = CGFloat(data[pixelInfo+1]) / CGFloat(255.0)
var b = CGFloat(data[pixelInfo+2]) / CGFloat(255.0)
var a = CGFloat(data[pixelInfo+3]) / CGFloat(255.0)
return UIColor(red: r, green: g, blue: b, alpha: a)
}
private func getHeight() -> Int {
var startHeight = 0
var endHeight = Int(round(self.size.height))
outerLoop: for var index = 0; index < Int(round(self.size.height)); index++ {
for var j = 0; j < Int(round(self.size.width)); j++ {
if(self.getPixelColor(CGPoint(x:j, y:index)) == UIColor(red: 0, green: 0, blue: 0, alpha: 1)) {
startHeight = index
break outerLoop
}
}
}
outerLoop: for var index = Int(round(self.size.height))-1; index >= 0; index -= 1 {
for var j = 0; j < Int(round(self.size.width)); j++ {
if(self.getPixelColor(CGPoint(x:j, y:index)) == UIColor(red: 0, green: 0, blue: 0, alpha: 1)) {
endHeight = index
break outerLoop
}
}
}
return endHeight-startHeight
}
}
extension UILabel {
func setSizeFont (sizeFont: CGFloat, center:CGPoint) {
var str = self.text!
str = str.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
var tempLabel = UILabel(frame: self.frame)
//Set text to only be the first char
tempLabel.text = str.substringWithRange(Range<String.Index>(start: advance(str.startIndex, 0), end: advance(str.startIndex, 1)))
tempLabel.font = UIFont(name: self.font.fontName, size: sizeFont)!
tempLabel.backgroundColor = UIColor.whiteColor()
tempLabel.textColor = UIColor.blackColor()
tempLabel.sizeToFit()
self.font = UIFont(name: self.font.fontName, size: sizeFont)!
var height = tempLabel.generateImg().getHeight()
var sizeF = Int(round(sizeFont))
var currSize = sizeF
while( height < sizeF ) {
var diff = sizeF - height
if(diff<=5){
currSize++
} else {
currSize += diff-5
}
tempLabel.font = UIFont(name: tempLabel.font.fontName, size: CGFloat(currSize))!
tempLabel.sizeToFit()
height = tempLabel.generateImg().getHeight()
}
self.font = UIFont(name: self.font.fontName, size: CGFloat(currSize))
self.sizeToFit()
self.center = center
}
private func generateImg() -> UIImage{
UIGraphicsBeginImageContext(self.bounds.size);
// Make the CALayer to draw in our "canvas".
self.layer.renderInContext(UIGraphicsGetCurrentContext())
// Fetch an UIImage of our "canvas".
var image = UIGraphicsGetImageFromCurrentImageContext();
// Stop the "canvas" from accepting any input.
UIGraphicsEndImageContext();
return image
}
}
我有一件不寻常的事情需要完成,但不知道如何完成。
我有一个 UILabel,想将其设置为特定高度,然后调整其中文本的大小,以便第一个字符等于该特定高度,其余字符仅获得计算出的字体大小。
我尝试使用 myLabel.adjustsFontSizeToFitWidth = YES;
但它并没有真正解决我的问题,因为它在文本中使用了伟大的字符,它仍然添加了字体可能具有的垂直 padding/spacing。
图片应该描述我想要完成的事情。你可以看到高度应该是 200px 并且第一个字符正好是 200px 没有任何垂直添加 padding/spacing 。
有人知道如何解决这个问题吗?
提前致谢
瓦坦
如果您希望 UILabel 的高度始终与第一个字符的高度匹配,您可以使用 sizeToFit
但不要包含整个字符串,只包含第一个字符。然后,在计算出 UILabel 的框架后,仅根据第一个字母,您可以添加其余文本,标签仍处于所需的高度。
希望对您有所帮助。祝你好运!
编辑: 您可以根据这些 UIFont 特性获得所需字符的确切高度。图像很好地解释了这一点。您可能需要根据您当前正在处理的字符进行稍微不同的计算,但是,正如您在图像中看到的那样,您拥有计算所需的所有数据:A great visualization of UIFont properties
[labelAutoResizeCheck setFont:[UIFont fontWithName:labelAutoResizeCheck.font.fontName size:90]];
设置字体后,执行此操作..
CGSize sizeAsPerText = [labelAutoResizeCheck.text sizeWithFont:labelAutoResizeCheck.font];
[labelAutoResizeCheck setFrame:CGRectMake(labelAutoResizeCheck.frame.origin.x, labelAutoResizeCheck.frame.origin.y, sizeAsPerText.width, sizeAsPerText.height)];
基于渲染图像的解决方案,其中标签以字体大小显示,我们可以获得字符的开始位置和结束位置。这样我们就可以确定当前字符的高度(以像素为单位)。下一步是给标签一个新的字体大小,然后通过渲染图像重复上一步。无论字体如何,这都会给出相同大小的字符。
要使用它,您需要将以下代码添加到您的控制器,然后只需调用方法 setSizeFont (sizeFont: CGFloat, center:CGPoint)
,其中 sizeFont 是字符所需的大小,中心是放置标签的位置(我需要这个参数在我的程序中,它可能对其他人没有用)
如果解决方案可以改进,请随时编辑
extension UIImage {
func getPixelColor(pos: CGPoint) -> UIColor {
var pixelData = CGDataProviderCopyData(CGImageGetDataProvider(self.CGImage))
var data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
var pixelInfo: Int = ((Int(self.size.width) * Int(pos.y)) + Int(pos.x)) * 4
var r = CGFloat(data[pixelInfo]) / CGFloat(255.0)
var g = CGFloat(data[pixelInfo+1]) / CGFloat(255.0)
var b = CGFloat(data[pixelInfo+2]) / CGFloat(255.0)
var a = CGFloat(data[pixelInfo+3]) / CGFloat(255.0)
return UIColor(red: r, green: g, blue: b, alpha: a)
}
private func getHeight() -> Int {
var startHeight = 0
var endHeight = Int(round(self.size.height))
outerLoop: for var index = 0; index < Int(round(self.size.height)); index++ {
for var j = 0; j < Int(round(self.size.width)); j++ {
if(self.getPixelColor(CGPoint(x:j, y:index)) == UIColor(red: 0, green: 0, blue: 0, alpha: 1)) {
startHeight = index
break outerLoop
}
}
}
outerLoop: for var index = Int(round(self.size.height))-1; index >= 0; index -= 1 {
for var j = 0; j < Int(round(self.size.width)); j++ {
if(self.getPixelColor(CGPoint(x:j, y:index)) == UIColor(red: 0, green: 0, blue: 0, alpha: 1)) {
endHeight = index
break outerLoop
}
}
}
return endHeight-startHeight
}
}
extension UILabel {
func setSizeFont (sizeFont: CGFloat, center:CGPoint) {
var str = self.text!
str = str.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
var tempLabel = UILabel(frame: self.frame)
//Set text to only be the first char
tempLabel.text = str.substringWithRange(Range<String.Index>(start: advance(str.startIndex, 0), end: advance(str.startIndex, 1)))
tempLabel.font = UIFont(name: self.font.fontName, size: sizeFont)!
tempLabel.backgroundColor = UIColor.whiteColor()
tempLabel.textColor = UIColor.blackColor()
tempLabel.sizeToFit()
self.font = UIFont(name: self.font.fontName, size: sizeFont)!
var height = tempLabel.generateImg().getHeight()
var sizeF = Int(round(sizeFont))
var currSize = sizeF
while( height < sizeF ) {
var diff = sizeF - height
if(diff<=5){
currSize++
} else {
currSize += diff-5
}
tempLabel.font = UIFont(name: tempLabel.font.fontName, size: CGFloat(currSize))!
tempLabel.sizeToFit()
height = tempLabel.generateImg().getHeight()
}
self.font = UIFont(name: self.font.fontName, size: CGFloat(currSize))
self.sizeToFit()
self.center = center
}
private func generateImg() -> UIImage{
UIGraphicsBeginImageContext(self.bounds.size);
// Make the CALayer to draw in our "canvas".
self.layer.renderInContext(UIGraphicsGetCurrentContext())
// Fetch an UIImage of our "canvas".
var image = UIGraphicsGetImageFromCurrentImageContext();
// Stop the "canvas" from accepting any input.
UIGraphicsEndImageContext();
return image
}
}