手动更改的iOS布局在UI中变为空

时间:2015-04-13 08:02:29

标签: ios iphone swift autolayout constraints

我的目标是在纵向或横向模式下手动控制自定义视图布局。在启动时,View通常可以通过纵向或横向模式显示子视图1和视图2,这意味着我的约束设置应该没问题。但是在旋转之后,视图将显示为空,而不是我期望的view1和view2布局。我无法理解如何强制UI刷新以显示我的新布局。

以下是我的代码段和测试结果。


class ConstraintViewController: UIViewController 
{
    let metrics = ["topMargin":64,"leftMargin":10,"rightMargin":10,"bottomMargin":10,"interSpace":20]
    var viewsDictionary: Dictionary<String,UIView!>?
    var view1: UIView?
    var view2: UIView?
    let button1 = UIButton.buttonWithType(UIButtonType.System) as UIButton
    let label1 = UILabel() as UILabel
    let atRest = "Doesn't do much"
    let atWork = "Secret Agent"

    override func viewDidLoad() {
        super.viewDidLoad()

        // Remove conflicting NSIBPrototypingLayoutConstraints.
        NSLayoutConstraint.deactivateConstraints(self.view.constraints())

        setupElements()
        println("In viewDidLoad")
     if(UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation)) {
            //Landscape code
            isPortrait = false
            landscapeConstraint()  
        } else {
            //Portrait code
            isPortrait = true
            portraitConstraint()
        }  
    }

    override func shouldAutorotate() -> Bool {
        return true
    }

    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        if(UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation)) {
            //Landscape code
            println("Detect landscape mode")
                NSLayoutConstraint.deactivateConstraints(self.view.constraints())
                self.view1!.removeConstraints(self.view1!.constraints())
                self.view2!.removeConstraints(self.view2!.constraints())
                self.view!.removeConstraints(self.view!.constraints())

                //self.view.removeConstraints(<#constraints: [AnyObject]#>)
                landscapeConstraint()

                self.view1?.layoutIfNeeded()
                self.view2?.layoutIfNeeded()
                self.view.layoutIfNeeded()
        } else {
            //Portrait code
            println("Detect portrait mode")
           NSLayoutConstraint.deactivateConstraints(self.view.constraints())
                self.view1!.removeConstraints(self.view1!.constraints())
                self.view2!.removeConstraints(self.view2!.constraints())
                self.view!.removeConstraints(self.view!.constraints())
                portraitConstraint()

                self.view1?.layoutIfNeeded()
                self.view2?.layoutIfNeeded()
                self.view.layoutIfNeeded()
        }
    }

    func setupElements() {

        //Make a view
        view1 = UIView()
        view1!.setTranslatesAutoresizingMaskIntoConstraints(false)
        view1!.backgroundColor = UIColor.redColor()

        //Make a second view
        view2 = UIView()
        view2!.setTranslatesAutoresizingMaskIntoConstraints(false)
        view2!.backgroundColor = UIColor(red: 0.75, green: 0.75, blue: 0.1, alpha: 1.0)

        //Make a label
        label1.text = atRest
        label1.setTranslatesAutoresizingMaskIntoConstraints(false)

        //Make a button
        button1.setTranslatesAutoresizingMaskIntoConstraints(false)
        button1.setTitle("Platypus", forState: UIControlState.Normal)
        button1.addTarget(self, action: "buttonPressed", forControlEvents: UIControlEvents.TouchUpInside)
        button1.backgroundColor = UIColor.blueColor()
        button1.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)

        //Add the views
        view.addSubview(view1!)
        view.addSubview(view2!)
        view2!.addSubview(button1)
        view2!.addSubview(label1)

        viewsDictionary = ["view":self.view,"view1":view1,"view2":view2,"button1":button1,"label1":label1]

    }

    func landscapeConstraint() {
        //--------------- landscape constraints
        println("In landscapeConstraint")
        //make dictionary for views
        //views
        let view1_constraint_V:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:|-topMargin-[view1]-bottomMargin-|", options: NSLayoutFormatOptions(0), metrics: metrics, views: viewsDictionary!)
        let view2_constraint_V:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:|-topMargin-[view2]-bottomMargin-|", options: NSLayoutFormatOptions(0), metrics: metrics, views: viewsDictionary!)
        let view_constraint_H:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[view1]-20-[view2]-10-|", options: NSLayoutFormatOptions.AlignAllTop, metrics: nil, views: viewsDictionary!)
        let view1_width_constraint = NSLayoutConstraint(item: view1!, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: view2!, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0)

        self.view.addConstraints(view1_constraint_V)
        self.view.addConstraints(view2_constraint_V)
        self.view.addConstraints(view_constraint_H)
        self.view.addConstraint(view1_width_constraint)

        //controls
        let control_constraint_H:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|-[button1(>=20)]-interSpace-[label1(>=30)]", options: NSLayoutFormatOptions.AlignAllCenterY, metrics: metrics, views: viewsDictionary!)
        let control_constraint_V:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:[button1(20)]-10-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary!)

        view2!.addConstraints(control_constraint_H)
        view2!.addConstraints(control_constraint_V)

    }

    func portraitConstraint() {
        //--------------- portrait constraints
        println("In portraitConstraint")
        //make dictionary for views
        //views
        let view1_constraint_H:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|-leftMargin-[view1]-rightMargin-|", options: NSLayoutFormatOptions(0), metrics: metrics, views: viewsDictionary!)
        let view2_constraint_H:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|-leftMargin-[view2]-rightMargin-|", options: NSLayoutFormatOptions(0), metrics: metrics, views: viewsDictionary!)
        let view_constraint_V:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:|-topMargin-[view1]-interSpace-[view2]-bottomMargin-|", options: NSLayoutFormatOptions.AlignAllLeading, metrics: metrics, views: viewsDictionary!)
        let view1_height_constraint = NSLayoutConstraint(item: view1!, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: view2!, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: 0)

        self.view.addConstraints(view1_constraint_H)
        self.view.addConstraints(view2_constraint_H)
        self.view.addConstraints(view_constraint_V)
        self.view.addConstraint(view1_height_constraint)

        //controls
        let control_constraint_H:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|-[button1(>=80)]-interSpace-[label1(>=100)]", options: NSLayoutFormatOptions.AlignAllCenterY, metrics: metrics, views: viewsDictionary!)
        let control_constraint_V:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:[button1(40)]-40-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary!)

        view2!.addConstraints(control_constraint_H)
        view2!.addConstraints(control_constraint_V)
    }
}

测试结果:

init布局视图显示正确。

旋转后,视图显示为空,未更新为预期的布局。

1 个答案:

答案 0 :(得分:0)

你写viewWillTransitionToSize的地方

 self.view!.removeConstraints(self.view!.constraints())

这将删除您添加的新约束,创建视图时创建的初始默认约束。如果没有这些默认约束,视图的大小将缩小为零,并且子视图的大小会缩小以匹配。

您可以创建新的实例变量

var viewInitialConstraints: [AnyObject]?

然后在viewDidAppear中(它在viewDidLoadviewWillAppear中不起作用)

viewInitialConstraints = view.constraints()

(将最初添加的额外约束移至ViewDidAppear),然后您可以写入viewWillTransitionToSize

view.removeConstraints(view.constraints())
view.addConstraints(viewInitialConstraints)

或者,您可以尝试跟踪您添加的约束:

view.removeConstraints(viewExtraConstraints)