How to align the top of a view to half the parent view's height in Xcode 6.1

3.5k Views Asked by At

I am trying to align the top of the white subview to half the height of the container view in the viewcontroller. See attached image. In old versions of Xcode it was possible to CTRL-drag from the view to the container view and select "top alignment with the container view", but in the new Xcode 6.1 they offer only alignment with the "TopLayout guide". So I used that constraint and setup the constraint as you can see in the right hand side of the image. Based on my reading, the following equation applies:

property1 = property2 * multiplier + constant.

So I wanted to do this with my settings: View.top = TopLayoutGuide.bottom * 0.5 + 0

such that the top of the white "View" aligns with half the height of the TopLayoutGuide.bottom. However, when I do this, the result is that the ).5 is totally ignored, and the white view's top is aligned with the TopLayouGuide.bottom, covering the whole screen basically.

Can someone figure out what I am doing wrong, and what is the proper way to align the View's top to half the height of the container?

thanks

-Malenasee image below

2

There are 2 best solutions below

2
On

You can't achieve what you want to do in Interface Builder. But this is possible by creating constraints via code. I have created a sample project for you which you can download from Here

Below is the code of ViewController file to add constraints via code. Note: I have added arbitrary constraints in Interface Builder since we need to get the main view height. Those are also important

//
//  ViewController.swift
//  Test
//
//  Created by FR-MAC on 11/12/14.
//  Copyright (c) 2014 ABC. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var mySubview: UIView!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    self.addContraintsForMoviePlayerView(self.mySubview, superView: self.view)

}

func addContraintsForMoviePlayerView(var view:UIView, superView:UIView) -> Void {

    view.setTranslatesAutoresizingMaskIntoConstraints(false)
    let leftConstraint = NSLayoutConstraint(item: view, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: superView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0)

    let rightConstraint = NSLayoutConstraint(item: view, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: superView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0)

    let bottomConstraint = NSLayoutConstraint(item: view, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: superView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0)

    var topValue:CGFloat = superView.frame.size.height
    topValue = topValue/2

    let topConstraint = NSLayoutConstraint(item: view, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: view.superview?, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: topValue)

    // Remove the constraints created in Interface Builder to avoid autolayout constraint issues. We just added those constraints to get the correct height of self.view.frame which we used to create above topConstaint
    self.view.removeConstraints(self.view.constraints())

    //Add the above created constraints
    superView.addConstraints( [leftConstraint, rightConstraint, topConstraint, bottomConstraint] )
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
}

Hope this helps you :)

0
On

I encountered the same problem with Xcode 6.1. I found that there are several ways to use only the storyboard editor to split a view (nearly) in half by adding a subview to use as a sort of benchmark. iMemon's programmatic solution works, but it requires additional code for constraints on any objects that use the halfway point as a reference, which can get tedious.

To solve your problem:

  1. Add another view to the controller's main view.
  2. Give it a color that stands out against its background.
  3. Give it a height of 1.
  4. Move it to the center of the main view and give it the "Vertical Center in Container" constraint.
  5. Now you can drag the top or bottom of any object to align with the frame of the view you just added. You can apply constraints by control+click+dragging from any object to the new view and selecting the appropriate constraint from the pop-up menu.
  6. Change the color of your benchmark view to something that will make it invisible in your application. I just used a clear color, as the object I wanted to align was also clear, and I had a background. If clear doesn't work for you, you could try constraining the width of the benchmark view to match the width of the object you aligned, then give them the same color.

You can extend this idea of using views as benchmarks to other situations, such as aligning with a point 3/4 the distance between two objects. You can add objects to views, apply constraints within those, and then move the views around and apply constraints in their superview as well. Get creative and experiment with it.