Skip to content

Objective-C helper class to easily configure Auto-layout programmatically

Notifications You must be signed in to change notification settings

fmaylinch/autolayout-helper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NOTE: I started a new Swift version here.

AutolayoutHelper

This is a Objective-C class that can help you working with autolayout programmatically with the visual format language.

Installation

Just copy the files to your project.

Basic Usage

If you have a view where you want to put some subviews like v1 and v2, call this method:

[AutolayoutHelper configureView:view
                       subViews:VarBindings(v1, v2)
                        metrics:@{@"h":@(50)}
                    constraints:@[
                            @"H:|[v1]",
                            @"H:|[v2]|",
                            @"X:v1.width == v2.width / 2", // extended constraint
                            @"V:|-[v1(h)]-[v2]-|"
                    ]];

Note: VarBindings is defined as NSDictionaryOfVariableBindings. So VarBindings(v1, v2) is the same as @{@"v1":v1, @"v2":v2}.

This method prepares the subViews for autolayout (see here), adds them to view, and also adds the constraints to view.

IMPORTANT: subViews are not necessarily added to the view in the order you write them (because they're passed in a NSDictionary). If you want some views to be added after others, you may add them in different calls or use this convenience method:

// We want v3 to be above the other views
NSDictionary* layer1 = VarBindings(v1, v2);
NSDictionary* layer2 = VarBindings(v3);

AutolayoutHelper* layout = [AutolayoutHelper
    configureView:view
    subViewLayers:@[layer1, layer2]
     constraints:@[
         @"H:|[v1]|",
         @"H:|[v2]|",
         @"H:|[v3]",
         @"V:|-[v1]-[v2]-|",
         @"V:[v1]-[v3]",
      ]];

If you need some help with programatic autolayout, you can read this tutorial.

Advanced Usage

Using extended constraint expressions

AutolayoutHelper extends the visual format language by adding support for constraints that require the constraintWithItem method.

For example, let's say you want to add a constraint so the height of v1 is half the height of v2. You would normally do that this way:

NSLayoutConstraint* c =
    [NSLayoutConstraint constraintWithItem:v1
                attribute:NSLayoutAttributeWidth
                relatedBy:NSLayoutRelationEqual
                   toItem:v2
                attribute:NSLayoutAttributeWidth
               multiplier:0.5
                 constant:0];
[view addConstraint:c];

That creates and adds a constraint that can be thought as this equation:

v1.width == v2.width * 0.5 + 0

The equation is easier to read. And we could even simplify it as:

v1.width == v2.width / 2

With AutolayoutHelper you could write that constraint like this:

    @"X:v1.width == v2.width / 2"

"X" stands for "extended". The syntax for extended constraints is:

X:view1.attr1 relation view2.attr2 *|/ mult +|- const
  • You can use any subview or refer to the superview using the superview key.
  • You may use any attribute supported in iOS7 (see NSLayoutAttribute).
  • The relation can be ==, <= or >=.
  • The multiplier is optional (default: 1). Use * or / and a floating point number or a metric.
  • The constant is optional (default: 0). Use + or - and a floating point number or a metric.

Examples:

    @"X:v1.top == v2.centerY * 0.5 - 10"      // using multiplier and constant
    @"X:v1.top >= v2.bottom"                  // using relation >= and no multiplier or constant
    @"X:v1.centerX == superview.centerX + x"  // using superview and a metric named "x"

Adding and removing views and constraints dynamically

Let's say you created the following layout. Notice is the same as the one above, but storing the result in a variable of type AutolayoutHelper.

AutolayoutHelper* layout = [AutolayoutHelper
                  configureView:view
                       subViews:VarBindings(v1, v2)
                    constraints:@[
                            @"H:|[v1]|",
                            @"H:|[v2]|",
                            @"V:|-[v1]-[v2]-|"
                    ]];

Now let's suppose you want to replace the view v2 by another v3.

First, remove v2 with one of these methods:

[layout removeViews:VarBindings(v2)];
// or
[layout removeViewsWithKeys:@[@"v2"]];

Now the parts of the constraints that include the removed view v2 will be automatically removed from the view, so the remaining constraints are: "H:|[v1]|" and "V:|-[v1]". (We're left with the part of the vertical constraint that doesn't mention v2).

Now add v3 and the necessary constraints:

[layout addViews:VarBindings(v3)
     constraints:@[
             @"H:|[v3]|",
             @"V:|-[v1]-[v3]-|"
     ]];

Now let's suppose you want to remove v3 but you don't want to add any other view.

First remove v3:

[layout removeViews:VarBindings(v3)];
// or
[layout removeViewsWithKeys:@[@"v3"]];

Now, like before, we're left with these constraints: "H:|[v1]|" and "V:|-[v1]". So you may want to complete the vertical constraint to anchor v1 to the bottom of the view:

[layout addConstraint:@"V:[v1]-|"]

Switching constraints

Let's suppose you want to switch between the constraints "V:|-[v1]-[v2]-|" and "V:|-[v2]-[v1]-|" in order to swap v1 and v2 vertically. First add the constraints that won't change:

AutolayoutHelper* layout = [AutolayoutHelper
                  configureView:view
                       subViews:VarBindings(v1, v2)
                    constraints:@[
                            @"H:|[v1]|",
                            @"H:|[v2]|"
                    ]];

Then add the constraints you want first, and assign a key for them:

[layout addConstraints:@[@"V:|-[v1]-[v2]-|"] forKey:@"vertical swap"]

To switch to the other constraints, just add them using the same key. The constraints that we added before for that key will be replaced by the new ones:

[layout addConstraints:@[@"V:|-[v2]-[v1]-|"] forKey:@"vertical swap"]

Using UIScrollView

If you need to use a UIScrollView with autolayout, check this Stack Overflow answer.

You can use the configureScrollView helper method if you want the typical UIScrollView for vertical scrolling where the content view fills the width of the main view. Here's an example:

UIScrollView* scrollView = [[UIScrollView alloc] init];

// Here the scrollView fills the main view, but you might want to add
// other views (like a fixed button at the bottom).
[AutolayoutHelper configureView:self.view
                       subViews:VarBindings(scrollView)
                    constraints:@[ @"H:|[scrollView]|", @"V:|[scrollView]|" ]];

// This view will be the content of the scrollView
UIView* scrollContent = [[UIView alloc] init];

// This method adds the scrollContent to the scrollView and makes it
// as wide as the self.view (the height will be adjusted depending on
// the views you add to the scrollContent later)
[AutolayoutHelper configureScrollView:scrollView contentView:scrollContent mainView:self.view];

// Now, for example, we configure the scrollContent by adding 3 views.
// The scrollContent height will be automatically adjusted thanks to the
// @"V:|-[v1]-[v2]-[v3]-|" constraint. The scrollView contentSize is also
// adjusted automatically to the size of the scrollContent. 
[AutolayoutHelper configureView:scrollContent
                       subViews:VarBindings(v1, v2, v3)
                    constraints:@[
                            @"H:|-[v1]-|",
                            @"H:|-[v2]-|",
                            @"H:|-[v3]-|",
                            @"V:|-[v1]-[v2]-[v3]-|" // The "|" symbols here are important!
                    ]];

Debugging your layout

When programming your layout, it might be helpful to enable an option to set random background colors to the views, so you can see how the views are being positioned and sized. Call it before configuring the views:

[AutolayoutHelper setDisplayBackgroundColorsForDebugging:YES];

About

Objective-C helper class to easily configure Auto-layout programmatically

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published