這個問題是一個真正的PITA解決。 API的這項工作在iOS7中不推薦使用,或者iOS7替代API被破壞也無濟於事。胡說!
您的解決方案很不錯,但它使用了不推薦使用的API(sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:
),並且它的封裝不是很好 - 您需要將此代碼複製到任何想要此行爲的單元或視圖。好的一面是相當高效的!一個錯誤可能是當你進行計算時,標籤還沒有佈置,但是你根據寬度進行計算。
我建議你將這種行爲封裝在UILabel子類中。通過將大小計算放在覆蓋的intrinsicContentSize
方法中,標籤將自動調整大小。我寫了下面,其中包含你的代碼,將在iOS6的執行和使用iOS7或非過時的API的好我的版本:
@implementation TSAutoHeightLabel
- (CGSize) intrinsicContentSize
{
NSAssert(self.baselineAdjustment == UIBaselineAdjustmentAlignCenters, @"Please ensure you are using UIBaselineAdjustmentAlignCenters!");
NSAssert(self.numberOfLines == 1, @"This is only for single-line labels!");
CGSize intrinsicContentSize;
if ([self.text respondsToSelector: @selector(boundingRectWithSize:options:attributes:context:)])
{
NSStringDrawingContext* context = [NSStringDrawingContext new];
context.minimumScaleFactor = self.minimumScaleFactor;
CGSize inaccurateSize = [self.text boundingRectWithSize: CGSizeMake(self.bounds.size.width, CGFLOAT_MAX)
options: NSStringDrawingUsesLineFragmentOrigin
attributes: @{ NSFontAttributeName : self.font }
context: context].size;
CGSize accurateSize = [self.text sizeWithAttributes: @{ NSFontAttributeName : [UIFont fontWithName: self.font.fontName size: 12.0] } ];
CGFloat accurateHeight = accurateSize.height * inaccurateSize.width/accurateSize.width;
intrinsicContentSize = CGSizeMake(inaccurateSize.width, accurateHeight);
}
else
{
CGFloat actualFontSize;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
[self.text sizeWithFont: self.font
minFontSize: self.minimumFontSize
actualFontSize: &actualFontSize
forWidth: self.frame.size.width
lineBreakMode: NSLineBreakByTruncatingTail];
#pragma GCC diagnostic pop
CGRect lineBox = CTFontGetBoundingBox((__bridge CTFontRef)([UIFont fontWithName: self.font.fontName size: actualFontSize]));
intrinsicContentSize = lineBox.size;
}
return intrinsicContentSize;
}
@end
這個實現是不完美的。我必須確保使用baselineAdjustment == UIBaselineAdjustmentAlignCenters,並且我不能100%確定地理解原因。我不喜歡我必須跳過才能獲得準確的文字高度。計算產生的結果與你的結果之間也有幾個像素差異。隨意玩它,並根據需要進行調整:)
boundingRectWithSize:options:attributes:context
API似乎很破碎給我。雖然它(主要是!)正確地將文本限制爲輸入大小,但它不會計算正確的高度!它返回的高度取決於提供的字體的行高,即使縮放處於播放狀態。我的猜測是這是爲什麼UILabel
默認情況下沒有這種行爲?我的解決方法是計算高度和寬度均準確的無約束大小,然後使用約束寬度和約束寬度之間的比率來計算約束大小的準確高度。什麼是PITA。在蘋果開發論壇中有很多投訴,在這裏指出這個API有這樣的問題。
@ hans-sjunnesson:你有沒有嘗試使用'None'的基線調整來自動縮小? – 2013-10-31 22:46:10
@JörnEyrich雖然這將使文本堅持框架的頂部,UILabel的實際框架不會向上收縮。 這意味着如果您在其下面有一個子標籤,子標籤不會隨着標籤的縮小而向上追隨標籤。 – 2013-11-03 16:13:54
退房http://stackoverflow.com/a/4942766/1039901 – 2013-11-04 12:14:04