[self.Review sizeToFit];
SizeToFitの前の結果:
NSStringFromCGRect(self.Review.frame): {{90, 20}, {198, 63}}
SizeToFit後の結果:
NSStringFromCGRect(self.Review.frame): {{90, 20}, {181, 45}}
幅は同じままにしておきたい。高さを変えたいだけです。自動マスクは
(lldb) po self.Review
(UILabel *) $1 = 0x08bb0fe0 <UILabel: 0x8bb0fe0; frame = (90 20; 181 45); text = 'I'm at Mal Taman Anggrek ...'; clipsToBounds = YES; opaque = NO; autoresize = LM+RM+H; userInteractionEnabled = NO; layer = <CALayer: 0x8bb68b0>>
私はそれを行う方法があることを知っています: テキストサイズに合わせてUILabelの幅を調整して作成する方法?
答えは奇妙です(フォント情報を再提供する必要があります)。または不明。
また、最大幅を定義し、sizeToFitがその最大幅より大きい幅を与えた場合の対処方法をプログラムに指示する必要があります。
sizeWithFont
を使用するという奇妙なソリューションを使用します。 UILabelはラベルのフォントを既に知っているため、奇妙です。
実際、sizeToFitはどのように動作しますか? UILabelをより薄くするか、より高くする必要があるかどうかは、どのように決定しますか?
これがどのように行われるかです。ラベルにはすでにフォント情報が含まれているため、このメソッド呼び出しにラベルを含めるのは簡単です。
CGSize size = [label.text sizeWithFont:label.font
constrainedToSize:CGSizeMake(maxWidth, MAXFLOAT)
lineBreakMode:UILineBreakModeWordWrap];
CGRect labelFrame = label.frame;
labelFrame.size.height = size.height;
label.frame = labelFrame;
最新のboundingRectWithSize
を使用したSwiftバージョン:
let maxHeight = CGFloat.infinity
let rect = label.attributedText?.boundingRectWithSize(CGSizeMake(maxWidth, maxHeight),
options: .UsesLineFragmentOrigin, context: nil)
var frame = label.frame
frame.size.height = rect.size.height
label.frame = frame
SizeThatFitsでも同じ結果を得ることができます。
CGSize size = [label sizeThatFits:CGSizeMake(label.frame.size.width, CGFLOAT_MAX)];
CGRect frame = label.frame;
frame.size.height = size.height;
label.frame = frame;
または、sizeToFitを使用します。
CGRect frame = label.frame;
[label sizeToFit];
frame.size.height = label.frame.size.height;
label.frame = frame;
sizeToFitは素晴らしい作品です。唯一の問題は、コントロールの現在のサイズに基づいていることです。
たとえば、ラベル付きのテーブルビューセルをリサイクルする場合、ラベルの幅が前のセルで縮小されている可能性があるため、sizeToFitの呼び出しは信頼できないように見える場合があります。
SizeToFitメッセージを送信する前に、コントロールの元の幅をリセットするだけです。
c = CGSize(width:yourWidth、height:CGFloat.greatestFiniteMagnitude)
result = sizeThatFits(c).height
そう...
let t = .... your UITextView
let w = .... your known width of the item
let trueHeight = t.sizeThatFits(
CGSize(width: t, height: CGFloat.greatestFiniteMagnitude)).height
それでおしまい。
非常に多くの場合、「通常の」1行エントリと比較した高さのdifferenceを知りたい。
これは、特にUTableViewとは関係のないある種のセル(たとえば、ある種のカスタムスタックビュー)を作成している場合に発生します。ある時点で高さを手動で設定する必要があります。ストーリーボードで、通常の状況ではもちろん1行だけの短い文字列(たとえば「A」)のサンプルテキストを使用して、希望どおりにビルドします。次に、このようなことをします...
func setTextWithSizeCorrection() { // an affaire iOS
let t = .... your UITextView
let w = .... your known width of the item
let oneLineExample = "A"
let actualText = yourDataSource[row].description.whatever
// get the height as if with only one line...
experimental.text = oneLineExample
let oneLineHeight = t.sizeThatFits(
CGSize(width: w, height: CGFloat.greatestFiniteMagnitude)).height
// get the height with the actual long text...
// (note that usually, you do not want a one-line minimum)
experimental.text = (actualText == "") ? oneLineExample : actualText
let neededHeight = t.sizeThatFits(
CGSize(width: w, height: CGFloat.greatestFiniteMagnitude)).height
experimental.text = actualText
let delta = neededHeight - oneLineHeight
set the height of your cell, or whatever it is(standardHeight + delta)
}
最後のポイント:iOSで本当に愚かなことの1つは、UITextViewの内部に奇妙な種類のマージンがあることです。これは、UITextViewとラベルを単に入れ替えることができないことを意味します。そして、それは他の多くの問題を引き起こします。 Apple執筆時点でこの問題は修正されていません。問題を修正するのは困難です。通常、次のアプローチで問題ありません。
@IBDesignable class UITextViewFixed: UITextView {
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
func setup() {
textContainerInset = UIEdgeInsets.zero;
textContainer.lineFragmentPadding = 0;
}
}
壊れた、使用できないAppleのUITextView ...
UITextViewFixed
は、ほとんどの場合、受け入れ可能な修正です。
(明確にするために黄色が追加されました。)
NSString
のsize...
メソッド、UILabel
はすでに@vatrifが指摘するように、そのためのAPIを既に持っています(内部的にはおそらくNSString
のメソッドのみを使用します)。
それでも、UILabel
のAPIは改善されると思います。それが、カテゴリが最もエレガントなソリューションだと思う理由です。
// UILabel+Resize.h
@interface UILabel (Resize)
- (void)sizeToFitHeight;
@end
// UILabel+Resize.m
@implementation UILabel (Resize)
- (void)sizeToFitHeight {
CGSize size = [self sizeThatFits:CGSizeMake(self.frame.size.width, CGFLOAT_MAX)];
CGRect frame = self.frame;
frame.size.height = size.height;
self.frame = frame;
}
@end
一つだけ:私はそのメソッドの適切な名前がわからない:
コメントありがとうございます!
合意されたAPIはこの追加の恩恵を受けます。作業を簡単にし、Swift=のUILabelクラスに拡張機能を追加します。
extension UILabel {
func sizeToFitHeight() {
let size:CGSize = self.sizeThatFits(CGSizeMake(self.frame.size.width, CGFloat.max))
var frame:CGRect = self.frame
frame.size.height = size.height
self.frame = frame
}
}
Swift 3。
extension UILabel {
func sizeToFitHeight() {
let size: CGSize = self.sizeThatFits(CGSize.init(width: self.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
var frame:CGRect = self.frame
frame.size.height = size.height
self.frame = frame
}
}
Swiftの修正ソリューション
MaxHeightには_CGFloat.greatestFiniteMagnitude
_を使用します。
_let size = CGSize.init(width: yourLabel.frame.size.width,
height: CGFloat.greatestFiniteMagnitude)
let rect = errorLabel.attributedText?.boundingRect(with: size, options: .usesLineFragmentOrigin, context: nil)
var frame = errorLabel.frame
frame.size.height = (rect?.size.height)!
errorLabel.frame = frame
_
またはUIlabel
拡張機能を作成し、メソッドyourLabel. sizeToFitHeight()
を呼び出します
_extension UILabel {
func sizeToFitHeight() {
let maxHeight : CGFloat = CGFloat.greatestFiniteMagnitude
let size = CGSize.init(width: self.frame.size.width, height: maxHeight)
let rect = self.attributedText?.boundingRect(with: size, options: .usesLineFragmentOrigin, context: nil)
var frame = self.frame
frame.size.height = (rect?.size.height)!
self.frame = frame
}
}
_
Mundi の答えのSwift 3バージョン:
let maxHeight: CGFloat = 10000
let rect = label.attributedText!.boundingRect(with: CGSize(width: maxWidth, height: maxHeight),
options: .usesLineFragmentOrigin,
context: nil)
var frame = labe.frame
frame.size.height = rect.size.height
label.frame = frame