AutoLayoutの制約を動的に変更した話の続き

これだとiOS9.2で意図した通りに動作しなくなったので、
こんな感じに変更してみた。

MainContainerView.swift

import UIKit

class MainContainerView: UIView {
    var containerHeightAtDesigned: CGFloat = 0.0
    var containerHeightAtUpdate: CGFloat = 0.0
    var constantsAtDesigned: [UIView : CGFloat] = [:]

    func initConstraints(heightAtDesigned: CGFloat) {
        containerHeightAtDesigned = heightAtDesigned // memo: デザイン時の高さ
        //print( "MainContainerView.init, frame: \(self.frame)" )
        for c in self.constraints {
            if let label = c.firstItem as? UILabel {
                if c.firstAttribute == .Top {
                    constantsAtDesigned[label] = c.constant
                }
            }
        }
    }

    override func updateConstraints() {
        //println( "updateConstraints: \(self.frame)" )

        containerHeightAtUpdate = self.frame.height
        let constraints = self.constraints
        for var i = 0; i<constraints.count; i++ {
            let c = constraints[i] 
            if let label = c.firstItem as? UILabel {
                if c.firstAttribute == .Top {
                    var val = constantsAtDesigned[label]!
                    val = val * (self.frame.height / containerHeightAtDesigned)
                    //print( "\(label.text) -> \(c.constant) -> \(val)" )
                    c.constant = val
                }
            }
        }
        
        super.updateConstraints()
    }
    
    override func layoutSubviews() {
        if containerHeightAtUpdate != self.frame.height {
            //print( "layoutSubviews: \(self.frame)" )
            setNeedsUpdateConstraints()
        }

        //print( "layoutSubviews: Here!" )
        super.layoutSubviews()
    }
}

んでもって、viewDidLoadでこんな感じで呼び出す。

(self.view as! MainContainerView).initConstraints( 487.0 /* from Stroyboard */ )

Storyboardからデザイン時の高さを埋め込まなきゃいけなくて、
こうやって動的に制約を変更するのはもうやらないと誓った次第。

あと、SuperView(親View)の中央にセットして、
multiplierを設定すれば解決できそうだったけど、
上記の方法で解決したので、今回は見送ることにした。

おしまい。

Leave a Comment