【swift】Viewに自分自身の大きさを定義して、動的なViewを正しくレイアウトする
動的に要素を並べるようなViewを作成した時に、AutoLayoutの設定の仕方で悩みました。
class CustomView: UIView { init() { super.init(frame: .zero) backgroundColor = .whiteColor() // 正方形のViewを左右に並べる let view1 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) let view2 = UIView(frame: CGRect(x: 110, y: 0, width: 100, height: 100)) view1.backgroundColor = .blueColor() view2.backgroundColor = .greenColor() addSubview(view1) addSubview(view2) } }
このようにinitializeの中で動的に要素を作成しているViewを作成します。
このViewの中ではAutoLayoutは定義せずにCGRectで位置を設定しています。
CustomViewを表示してみる
このViewをViewControllerでaddSubview
してあげます。
addしたCustomViewはAutoLayoutで中央揃えになるように設定します。
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .grayColor() let customView = CustomView() view.addSubview(customView) customView.translatesAutoresizingMaskIntoConstraints = false // customView自体には中央揃えになるようにAutoLayoutを設定 customView.centerYAnchor.constraintEqualToAnchor(view.layoutMarginsGuide.centerYAnchor).active = true customView.centerXAnchor.constraintEqualToAnchor(view.layoutMarginsGuide.centerXAnchor).active = true } }
ビルドしてみるとこんな感じです。
うまく中央揃えになりません。
また、CustomView自体の白背景部分が描画されていないため、CustomViewに大きさが無いことがわかります。
intrinsicContentSizeの設定
UIViewにはintrinsicContentSize
というCGSizeを返すメソッドが定義されており、そのサイズを自分自身のサイズと認識します。
ですので、先ほどのCustomViewにintrinsicContentSize
をoverrideさせます。
class CustomView: UIView { init() { super.init(frame: .zero) backgroundColor = .whiteColor() let view1 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) let view2 = UIView(frame: CGRect(x: 110, y: 0, width: 100, height: 100)) view1.backgroundColor = .blueColor() view2.backgroundColor = .greenColor() addSubview(view1) addSubview(view2) } // 追加 override func intrinsicContentSize() -> CGSize { return CGSize(width: 210, height: 100) } }
これでCustomView自体は、幅210px、高さ100pxの要素だと認識するようになりました。
この状態でビルドしてみると
正しく中央揃えになり、CustomViewの白背景も描画されています。
今回の例はサイズを全て決め打ちで書いていますが、この辺りをちゃんと計算して算出するようにすれば、動的な要素も正しくレイアウトされるようになります。