UIView
にサブビューを追加するとき、または既存のサブビューのサイズを変更するとき、[view sizeToFit]
および[view sizeThatFits]
にその変更が反映されることを期待します。ただし、私の経験では、sizeToFit
は何もせず、sizeThatFits
は変更の前後で同じ値を返します。
私のテストプロジェクトには、単一のボタンを含む単一のビューがあります。ボタンをクリックすると、ビューに別のボタンが追加され、含まれているビューでsizeToFit
が呼び出されます。ビューの境界は、サブビューを追加する前後にコンソールにダンプされます。
- (void) logSizes {
NSLog(@"theView.bounds: %@", NSStringFromCGRect(theView.bounds));
NSLog(@"theView.sizeThatFits: %@", NSStringFromCGSize([theView sizeThatFits:CGSizeZero]));
}
- (void) buttonTouched {
[self logSizes];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(10.0f, 100.0f, 400.0f, 600.0f);
[theView addSubview:btn];
[theView sizeToFit];
[self performSelector:@selector(logSizes) withObject:nil afterDelay:1.0];
}
そして出力は:
2010-10-15 15:40:42.359 SizeToFit[14953:207] theView.bounds: {{0, 0}, {322, 240}}
2010-10-15 15:40:42.387 SizeToFit[14953:207] theView.sizeThatFits: {322, 240}
2010-10-15 15:40:43.389 SizeToFit[14953:207] theView.bounds: {{0, 0}, {322, 240}}
2010-10-15 15:40:43.391 SizeToFit[14953:207] theView.sizeThatFits: {322, 240}
ここに何か欠けているに違いない。
ありがとう。
ドキュメントはこれについてかなり明確です。 -sizeToFit
は-sizeThatFits:
をほとんど呼び出し(おそらくビューの現在のサイズを引数として)、-sizeThatFits:
のデフォルト実装はほとんど何もしません(引数を返すだけです)。
一部のUIViewサブクラスは-sizeThatFits:
をオーバーライドして、より便利なものを実行します(UILabelなど)。他の機能(サブビューに合わせてビューのサイズを変更するなど)が必要な場合は、UIViewをサブクラス化し、-sizeThatFits:
をオーバーライドする必要があります。
UIViewをオーバーライドしない場合は、拡張機能を使用できます。
迅速:
extension UIView {
func sizeToFitCustom () {
var size = CGSize(width: 0, height: 0)
for view in self.subviews {
let frame = view.frame
let newW = frame.Origin.x + frame.width
let newH = frame.Origin.y + frame.height
if newW > size.width {
size.width = newW
}
if newH > size.height {
size.height = newH
}
}
self.frame.size = size
}
}
同じコードですが、3倍高速です。
extension UIView {
final func sizeToFitCustom() {
var w: CGFloat = 0,
h: CGFloat = 0
for view in subviews {
if view.frame.Origin.x + view.frame.width > w { w = view.frame.Origin.x + view.frame.width }
if view.frame.Origin.y + view.frame.height > h { h = view.frame.Origin.y + view.frame.height }
}
frame.size = CGSize(width: w, height: h)
}
}
self.errorMessageLabel.text = someNewMessage;
// We don't know how long the given error message might be, so let's resize the label + containing view accordingly
CGFloat heightBeforeResize = self.errorMessageLabel.frame.size.height;
[self.errorMessageLabel sizeToFit];
CGFloat differenceInHeightAfterResize = self.errorMessageLabel.frame.size.height - heightBeforeResize;
self.errorViewHeightContstraint.constant = kErrorViewHeightConstraintConstant + differenceInHeightAfterResize;
これでうまくいきました。
IBのみ(xcode 4.5)を使用して、そのようないくつかを行うことができます。
UIView
をクリックしますcontent hugging
to 1(水平および垂直の両方)compression resistance
〜1000(両方)constraints
の下でWidth
をクリックし、priority
を250に変更しますUIView
のinset
を使用して、左/右/上/下のパディングを制御できます