获取以编程方式创建的子视图的框架

时间:2015-10-15 16:04:40

标签: ios swift cocoa-touch uiview

我有一个以编程方式创建的子视图view1。我正在为它添加一些UIButtons,但这些按钮的测量结果取决于view1.frame.height。但是,我似乎只能获得viewDidAppear中的值,这显然不是我想要的。此外,如果我将addButtons()函数放在viewDidLayoutSubviews中,我会得到一个无限循环。将addButtons()放入各种UIViewController函数的结果如下(在注释中):

override func viewDidLoad() {
    super.viewDidLoad()
    addView1()
}

override func viewDidLayoutSubviews(){
    print(view1.frame.height)  // 0.0 first time it is called, 74.0, which is right, the second time it is called, but I got into an infinite loop
    //addButtons() -> infinite loop
}

override func viewWillAppear(animated: Bool) {
    print(view1.frame.height) //0.0
}

override func  viewDidAppear(animated: Bool) {
    print(view1.frame.height) //74.0, the value I want, but obviously not where I want it
}

我的addButtons()看起来像这样:

 func addButtons(){

    let mon = UIButton()
    let tue = UIButton()
    let wed = UIButton()
    let thu = UIButton()
    let fri = UIButton()
    let sat = UIButton()
    let sun = UIButton()


    let buttonsArray = ["mon": mon, "tue": tue, "wed": wed, "thu": thu, "fri": fri, "sat": sat, "sun": sun]
    let daysArray1 = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
    var daysArray2 = ["mon": "M", "tue":"T", "wed": "W", "thu": "T", "fri": "F", "sat": "S", "sun": "S"]
    let buttonSide = view1.frame.height * 0.6

    let distance = (view1.frame.width - buttonSide * 7) / 8.0
    var count = 0

    for day in daysArray1{
        let offSet = (buttonSide ) * CGFloat(count) + distance * CGFloat(count + 1)
        let centerX = (buttonSide / 2) + offSet



        buttonsArray[day]!.setTitle(daysArray2[day], forState: .Normal)

        buttonsArray[day]!.translatesAutoresizingMaskIntoConstraints = false

        buttonsArray[day]!.layer.cornerRadius = 5

        view1.addSubview(buttonsArray[day]!)

        view1.addConstraint(NSLayoutConstraint(item: buttonsArray[day]!, attribute: NSLayoutAttribute.CenterY, relatedBy: .Equal, toItem: view1, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))
        view1.addConstraint(NSLayoutConstraint(item: buttonsArray[day]!, attribute: NSLayoutAttribute.CenterX, relatedBy: .Equal, toItem: view1, attribute: NSLayoutAttribute.Left, multiplier: 1, constant: centerX))
        view1.addConstraint(NSLayoutConstraint(item: buttonsArray[day]!, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: buttonSide))
        view1.addConstraint(NSLayoutConstraint(item: buttonsArray[day]!, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: buttonSide))
        count += 1


    }

1 个答案:

答案 0 :(得分:1)

每次向视图添加按钮时,系统都会调用viewDidLayoutSubviews,您可以继续添加按钮,系统会一直调用viewDidLayoutSubviews。您应该在viewDidLoad()时添加按钮。 要匹配视图的高度,您可以:

  
      
  • 将所有按钮固定到视图的尾随和前沿
  •   
  • 将第一个按钮的顶部固定在视图的顶边
  • 上   
  • 将最后一个按钮的底部固定在视图的底部
  •   
  • 使用上一个按钮的下边缘(给定不是第一个按钮)固定每个按钮的顶部
  •   
  • 约束所有按钮。高度匹配视图的.Height乘以0.6
  •   

这是我使用PureLayout

所做的一个例子
    let someView = UIView(frame: CGRectZero)
    view.addSubview(someView)
    var prev: UIButton?
    for i in 0..<6 {
        let button = UIButton(frame: CGRectZero)
        button.setBackgroundColor(UIColor.randomColor(), forUIControlState: .Normal)
        someView.addSubview(button)
        button.autoPinEdgeToSuperviewEdge(.Trailing)
        button.autoPinEdgeToSuperviewEdge(.Leading)
        button.autoMatchDimension(.Height, toDimension: .Height, ofView: someView, withMultiplier: 0.6)
        if let previous = prev {
            button.autoPinEdge(.Top, toEdge: .Bottom, ofView: previous)
        } else {
            button.autoPinEdgeToSuperviewEdge(.Top)
        }
        prev = button
    }

    someView.autoPinEdgeToSuperviewEdge(.Trailing)
    someView.autoPinEdgeToSuperviewEdge(.Leading)
    someView.autoPinEdgeToSuperviewEdge(.Top)
    someView.autoSetDimension(.Height, toSize: 100)

UPDATE(等水平间距)

根据你的评论确定,我知道你还需要按钮之间的间距以及父容器的侧边。其中是一个完整的工作视图控制器类:

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let wrapper = UIView(frame: CGRectZero)
        view.addSubview(wrapper)
        wrapper.backgroundColor = UIColor.redColor()

        var previous: (button: UIButton, spacer: UIView)?
        for day in ["M", "T", "W", "T", "F", "S", "S"] {
            let button = UIButton(frame: CGRectZero)
            let spacer = UIView(frame: CGRectZero)
            button.setTitle(day, forState: .Normal)
            button.backgroundColor = UIColor.grayColor()
            button.translatesAutoresizingMaskIntoConstraints = false
            spacer.translatesAutoresizingMaskIntoConstraints = false
            wrapper.addSubview(button)
            wrapper.addSubview(spacer)

            //set height 60% of wrapper
            wrapper.addConstraint(NSLayoutConstraint(
                item: button,
                attribute: .Height,
                relatedBy: .Equal,
                toItem: wrapper,
                attribute: .Height,
                multiplier: 0.6,
                constant: 0))

            //set width same has height
            wrapper.addConstraint(NSLayoutConstraint(
                item: button,
                attribute: .Height,
                relatedBy: .Equal,
                toItem: button,
                attribute: .Width,
                multiplier: 1,
                constant: 0))

            //pin button leading with spacer trailing
            wrapper.addConstraint(NSLayoutConstraint(
                item: button,
                attribute: .Leading,
                relatedBy: .Equal,
                toItem: spacer,
                attribute: .Trailing,
                multiplier: 1,
                constant: 0))


            //pin spacer trailing with button leading
            wrapper.addConstraint(NSLayoutConstraint(
                item: spacer,
                attribute: .Trailing,
                relatedBy: .Equal,
                toItem: button,
                attribute: .Leading,
                multiplier: 1,
                constant: 0))

            //align button to center
            wrapper.addConstraint(NSLayoutConstraint(
                item: button,
                attribute: .CenterY,
                relatedBy: .Equal,
                toItem: wrapper,
                attribute: .CenterY,
                multiplier: 1,
                constant: 0))

            if let previous = previous {
                //pin spacer Leading with previous button trailing
                wrapper.addConstraint(NSLayoutConstraint(
                    item: spacer,
                    attribute: .Leading,
                    relatedBy: .Equal,
                    toItem: previous.button,
                    attribute: .Trailing,
                    multiplier: 1,
                    constant: 0))

                //pin previous button's Trailing with spacer Leading
                wrapper.addConstraint(NSLayoutConstraint(
                    item: previous.button,
                    attribute: .Trailing,
                    relatedBy: .Equal,
                    toItem: spacer,
                    attribute: .Leading,
                    multiplier: 1,
                    constant: 0))

                //set spacer's width same as previous spacer
                wrapper.addConstraint(NSLayoutConstraint(
                    item: spacer,
                    attribute: .Width,
                    relatedBy: .Equal,
                    toItem: previous.spacer,
                    attribute: .Width,
                    multiplier: 1,
                    constant: 0))

            } else {
                //this is the first item, pin the spacer Leading to wrapper Leading
                wrapper.addConstraint(NSLayoutConstraint(
                    item: spacer,
                    attribute: .Leading,
                    relatedBy: .Equal,
                    toItem: wrapper,
                    attribute: .Leading,
                    multiplier: 1,
                    constant: 0))
            }

            previous = (button: button, spacer: spacer)
        }
        // last spacer
        if let previous = previous {
            let spacer = UIView(frame: CGRectZero)
            spacer.translatesAutoresizingMaskIntoConstraints = false
            wrapper.addSubview(spacer)
            //pin spacer Leading with previous button trailing
            wrapper.addConstraint(NSLayoutConstraint(
                item: spacer,
                attribute: .Leading,
                relatedBy: .Equal,
                toItem: previous.button,
                attribute: .Trailing,
                multiplier: 1,
                constant: 0))


            //pin previous button's Trailing with spacer Leading
            wrapper.addConstraint(NSLayoutConstraint(
                item: previous.button,
                attribute: .Trailing,
                relatedBy: .Equal,
                toItem: spacer,
                attribute: .Leading,
                multiplier: 1,
                constant: 0))

            //set spacer's width same as previous spacer
            wrapper.addConstraint(NSLayoutConstraint(
                item: spacer,
                attribute: .Width,
                relatedBy: .Equal,
                toItem: previous.spacer,
                attribute: .Width,
                multiplier: 1,
                constant: 0))

            //pin spacer's Trailing with wrappper Trailing
            wrapper.addConstraint(NSLayoutConstraint(
                item: spacer,
                attribute: .Trailing,
                relatedBy: .Equal,
                toItem: wrapper,
                attribute: .Trailing,
                multiplier: 1,
                constant: 0))
        }

        wrapper.frame = CGRect(x: 0, y: 100, width: 320, height: 40)
    }


}