web-dev-qa-db-ja.com

UIView sizeToFitが意味のあることを行うのに問題がある

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}

ここに何か欠けているに違いない。

ありがとう。

36
FishesCycle

ドキュメントはこれについてかなり明確です。 -sizeToFit-sizeThatFits:をほとんど呼び出し(おそらくビューの現在のサイズを引数として)、-sizeThatFits:のデフォルト実装はほとんど何もしません(引数を返すだけです)。

一部のUIViewサブクラスは-sizeThatFits:をオーバーライドして、より便利なものを実行します(UILabelなど)。他の機能(サブビューに合わせてビューのサイズを変更するなど)が必要な場合は、UIViewをサブクラス化し、-sizeThatFits:をオーバーライドする必要があります。

52
Ole Begemann

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)
    }
}
3
Dmytro Shvetsov
        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;

これでうまくいきました。

0
shaunlim

IBのみ(xcode 4.5)を使用して、そのようないくつかを行うことができます。

  1. UIViewをクリックします
  2. サイズインスペクタでドラッグcontent hugging to 1(水平および垂直の両方)
  3. 引っ張る compression resistance〜1000(両方)
  4. uIViewのconstraintsの下でWidthをクリックし、priorityを250に変更します
  5. 高さについても同じようにします
  6. UIViewinsetを使用して、左/右/上/下のパディングを制御できます
0
marmor