Auto Layout and Constraints

Duration

15 minutes

Lab Goals

The goal of this lab is to work with constraints in code. To demonstrate this, we will update designer created constraints when the device's orientation changes. This will allow our application to make more effective use of the available screen space.

Required assets

You can use your project from the previous exercise, or use the completed project in the Exercise 1 folder.

Note: if you did the bonus steps from the previous exercise, you'll need to remove the UILabel added at the end before continuing with this exercise.

Steps

Name the Constraints on the Text View

Our goal is to make more effective use of our screen space by updating the constraints on the UITextView. Specifically, we're going to change the leading and top edge constraints.

  1. Start by running the application in the simulator or on a device.
  2. Rotate the device and notice how the text remains on the bottom of the image - the constraints are properly keeping things positioned, but what if we want the text to move to the right side of the image?
  1. Open the MainStoryboard.storyboard file.
  2. Click on the Text View which is displaying the text in the designer to select it
  3. On the Properties Tab, select Layout.
  4. Select the Leading Space constraint, it should say "Leading Space to:" - notice the constraint is also highlighted in the design surface when selected.
  5. Edit the constraint and set the Name to constLeftText.
  6. Repeat the steps above but this time select the top edge constraint. It will specify "Top Space to: Image View ...".
  7. Name the Top Edge constraints constTopText.

Create the helper method GetConstraint

We're now going to start working in the code behind. To simplify some of the steps we'll use a helper method. This method will allow us to create a new constraint based upon an existing constraint.

We will use named parameters to simplify the calling code and C# nullable types to pass in optional floating point values.

  1. Open ViewController.cs.
  2. Add the method in the code block below.
    • It takes an existing constraint - either the top or leading space constraint we named.
    • It takes optional new values to assign to the first object + attribute, relationship, second object + attribute, multiplier and constant.
    • Using the parameters, it creates a new constraint using NSLayoutConstraint.Create and returns it to the caller. If a parameter is not supplied (passed as null, then it uses the current value of the existing constraint.
    • You may need to add the Foundation namespace.
//helper method to create constraints based on existing constraints
NSLayoutConstraint GetConstraint (
   NSLayoutConstraint constraint,
   NSObject object1 = null,
   NSLayoutAttribute? attribute1 = null,
   NSLayoutRelation? relation = null,
   NSObject object2 = null,
   NSLayoutAttribute? attribute2 = null,
   nfloat? multiplier = null,
   nfloat? constant = null)
{
   if (constraint == null)
            return null;
   return NSLayoutConstraint.Create(
            object1 ?? constraint.FirstItem,
            (attribute1 == null) ? constraint.FirstAttribute : attribute1.Value,
            (relation == null) ? constraint.Relation : relation.Value,
            object2 ?? constraint.SecondItem, 
            (attribute2 == null) ? constraint.SecondAttribute : attribute2.Value,
            (multiplier == null) ? constraint.Multiplier : multiplier.Value,
            (constant == null) ? constraint.Constant : constant.Value);
}

Handle Orientation Changes

Now we'll add code to respond to orientation changes.

  1. Override the WillRotate method.
  2. Create a new method called SetOrientation that accepts a bool indicating orientation, we will pass true if the orientation is Landscape.
  3. Call your new SetOrientation from the WillRotate method and pass the boolean by evaluating the toInterfaceOrientation parameter.

Show Code

Update the Edge Constraints on the Text View

In the SetOrientation method you just created, you're going to check if we're changing to landscape or portrait, and in response, update the constraints as necessary. To to do this, we'll need to remove the old constraints, create new constraints for what we want to change, and add it to the root View. We'll start with the Leading constraint.

  1. Remove the constLeftText constraint using the RemoveConstraint method on the parent view (this.View)
  2. Create a new constraint and pass in the object2 parameter:
    • if we're in landscape pass in the imgMonkey.
    • otherwise pass it the root View property.
    and the attribute2 parameter as NSLayoutAttribute.Trailing for landscape and NSLayoutAttribute.Leading for portrait.
  3. Add the new constraint to the root View.
  4. Repeat the above steps for the Top constraint but in this case, swap the views used for the object2 parameter (e.g. imgMonkey should be used in portrait). Pass in NSLayoutAttribute.Top for landscape and NSLayoutAttribute.Bottom as the attribute2 parameter for portrait.

Show Code

  1. Run the app again and try rotating the device to see the new constraints in action.

Summary

In this exercise, we created and replaced constraints programmatically to respond to device orientation changes.

Go Back