異なる文字列長に基づいてUILabelの高さを計算しようとしています。
func calculateContentHeight() -> CGFloat{
var maxLabelSize: CGSize = CGSizeMake(frame.size.width - 48, CGFloat(9999))
var contentNSString = contentText as NSString
var expectedLabelSize = contentNSString.boundingRectWithSize(maxLabelSize, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: UIFont.systemFontOfSize(16.0)], context: nil)
print("\(expectedLabelSize)")
return expectedLabelSize.size.height
}
上記の高さを決定するために使用している現在の関数ですが、それは機能していません。私は私が得ることができるどんな助けでも大いに感謝するでしょう。 Objective Cではなく、Swiftで答えをお勧めします。
String
で拡張子を使う
extension String {
func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return ceil(boundingBox.height)
}
func width(withConstrainedHeight height: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return ceil(boundingBox.width)
}
}
そしてまたNSAttributedString
(これは時々非常に役に立ちます)
extension NSAttributedString {
func height(withConstrainedWidth width: CGFloat) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, context: nil)
return ceil(boundingBox.height)
}
func width(withConstrainedHeight height: CGFloat) -> CGFloat {
let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
let boundingBox = boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, context: nil)
return ceil(boundingBox.width)
}
}
extension String
メソッドのattributes
の値を変更するだけです。
から
[NSFontAttributeName: font]
に
[.font : font]
複数行テキストの場合、この答えは正しく機能しません。 UILabelを使用して別の文字列拡張子を構築できます。
extension String {
func height(constraintedWidth width: CGFloat, font: UIFont) -> CGFloat {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: .greatestFiniteMagnitude))
label.numberOfLines = 0
label.text = self
label.font = font
label.sizeToFit()
return label.frame.height
}
}
UILabelは固定幅を取得し、.numberOfLinesは0に設定されます。テキストを追加して.sizeToFit()を呼び出すと、自動的に正しい高さに調整されます。
コードはSwift 3で書かれています????????
ここに私のために働いている簡単な解決策があります...投稿された他のいくつかに似ていますが、sizeToFit
を呼び出す必要はありません
これはSwift 5で書かれていることに注意してください
let lbl = UILabel()
lbl.numberOfLines = 0
lbl.font = UIFont.systemFont(ofSize: 12) // make sure you set this correctly
lbl.text = "My text that may or may not wrap lines..."
let width = 100.0 // the width of the view you are constraint to, keep in mind any applied margins here
let height = lbl.systemLayoutSizeFitting(CGSize(width: width, height: UIView.layoutFittingCompressedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel).height
これは、行の折り返しなどを処理します。最もエレガントなコードではありませんが、仕事は完了です。
extension String{
func widthWithConstrainedHeight(_ height: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: CGFloat.greatestFiniteMagnitude, height: height)
let boundingBox = self.boundingRect(with: constraintRect, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return ceil(boundingBox.width)
}
func heightWithConstrainedWidth(_ width: CGFloat, font: UIFont) -> CGFloat? {
let constraintRect = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return ceil(boundingBox.height)
}
}
私は、受け入れられた答えが固定幅ではあるが固定高さではうまくいかないことを発見した。固定の高さでは、テキストに改行がない限り、1行に収まるように幅を広げるだけです。
Width関数はheight関数を複数回呼び出しますが、これは簡単な計算であり、UITableの行でこの関数を使用した場合のパフォーマンスの問題には気付きませんでした。
extension String {
public func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [.font : font], context: nil)
return ceil(boundingBox.height)
}
public func width(withConstrainedHeight height: CGFloat, font: UIFont, minimumTextWrapWidth:CGFloat) -> CGFloat {
var textWidth:CGFloat = minimumTextWrapWidth
let incrementWidth:CGFloat = minimumTextWrapWidth * 0.1
var textHeight:CGFloat = self.height(withConstrainedWidth: textWidth, font: font)
//Increase width by 10% of minimumTextWrapWidth until minimum width found that makes the text fit within the specified height
while textHeight > height {
textWidth += incrementWidth
textHeight = self.height(withConstrainedWidth: textWidth, font: font)
}
return ceil(textWidth)
}
}
これはSwift 4.1とXcode 9.4.1の私の答えです。
//This is your label
let proNameLbl = UILabel(frame: CGRect(x: 0, y: 20, width: 300, height: height))
proNameLbl.text = "This is your text"
proNameLbl.font = UIFont.systemFont(ofSize: 17)
proNameLbl.numberOfLines = 0
proNameLbl.lineBreakMode = .byWordWrapping
infoView.addSubview(proNameLbl)
//Function to calculate height for label based on text
func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat {
let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.byWordWrapping
label.font = font
label.text = text
label.sizeToFit()
return label.frame.height
}
今、あなたはこの関数を呼びます
//Call this function
let height = heightForView(text: "This is your text", font: UIFont.systemFont(ofSize: 17), width: 300)
print(height)//Output : 41.0
ラベルのテキストの高さを確認してください。
let labelTextSize = ((labelDescription.text)! as NSString).boundingRect(
with: CGSize(width: labelDescription.frame.width, height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin,
attributes: [.font: labelDescription.font],
context: nil).size
if labelTextSize.height > labelDescription.bounds.height {
viewMoreOrLess.hide(byHeight: false)
viewLess.hide(byHeight: false)
}
else {
viewMoreOrLess.hide(byHeight: true)
viewLess.hide(byHeight: true)
}