21897


AutoLayoutの設定をしたUIView上(の中)に等間隔でUIButtonを配置するプログラムを書いています。（厳密な「等間隔」ではなく、はみ出ない程度に配置する、といったもの）  
UIButtonは7つで、カレンダーの1週間分を表示するようなイメージです。  
UIViewのwidthからボタンの幅と間隔を計算して配置する、というだけのプログラムなのですが、シミュレーターで確認しますとUIViewからはみ出てしまいます。デバッグしてみても値は正しく計算されているようなので、何が原因なのか分からずにいます。もしかしたら何か根本的に間違っているのかもしれません^^;

恐れ入りますが、お気づきの点がありましたらご指摘頂けないでしょうか？

〜追記〜  
viewOya.bounds.widthで「359」という値を取得していますが、これが誤っているようです。  
実際には「343」なのでこの値を取得したいのですが、bounds.width,frame.widthとも「359」を返してきます。  
正しいサイズを取得するにはどうしたら良いのでしょうか？

* * *

＊ピンク色の背景の部分がボタンを配置したいUIView。  
＊AutoLayoutは、Leading,TrailingともSuperviewから「0」に設定しました。  
[![AutoLayoutを設定したUIView](https://i.stack.imgur.com/AVRai.png)](https://i.stack.imgur.com/AVRai.png)

* * *

＊シミュレーターでの見た目(「6」のボタンが右にはみ出てしまっています^^;??)  
[![シミュレーターでの見た目](https://i.stack.imgur.com/iXASa.png)](https://i.stack.imgur.com/iXASa.png)

* * *

＊ソース

[code]

    func test() {
    
        viewOya.setNeedsLayout()
        viewOya.layoutIfNeeded()
    
        let intOyaW: Int = Int(viewOya.bounds.width)    //親viewの幅
        let intBtnW: Int = intOyaW * 12 / 100           //ボタンの幅(親viewの幅の12％としよう)
        let intSpan: Int = (intOyaW - intBtnW * 7) / 6  //間隔
        let incl: Int    = intBtnW + intSpan            //増分値
        print("intOyaW -> \(intOyaW)")
        print("intBtnW -> \(intBtnW)")
        print("intSpan -> \(intSpan)")
        print("intBtnW*7+intSpan*6 -> \(intBtnW*7+intSpan*6)")
    
        for i in 0...6 {
    
            //ボタン作成
            let btn: UIButton = UIButton()
            btn.setTitle(String(i), forState: .Normal)
            btn.setTitleColor(UIColor.whiteColor(), forState: .Normal)
            btn.backgroundColor = UIColor.lightGrayColor()
    
            //位置・サイズを定義
            let posX  = CGFloat(incl * (i % 7))
            let posY  = CGFloat(0)
            let sizeW = CGFloat(intBtnW)
            let sizeH = CGFloat(intBtnW)
            btn.frame = CGRectMake(posX, posY, sizeW, sizeH)
    
            //ボタンを配置
            viewOya.addSubview(btn)
    
            //デバッグ
            print("btn\(i)  minX -> \(btn.frame.minX)  width -> \(btn.frame.size.width)  maxX -> \(btn.frame.maxX)")
        }
    
    }
    
[/code]

* * *

＊デバッグ出力結果

> intOyaW -> 359  
>  intBtnW -> 43  
>  intSpan -> 9  
>  intBtnW*7+intSpan*6 -> 355
>
> btn0 minX -> 0.0 width -> 43.0 maxX -> 43.0  
>  btn1 minX -> 52.0 width -> 43.0 maxX -> 95.0  
>  btn2 minX -> 104.0 width -> 43.0 maxX -> 147.0  
>  btn3 minX -> 156.0 width -> 43.0 maxX -> 199.0  
>  btn4 minX -> 208.0 width -> 43.0 maxX -> 251.0  
>  btn5 minX -> 260.0 width -> 43.0 maxX -> 303.0  
>  btn6 minX -> 312.0 width -> 43.0 maxX -> 355.0

* * *

iPhone6のシミュレーターで検証しています。  
親ビューの幅が359で「6」のボタンのmaxXが355なので、親ビューからはみ出ることはないと思うのですが、？です。

どうぞよろしくお願いいたします。


CC BY-SA 3.0
2016-02-09T03:34:12.537
21874
2016-02-09T09:16:30.763
2016-02-09T09:05:25.830
13962
13962
question
swift autolayout
swift AutoLayoutを設定したviewのサイズについて


test()関数をviewDidLoad()の中で呼び出しているのではないでしょうか？

viewDidLoad()が呼び出された時点では、各Viewのサイズは確定していません。

以下のように、viewDidLayoutSubviews()の中でtest()を呼ぶようにすることで、想定したとおりに配置されるかと思われます。（testの中で呼び出していた、setNeedsLayoutとlayoutIfNeededは不要になります）

[code]

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    
        test()
    
        view.layoutIfNeeded()
    }
    
[/code]

ただし、viewDidLayoutSubviews()は複数回呼ばれることがあるため、ボタンが重複して生成されないように工夫する必要があります。念のため。

こちらでテストした結果は、こんな感じになりました。

[![viewDidLayoutSubviewsで配置](https://i.stack.imgur.com/Ldcud.png)](https://i.stack.imgur.com/Ldcud.png)


CC BY-SA 3.0
2016-02-09T09:16:30.763
21897
2016-02-09T09:16:30.763
7459
21874
answer