Coder Social home page Coder Social logo

snapkit / masonry Goto Github PK

View Code? Open in Web Editor NEW
18.1K 716.0 3.1K 767 KB

Harness the power of AutoLayout NSLayoutConstraints with a simplified, chainable and expressive syntax. Supports iOS and OSX Auto Layout

License: MIT License

Objective-C 97.83% Ruby 1.79% Shell 0.38%

masonry's Introduction

Masonry Build Status Coverage Status Carthage compatible Pod Version

Masonry is still actively maintained, we are committed to fixing bugs and merging good quality PRs from the wider community. However if you're using Swift in your project, we recommend using SnapKit as it provides better type safety with a simpler API.

Masonry is a light-weight layout framework which wraps AutoLayout with a nicer syntax. Masonry has its own layout DSL which provides a chainable way of describing your NSLayoutConstraints which results in layout code that is more concise and readable. Masonry supports iOS and Mac OS X.

For examples take a look at the Masonry iOS Examples project in the Masonry workspace. You will need to run pod install after downloading.

What's wrong with NSLayoutConstraints?

Under the hood Auto Layout is a powerful and flexible way of organising and laying out your views. However creating constraints from code is verbose and not very descriptive. Imagine a simple example in which you want to have a view fill its superview but inset by 10 pixels on every side

UIView *superview = self.view;

UIView *view1 = [[UIView alloc] init];
view1.translatesAutoresizingMaskIntoConstraints = NO;
view1.backgroundColor = [UIColor greenColor];
[superview addSubview:view1];

UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[superview addConstraints:@[

    //view1 constraints
    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeTop
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeTop
                                multiplier:1.0
                                  constant:padding.top],

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeLeft
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeLeft
                                multiplier:1.0
                                  constant:padding.left],

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeBottom
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeBottom
                                multiplier:1.0
                                  constant:-padding.bottom],

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeRight
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeRight
                                multiplier:1
                                  constant:-padding.right],

 ]];

Even with such a simple example the code needed is quite verbose and quickly becomes unreadable when you have more than 2 or 3 views. Another option is to use Visual Format Language (VFL), which is a bit less long winded. However the ASCII type syntax has its own pitfalls and its also a bit harder to animate as NSLayoutConstraint constraintsWithVisualFormat: returns an array.

Prepare to meet your Maker!

Heres the same constraints created using MASConstraintMaker

UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler
    make.left.equalTo(superview.mas_left).with.offset(padding.left);
    make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom);
    make.right.equalTo(superview.mas_right).with.offset(-padding.right);
}];

Or even shorter

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(superview).with.insets(padding);
}];

Also note in the first example we had to add the constraints to the superview [superview addConstraints:.... Masonry however will automagically add constraints to the appropriate view.

Masonry will also call view1.translatesAutoresizingMaskIntoConstraints = NO; for you.

Not all things are created equal

.equalTo equivalent to NSLayoutRelationEqual

.lessThanOrEqualTo equivalent to NSLayoutRelationLessThanOrEqual

.greaterThanOrEqualTo equivalent to NSLayoutRelationGreaterThanOrEqual

These three equality constraints accept one argument which can be any of the following:

1. MASViewAttribute

make.centerX.lessThanOrEqualTo(view2.mas_left);
MASViewAttribute NSLayoutAttribute
view.mas_left NSLayoutAttributeLeft
view.mas_right NSLayoutAttributeRight
view.mas_top NSLayoutAttributeTop
view.mas_bottom NSLayoutAttributeBottom
view.mas_leading NSLayoutAttributeLeading
view.mas_trailing NSLayoutAttributeTrailing
view.mas_width NSLayoutAttributeWidth
view.mas_height NSLayoutAttributeHeight
view.mas_centerX NSLayoutAttributeCenterX
view.mas_centerY NSLayoutAttributeCenterY
view.mas_baseline NSLayoutAttributeBaseline

2. UIView/NSView

if you want view.left to be greater than or equal to label.left :

//these two constraints are exactly the same
make.left.greaterThanOrEqualTo(label);
make.left.greaterThanOrEqualTo(label.mas_left);

3. NSNumber

Auto Layout allows width and height to be set to constant values. if you want to set view to have a minimum and maximum width you could pass a number to the equality blocks:

//width >= 200 && width <= 400
make.width.greaterThanOrEqualTo(@200);
make.width.lessThanOrEqualTo(@400)

However Auto Layout does not allow alignment attributes such as left, right, centerY etc to be set to constant values. So if you pass a NSNumber for these attributes Masonry will turn these into constraints relative to the view’s superview ie:

//creates view.left = view.superview.left + 10
make.left.lessThanOrEqualTo(@10)

Instead of using NSNumber, you can use primitives and structs to build your constraints, like so:

make.top.mas_equalTo(42);
make.height.mas_equalTo(20);
make.size.mas_equalTo(CGSizeMake(50, 100));
make.edges.mas_equalTo(UIEdgeInsetsMake(10, 0, 10, 0));
make.left.mas_equalTo(view).mas_offset(UIEdgeInsetsMake(10, 0, 10, 0));

By default, macros which support autoboxing are prefixed with mas_. Unprefixed versions are available by defining MAS_SHORTHAND_GLOBALS before importing Masonry.

4. NSArray

An array of a mixture of any of the previous types

make.height.equalTo(@[view1.mas_height, view2.mas_height]);
make.height.equalTo(@[view1, view2]);
make.left.equalTo(@[view1, @100, view3.right]);

Learn to prioritize

.priority allows you to specify an exact priority

.priorityHigh equivalent to UILayoutPriorityDefaultHigh

.priorityMedium is half way between high and low

.priorityLow equivalent to UILayoutPriorityDefaultLow

Priorities are can be tacked on to the end of a constraint chain like so:

make.left.greaterThanOrEqualTo(label.mas_left).with.priorityLow();

make.top.equalTo(label.mas_top).with.priority(600);

Composition, composition, composition

Masonry also gives you a few convenience methods which create multiple constraints at the same time. These are called MASCompositeConstraints

edges

// make top, left, bottom, right equal view2
make.edges.equalTo(view2);

// make top = superview.top + 5, left = superview.left + 10,
//      bottom = superview.bottom - 15, right = superview.right - 20
make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20))

size

// make width and height greater than or equal to titleLabel
make.size.greaterThanOrEqualTo(titleLabel)

// make width = superview.width + 100, height = superview.height - 50
make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50))

center

// make centerX and centerY = button1
make.center.equalTo(button1)

// make centerX = superview.centerX - 5, centerY = superview.centerY + 10
make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10))

You can chain view attributes for increased readability:

// All edges but the top should equal those of the superview
make.left.right.and.bottom.equalTo(superview);
make.top.equalTo(otherView);

Hold on for dear life

Sometimes you need modify existing constraints in order to animate or remove/replace constraints. In Masonry there are a few different approaches to updating constraints.

1. References

You can hold on to a reference of a particular constraint by assigning the result of a constraint make expression to a local variable or a class property. You could also reference multiple constraints by storing them away in an array.

// in public/private interface
@property (nonatomic, strong) MASConstraint *topConstraint;

...

// when making constraints
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    self.topConstraint = make.top.equalTo(superview.mas_top).with.offset(padding.top);
    make.left.equalTo(superview.mas_left).with.offset(padding.left);
}];

...
// then later you can call
[self.topConstraint uninstall];

2. mas_updateConstraints

Alternatively if you are only updating the constant value of the constraint you can use the convience method mas_updateConstraints instead of mas_makeConstraints

// this is Apple's recommended place for adding/updating constraints
// this method can get called multiple times in response to setNeedsUpdateConstraints
// which can be called by UIKit internally or in your code if you need to trigger an update to your constraints
- (void)updateConstraints {
    [self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self);
        make.width.equalTo(@(self.buttonSize.width)).priorityLow();
        make.height.equalTo(@(self.buttonSize.height)).priorityLow();
        make.width.lessThanOrEqualTo(self);
        make.height.lessThanOrEqualTo(self);
    }];

    //according to apple super should be called at end of method
    [super updateConstraints];
}

3. mas_remakeConstraints

mas_updateConstraints is useful for updating a set of constraints, but doing anything beyond updating constant values can get exhausting. That's where mas_remakeConstraints comes in.

mas_remakeConstraints is similar to mas_updateConstraints, but instead of updating constant values, it will remove all of its constraints before installing them again. This lets you provide different constraints without having to keep around references to ones which you want to remove.

- (void)changeButtonPosition {
    [self.button mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.size.equalTo(self.buttonSize);

        if (topLeft) {
        	make.top.and.left.offset(10);
        } else {
        	make.bottom.and.right.offset(-10);
        }
    }];
}

You can find more detailed examples of all three approaches in the Masonry iOS Examples project.

When the ^&*!@ hits the fan!

Laying out your views doesn't always goto plan. So when things literally go pear shaped, you don't want to be looking at console output like this:

Unable to simultaneously satisfy constraints.....blah blah blah....
(
    "<NSLayoutConstraint:0x7189ac0 V:[UILabel:0x7186980(>=5000)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x839ea20 h=--& v=--& V:[MASExampleDebuggingView:0x7186560(416)]>",
    "<NSLayoutConstraint:0x7189c70 UILabel:0x7186980.bottom == MASExampleDebuggingView:0x7186560.bottom - 10>",
    "<NSLayoutConstraint:0x7189560 V:|-(1)-[UILabel:0x7186980]   (Names: '|':MASExampleDebuggingView:0x7186560 )>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7189ac0 V:[UILabel:0x7186980(>=5000)]>

Masonry adds a category to NSLayoutConstraint which overrides the default implementation of - (NSString *)description. Now you can give meaningful names to views and constraints, and also easily pick out the constraints created by Masonry.

which means your console output can now look like this:

Unable to simultaneously satisfy constraints......blah blah blah....
(
    "<NSAutoresizingMaskLayoutConstraint:0x8887740 MASExampleDebuggingView:superview.height == 416>",
    "<MASLayoutConstraint:ConstantConstraint UILabel:messageLabel.height >= 5000>",
    "<MASLayoutConstraint:BottomConstraint UILabel:messageLabel.bottom == MASExampleDebuggingView:superview.bottom - 10>",
    "<MASLayoutConstraint:ConflictingConstraint[0] UILabel:messageLabel.top == MASExampleDebuggingView:superview.top + 1>"
)

Will attempt to recover by breaking constraint
<MASLayoutConstraint:ConstantConstraint UILabel:messageLabel.height >= 5000>

For an example of how to set this up take a look at the Masonry iOS Examples project in the Masonry workspace.

Where should I create my constraints?

@implementation DIYCustomView

- (id)init {
    self = [super init];
    if (!self) return nil;

    // --- Create your views here ---
    self.button = [[UIButton alloc] init];

    return self;
}

// tell UIKit that you are using AutoLayout
+ (BOOL)requiresConstraintBasedLayout {
    return YES;
}

// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {

    // --- remake/update constraints here
    [self.button remakeConstraints:^(MASConstraintMaker *make) {
        make.width.equalTo(@(self.buttonSize.width));
        make.height.equalTo(@(self.buttonSize.height));
    }];
    
    //according to apple super should be called at end of method
    [super updateConstraints];
}

- (void)didTapButton:(UIButton *)button {
    // --- Do your changes ie change variables that affect your layout etc ---
    self.buttonSize = CGSize(200, 200);

    // tell constraints they need updating
    [self setNeedsUpdateConstraints];
}

@end

Installation

Use the orsome CocoaPods.

In your Podfile

pod 'Masonry'

If you want to use masonry without all those pesky 'mas_' prefixes. Add #define MAS_SHORTHAND to your prefix.pch before importing Masonry

#define MAS_SHORTHAND

Get busy Masoning

#import "Masonry.h"

Code Snippets

Copy the included code snippets to ~/Library/Developer/Xcode/UserData/CodeSnippets to write your masonry blocks at lightning speed!

mas_make -> [<#view#> mas_makeConstraints:^(MASConstraintMaker *make) { <#code#> }];

mas_update -> [<#view#> mas_updateConstraints:^(MASConstraintMaker *make) { <#code#> }];

mas_remake -> [<#view#> mas_remakeConstraints:^(MASConstraintMaker *make) { <#code#> }];

Features

  • Not limited to subset of Auto Layout. Anything NSLayoutConstraint can do, Masonry can do too!
  • Great debug support, give your views and constraints meaningful names.
  • Constraints read like sentences.
  • No crazy macro magic. Masonry won't pollute the global namespace with macros.
  • Not string or dictionary based and hence you get compile time checking.

TODO

  • Eye candy
  • Mac example project
  • More tests and examples

masonry's People

Contributors

0oneo avatar adempseybox avatar ahti avatar andreyoshev avatar bjallen avatar cloudkite avatar craigsiemens avatar danielrhammond avatar dinosaurdad avatar dlo avatar edoardoc avatar erichoracek avatar fabb avatar game3108 avatar gobetti avatar griffinmacias avatar honood avatar idalink avatar iwill avatar kouky avatar kovpas avatar msqr avatar nickynick avatar pingyourid avatar ploddi avatar rastersize avatar rea-myles-abbott avatar robertjpayne avatar sibljon avatar vascoorey avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

masonry's Issues

Examples don't compile 'out of the box'

So, I downloaded a zip of your archive, ran pod install, opened up the workspace, and switched my target to the example project. When I hit Run, it gave me a compile error saying that Masonry.h couldn't be found (from the example project's PCH file).

I had to modify the import line to be:

#import "Masonry/Masonry.h"

for it to work.

This is in Xcode 4.6.3.

MAS_ATTR_FORWARD(attribute) raises a warning if mismatched-return-types is enabled

If the flag -Wmismatched-return-types is set, the new property attribute from MASShorthandAdditions introduced in v0.5.0 will raise a warning when forwarding it to the non-shorthand equivalent.

This is the output from the compiler:

conflicting return type in implementation of 'attribute': 'MASViewAttribute *(^)(NSLayoutAttribute)' vs 'MASViewAttribute *' [-Wmismatched-return-types]
MAS_ATTR_FORWARD(attribute);

Insufficient examples

I plan to use masonery to build forms. I try to follow the examples but found it not enough.

For example, if I try to recreate

https://stripe.com/docs/checkout

(click in pay with card), I need to:

  • Add several rows of controls
  • Align the control to the left & center
  • Put the labels on top of each control
  • Keep the separation between them, and build the relations

So far, I have only work by trial and error and mainly things work with exact values (defeating the use of a layout manager).

I'm sure I have not get the library (neither with https://github.com/iMartinKiss/KeepLayout) so some more complete examples could help

Incorporating top layout guide

I am using a transparent UINavigationBar and UITextField. I want it to be 20px under the navigation bar, so I'm using the following commands:

[self.emailTextField mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo((self.view).mas_top).with.offset(20);
}];

However, my text field appears beneath the navigation bar, 20px from the top of the screen.

-- iOS 7 SPOILER ALERT --

In iOS 7 there is a topLayoutGuide property on UIViewController. How can I incorporate it using Masonry, so my text field appears under the navigation bar (84px from the top of the screen) both in iOS 7 with transparent navigation bar and in iOS 6?

I know that it can be done using NSLayoutConstraints. Taken from the documentation:

id topGuide = myViewController.topLayoutGuide;
// "button" is a UIButton object specified elsewhere
[myViewController.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[topGuide]-20-[button]"]];

Constraints strangely breaking

Hey I have some constraints that are oddly breaking and am hoping you can help me out.

Here's the scenario. I have a UIViewController with a custom toolbar at the bottom. The toolbar has 4 buttons, all equal height, and when switching between portrait and landscape mode the button widths will adjust equally to fill the view width. This works great when I test this in a ViewController that only has this custom toolbar.

However, in one of my more complex UIViewControllers that has many subviews with constraints, the toolbar constraint is breaking on the button widths.

I've tested on these devices.

iPhone 4 iOS 6 - breaks
iPad Mini iOS 6 - does not break
iPhone Simulator iOS 6 - breaks
iPhone Simulator iOS 7 - does not break

Here's my init function in my custom toolbar class. At the bottom of the function is where I do the auto layout for my toolbar. I must not be creating equal widths properly?

  • (id)init
    {
    self = [super init];
    if (self) {
    // Initialization code here.

    BOOL isIphone = [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone;
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    
    CGFloat viewHeight;
    if (isIphone)
    {
        viewHeight = 80.0f;
    }
    else//iPad
    {
        viewHeight = 100.0f;
    }
    
    self.view = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, screenSize.width, viewHeight)];
    self.view.backgroundColor = [UIColor grayColor];
    
    //add buttons
    
    _buttons = [[NSMutableArray alloc] init];
    
    UIButton *button;
    //CGFloat buttonWidth = screenSize.width / 4.0f;
    CGFloat buttonHeight = viewHeight;
    
    for (NSUInteger i = 0; i < 4; ++i)
    {
        button = [UIButton buttonWithType:UIButtonTypeCustom];
    
        [_buttons addObject:button];
    
        [self.view addSubview:button];
    }
    
    //auto layout
    UIButton *button0 = [_buttons objectAtIndex:0];
    UIButton *button1 = [_buttons objectAtIndex:1];
    UIButton *button2 = [_buttons objectAtIndex:2];
    UIButton *button3 = [_buttons objectAtIndex:3];
    
    self.view.mas_key = @"self.view";
    button0.mas_key = @"button0";
    button1.mas_key = @"button1";
    button2.mas_key = @"button2";
    button3.mas_key = @"button3";
    
    [button0 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.view.mas_left);
        make.bottom.equalTo(self.view.mas_bottom);
        make.right.equalTo(button1.mas_left);
    
        make.width.equalTo(button1.mas_width);
        make.height.equalTo([NSNumber numberWithFloat:buttonHeight]);
    }];
    
    [button1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(self.view.mas_bottom);
        make.left.equalTo(button0.mas_right);
        make.right.equalTo(self.view.mas_centerX);
    
        make.width.equalTo(button0.mas_width);
        make.height.equalTo([NSNumber numberWithFloat:buttonHeight]);
    }];
    
    [button2 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(self.view.mas_bottom);
        make.left.equalTo(self.view.mas_centerX);
        make.right.equalTo(button3.mas_left);
    
        make.width.equalTo(button3.mas_width);
        make.height.equalTo([NSNumber numberWithFloat:buttonHeight]);
    }];
    
    [button3 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(self.view.mas_bottom);
        make.left.equalTo(button2.mas_right);
        make.right.equalTo(self.view.mas_right);
    
        make.width.equalTo(button2.mas_width);
        make.height.equalTo([NSNumber numberWithFloat:buttonHeight]);
    }];
    

    }

    return self;
    }

Expose MASConstraintMaker's view property

First off, thanks for the amazing library! You've successfully made writing autolayout code a breeze.

It would be helpful to have MASConstraintMaker's view property exposed so that the following code could be written:

[view mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(make.view.superview);
}];

This way, constraints could be defined relative to the view's superview, regardless of if the superview is changed down the line in your implementation.

Additionally, this means that copy-pasting layout code when writing it would result in less occurrences of:

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(view1.superview);
}];
[view2 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(view1.superview);
}];

Where view2 is constrained to view1's superview, which is an easy to miss but hard to debug error.

Animator proxy on OS X seems to have some problem

Hi!

I use Masonry in my real cocoa project. All things are cool before adding support for the animator proxy on OS X #41 .

Arter #41 All my teammate except me have the following problem:
9qs4 rxufg8vrce6t __yj

So I do some test:

  1. I build a new Cocoa Application
  2. add the podfile with single line: pod 'Masonry'
  3. run 'pod install' with cocoapods 0.29.0
  4. this project still work fine on my computer and the same problem on my teammate's computer.

Using the animator proxy on OSX

I noticed you can't get to the animator proxy on OSX using Masonry. I was thinking of adding this feature, but before I do, do you have any idea on the best way to expose this?

This is a OSX only feature, and I don't want to sprinkle the code with #ifdefs, and also don't want to expose the underlying NSLayoutConstraint(s) on the MASConstraint protocol.

I thought about adding a delegate method, but that's far from elegant.

Maybe adding this to MASConstraint protocol:

#ifdef TARGET_OS_MAC && !TARGET_OS_IPHONE
@property (nonatomic, copy, readonly) id<MASConstraint> (^animated)(BOOL useAnimator);
#endif
- (void)update:(void (^)(id<MASConstraint>)block; 

After installing a constraint, updating it would be something like:

[self.heightConstraint update:^(id<MASConstraint> constraint){
    constraint.equalTo(@(100)).animated(YES);
}];

What do you think?

Idea: make.superview

I often use a pattern as the following:

- (instancetype)init...
UIView * mySubView = [UIView new];
[myView addSubview:mySubView];
[mySubView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(mySubView.superview);
}];

So I refer to myView indirectly using mySubView.superview. This is because it often eases refactoring, for instance if I want to introduce a container view between myView and mySubView.

I wonder if it would make sense to introduce a make.superview? This way, the constraints related to the actual view would be easier to recognize.

Also, I try to use mas_makeConstraints: as often as I can, since in my mind, constraints are almost always immutable, except when animating.

What are your comments to the above points? Are they patterns or anti-patterns? :-)

-[MASConstraint and] prevents compilation under Xcode 6 Beta 3

- (MASConstraint *)and;

When compiling my Swift project with this project included in my bridging header, I get a compilation error due to this line above. The error is as follows:

<unknown>:0: error:
    /path/to/Pods/Headers/Masonry/MASConstraint.h:113:
    expected selector for Objective-C method

When I comment out the line, compilation proceeds quite happily.

This is based off of head, latest commit being bec7297 (so this includes the fix from #84). Am I doing something wrong, or missing something?

Example for calculating a width or height

HI,
i've been using Masonry now for the past week and it's awesome.

But i have a question and perhaps you could add it to the examples. How do you do calculations in the equalTo function?

I want to do something like have a view which has a width the same as its superview but, the height should only be a third. Normally i would do CGRectGetWidth(superView.bounds) / 3, but how should i do it with Masonry?

[myView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.center.equalTo(superView);
    make.width.equalTo(superView.mas_width);
    make.height.equalTo(superView.mas_width); //It needs to be a third of the width
}];

thx!

Live reload possible in some way?

After I started using classy.as for my styling I have quickly become addicted to the live reloading feature. I'm thinking if we could somehow do something similar for Masonry it would be awesome. I don't know how this would work thought.

It's mostly my constant numbers I would like to change live. Today I use DCIntrospect (https://github.com/lukaswelte/DCIntrospect-ARC) to adjust frames in the simulator and then I have to remember the new constant values and change them in the code afterwards.

Could we define all constants in a separate file that is watched by Masonry. So that changes in the constant file would be injected into the running simulator?

Calling Masonry methods on root view causes layout problems

It seems that setting translatesAutoresizingMaskIntoConstraints=NO on the root view (i.e., the root view controller's view) has a bad effect on auto layout. Masonry implicitly changes that setting, so if it is used in the wrong way, it can cause nasty bugs.

HOW TO REPRODUCE: (I'll try to provide a toy example later, when time is less desperately tight, if desired)

  1. Set up a root view containing some subviews. Use auto layout to position the subviews relative to the root view.
  2. Set translatesAutoresizingMaskIntoConstraints=NO on window.rootViewController.view.
  3. From the rootViewController, present a modal view controller and then dismiss it.
  4. You will probably see a completely wrecked view layout; specifically, the main view is no longer sized to fit the window.

THE WORKAROUND: If RV is the root view and SV is a subview, then avoid calls of the form:

[RV.makeConstraints  .... {
    ... SV ... 
}]

and instead use:

[SV.makeConstraints ... {
    ... RV ...
}]

Note that this situation doesn't apply to every superview/subview relation, only when the superview is the topmost view.

THE FIX? Probably Masonry should check to see if the view on which the Masonry method is being called is the root view, before setting translatesAutoresizingMaskIntoConstraints to NO.

(This is the second time that implicit property change has bitten me. I'm not sure if it's worth the convenience.)

(P.S. Apologies if this is already reported or even documented. I searched but couldn't find anything.)

Breaking Objective-C language conventions

I love Masonry to bits. It makes a ton of difference for me and enjoy using it on a daily basis. In that light I'd like to offer some constructive feedback.

I have an issue with the implementation: The MASConstraintMaker design and syntax violates basic Objective-C conventions. Obj-C properties are used in ways they were not intended to be used. I think it's wrong to fight the language because although immediate readability may increase, it decreases implementation transparancy; the implicit conventions and expectation management between an API developer and the API user vanishes and it generally clutters the code if developers create their own conventions instead of following the ones given by the language. Moreover, you're not only fighting the language, you're also fighting the IDE.

Of course, this is what I'm talking about:

[someView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.equalTo(otherView).with.offset(someOffset);
}
  • The object 'make' is a verb. Object names should be nouns as their classes to indicate their role
  • 'left' is a property representing a constraint. It is vaguely named to increase readability but doesn't tell me what it is.
  • equalTo() can't really be considered a property although it's defined as such. It relates two objects (left and otherView) which is not the job of a property.
  • 'with' does nothing other than increase readability of the 'sentence' and it's a property on the 'equalTo' object. By now I've lost track of what kind of objects I'm actually working on.
  • etc...

Instead I suggest a syntax more like this:

[someView mas_makeConstraints:^(MASConstraintMaker *maker) {
    [maker setLeftEqualTo:otherView withOffset:someOffset];
}

Of course this would require a lot of new methods to cover all cases, but I think its more in line with language conventions and any Objective-C programmer with minimal experience will read this just as easily as the current syntax. An added benefit is that this syntax autocompletes much nicer in Xcode because you don't have to interrupt the auto completion with dots all the time.

I'd just like to start a discussion regarding this issue. I hope we can come up with a great solution that is more in line with the Obj-C language conventions while maintaining Masonry's simplicity and elegance.

updateConstraints installs two width constraints instead of updating it

When setting a constraint equalTo a NSNumber, and afterwards setting it to equalTo(self) in an updateConstraints block, the constraint is not recognised as needed to be updated, and instead two constraints are added and an autolayout error (cannot satisfy constraints) is thrown, which shows two simultaneously installed width constraints.

Example:

[self.containerView mas_updateConstraints:^(MASConstraintMaker *make) {
        if (something) {
            make.width.equalTo(@760);
        } else {
            make.width.equalTo(self);
        }
}];

A workaround i had to use was to take the width of self manually and wrap it in a NSNumber like this:

[self.containerView mas_updateConstraints:^(MASConstraintMaker *make) {
        if (something) {
            make.width.equalTo(@760);
        } else {
            make.width.equalTo(@(self.bounds.size.width));
        }
}];

Support for UILayoutSupports (topLayoutGuide & bottomLayoutGuide)

Support for building constraints with topLayoutGuide and bottomLayoutGuide would be great. From what I understand, using the length property of the guide to build the constraint would require us to also monitor for status bar frame changes, and reconfigure our constraints.

This looks like it would be difficult to support without a big refactor, but if you have ideas for how you'd like this implemented, I'd be happy to work on it.

No issues

I just wanted to say how insanely useful this has been to me in developing my app. Thank you so much!

(Sorry for creating this issue just for that - but I needed you to read it, and couldn't find elsewhere to contact you...)

how to get view frame

when i use masonry such as this,how can i get the truly frame of imageview

imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
        imageView.contentMode = UIViewContentModeScaleAspectFit;
        [backView addSubview:imageView];
        [imageView makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(backView.mas_top).with.offset(5);
            make.left.equalTo(backView.mas_left).with.offset(5);
            make.width.equalTo(@300);
            make.height.equalTo(@120);
        }];

Strange problem with "multipliedBy"

In self.view appeared black strip on the right.
If you delete line in code:

make.width.equalTo(self.mas_width).multipliedBy(multiplier);

problem disappears.

How can this be the reason?

- (void)setItems:(NSArray *)items
{
    _items = items;

    UIView *previousContainerItem;
    for (BarButtonItem *item in _items)
    {
        UIView *containerItem = [[UIView alloc] init];
        [self addSubview:containerItem];
        [containerItem addSubview:item];

        [containerItem mas_makeConstraints:^(MASConstraintMaker *make) {
            MASViewAttribute *left = (previousContainerItem) ? previousContainerItem.mas_right : self.mas_left;
            make.left.equalTo(left);
            make.height.equalTo(self);
            make.top.equalTo(self);
            float multiplier = 1.0 / _items.count;
            make.width.equalTo(self.mas_width).multipliedBy(multiplier); // <===
        }];

        [item mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerY.equalTo(containerItem);
            make.centerX.equalTo(containerItem);
            make.height.equalTo(@30);
            make.width.equalTo(@30);
        }];
        previousContainerItem = containerItem;
    }
}

picture alt

Screen - http://rghost.ru/50893121/image.png

Animating a view inside a cell : First init

First of all, I don't know if this is really an issue of Masonry or an Auto Layout thing.

I'd been doing some tests animating things with Masonry and after some tweaking it usually works like a charm and is pretty fast. I want to share one of these tests with you which is perfect to show the issue I had and the workaround used.

https://github.com/lluisgerard/Masonry-Animated-Cell

As you can see here. I have a view that starts always at width 0 and grows to the pixel equivalent percentage (from 0 to 300 px).

The basic code for this animation is where self.animateConstraint is animated:

        float width = self.frame.size.width / grade;
        self.animateConstraint.equalTo(@(width));
        [UIView animateWithDuration:1.0f
                              delay:0.0f
             usingSpringWithDamping:0.4f
              initialSpringVelocity:0.9f
                            options:UIViewAnimationOptionCurveEaseInOut
                         animations:^{
                             [self layoutIfNeeded];
                         } completion:^(BOOL finished) {

                         }];

What happens is that when you start the app for the first time (aka load the tableview) the growing view doesn't animate at all. It just appears on the cell with the end state of the animation.

I don't know the best way to approach this, maybe there is something that I'm missing like a trigger when the view is completely loaded and constraints are set (delegates?). I even found other issues that I cannot replicate now, like the bar started to grow while the whole view was being set by autolayout (I think I was using updateConstraints then).

Ok, the solution (or workaround) I found was to do this only the first init:

        double delayInSeconds = 0.0;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            growBlock(); // this block is the above animation code
        });

As you can see, delay is set to 0 seconds but the dispatch_after is enough to activate the first animation. You can download my example project, comment the dispatch, you will see that nothing is animated on the first load then.

You can see the whole code here https://github.com/lluisgerard/Masonry-Animated-Cell/blob/master/AnimateLayouts/LLGAnimatedView.m

I'm sure I'm missing something here to know when the autolayout finished doing it's job (maybe tracking self.frame width and height?). Anyway, I hope that at least somebody can enjoy my example :)

How do I add constraint with flipped relationship ?

How do I add constraint with flipped relationship ?

I have following constraint

[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:scrollView_
  attribute:NSLayoutAttributeLeft
  relatedBy:NSLayoutRelationEqual
  toItem:self.contentView
  attribute:NSLayoutAttributeLeft
  multiplier:1
  constant:JSMessageCellPadding]];

my understanding is that following DSL

[self.contentView mas_makeConstraints:^(MASConstraintMaker *make)
{
  make.left.equalTo(scrollView_.mas_left).with.offset(JSMessageCellPadding);
}];

will be equal to

[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.contentView
  attribute:NSLayoutAttributeLeft
  relatedBy:NSLayoutRelationEqual
  toItem:scrollView_
  attribute:NSLayoutAttributeLeft
  multiplier:1
  constant:JSMessageCellPadding]];

How can I do it ?

Thanks!

Ignoring titleEdgeInsets on UIButton

If I add titleEdgeInsets to UIButton whole width of a button stays the same as it would without inset and titleLabelText just doesn't display properly

Animating constraints?

It'd be nice if the documentation gave an example about how to animate constraints. I'd submit a pull if I knew how to form such documentation.

Problem with UIView in UIScrollView

Hi there

First of all, thanks for Masonry, it looks really awesome! Unfortunately though, I have the following problem: I created a UIScrollView inside the UIView of my UIViewController and added some constraints to keep the scroll view the size of the view:

self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
_scrollView.backgroundColor = [UIColor redColor];
[self.view addSubview:_scrollView];

[_scrollView makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(self.view);
}];

This seems to work, but then I added a UIView inside the scroll view and tried to make it stick to the top:

UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.backgroundColor = [UIColor blueColor];
[_scrollView addSubview:view];

[view makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(@0);
    make.left.equalTo(@0);
    make.right.equalTo(@0);
    make.height.equalTo(@100);
}]; 

However, this second view never shows up! Any idea on what I'm doing wrong?

Masonry built with Swift Support

Currently when trying to set constraints in Swift using the objc Masonry files, an error is generated: Cannot convert the expression's type '$T6' to type '() -> ((AnyObject!) -> MASContraint!)!'

MasonryTestLoader generated build phase uses a full path to the script

Since Pods are out of .gitignore now, Pods.xcodeproj is now included in the repo. However, Podfile specifies a build phase generation which involves a full path to the script:

export | egrep '( BUILT_PRODUCTS_DIR)|(CURRENT_ARCH)|(OBJECT_FILE_DIR_normal)|(SRCROOT)|(OBJROOT)' > /Users/jonas/Projects/Masonry/script/env.sh

So you can't run tests unless you run pod to regenerate it for yourself.

I'm not quite sure how to fix this properly, so leaving it here for now :)

iOS7: Calling -makeConstraints: order seems to matter

iOS7 Bug?

Maybe it is my misunderstanding about how AutoLayout or Masonry work, but it seems to me like the order of calling -makeContraints: in iOS7 is somehow order dependant.

Here is a very simple example:

Expected Result

A very simple view, with a yellow view on top and a blue view on bottom:
Expected Result (Gist)

screenshot 2013 11 25 10 29 00

[blueView makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(yellowView.bottom).offset(padding);
    make.bottom.equalTo(superview.bottom).offset(-padding);
    make.left.equalTo(superview.left).offset(padding);
    make.right.equalTo(superview.right).offset(-padding);
  }];

[yellowView makeConstraints:^(MASConstraintMaker *make) {
    make.top.greaterThanOrEqualTo(superview.top).offset(padding);
    make.left.equalTo(superview.left).offset(padding);
    make.right.equalTo(superview.right).offset(-padding);
    make.height.equalTo(@100);
}];

Possible Bug

All I do is switch the order -makeContraints: is called, calling yellowView first :
Possible Bug Result (Gist)

screenshot 2013 11 25 10 05 13

[yellowView makeConstraints:^(MASConstraintMaker *make) {
    make.top.greaterThanOrEqualTo(superview.top).offset(padding);
    make.left.equalTo(superview.left).offset(padding);
    make.right.equalTo(superview.right).offset(-padding);
    make.height.equalTo(@100);
}]

[blueView makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(yellowView.bottom).offset(padding);
    make.bottom.equalTo(superview.bottom).offset(-padding);
    make.left.equalTo(superview.left).offset(padding);
    make.right.equalTo(superview.right).offset(-padding);
}];

On iOS6 this seems to work fine.
So is this a bug or am I missing something?

Can't form weak reference to a NSTextView

As mentioned in Apples Transitioning to ARC Release Notes you can't create a weak reference to instances of class NSTextView. Meaning the app will crash if you are trying to call mas_makeConstraints: on a NSTextView.

Since i love using Masonry, I would love to see this being implemented so that I can use it for my Mac OS X projects as well.

Do you see this feature being implemented or will you go on not supporting this?

Thanks!

Code that worked with 0.3.0 now throws runtime exceptions

My use case is pretty simple: call mas_makeConstraints: on some views. I do this in several places and everything worked perfectly with 0.3.0. As soon as I updated to 0.4.0, I started seeing these exceptions:

-[UILabel mas_makeConstraints:]: unrecognized selector sent to instance 0x14989a80                                                                                      
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UILabel mas_makeConstraints:]: unrecognized selector sent to instance 0x14989a80'

No code has changed. I am importing <Masonry/Masonry.h> and the project builds just fine. Were there breaking changes that weren't mentioned in the README?

implicit superview offset not working correctly

Hi Jonas,

I'm seeing a strange issue which I think I should raise.

I've been quite happily using the shortcut in my project for mapping against a superview's offset,

e.g. inside a UIView subclass, when adding a subview, for configuring its constraints instead of writing

make.top.equalTo(self).with.offset(20)

I'd just write

make.top.offset(20)

which adds the same constraint. This has been working great except for a case i've came across - where the view is a UITableViewCell. I've uploaded an example project here which outlines exactly where it works for one case, and not for the other.

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        UILabel *label = [UILabel new];
        label.text = @"Label";

        [self addSubview:label];

        [label mas_makeConstraints:^(MASConstraintMaker *make){
//            /* Broken */
//            make.top.offset(20);
//            make.right.offset(-20);

            /* Works */
            make.top.equalTo(self).with.offset(20);
            make.right.equalTo(self).with.offset(-20);
        }];
    }
    return self;
}

I'm unsure whether it's a fault in Masonry or UIKit, but I figured you're better at debugging this than me so I'd ask you first!

Memory leak

I am applying the constrains over the subview that is tableview of viewcontroller HelpDetailVC and i found that dealloc method is not called if we keep constrain.

__weak UIView *superview = self.view;
[self.tableview mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(superview);
}];

So if now i comment the make.edges part it start calling dealloc method.
__weak UIView *superview = self.view;
[self.tableview mas_makeConstraints:^(MASConstraintMaker *make) {
//make.edges.equalTo(superview);
}];

So can you please verify this it is an issue?

The documentation and examples for updateConstraints contradict each other

The documentation shows the following example for the updateConstraints methods. The updateConstraints method is called at the top of the method.

- (void)updateConstraints {
    [super updateConstraints];

    [self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self);
        make.width.equalTo(@(self.buttonSize.width)).priorityLow();
        make.height.equalTo(@(self.buttonSize.height)).priorityLow();
        make.width.lessThanOrEqualTo(self);
        make.height.lessThanOrEqualTo(self);
    }];
}

The updateConstraints method in MASExampleUpdateView.m calls the updateConstraints method at the bottom of the method.

// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {

    [self.growingButton updateConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self);
        make.width.equalTo(@(self.buttonSize.width)).priorityLow();
        make.height.equalTo(@(self.buttonSize.height)).priorityLow();
        make.width.lessThanOrEqualTo(self);
        make.height.lessThanOrEqualTo(self);
    }];

    //according to apple super should be called at end of method
    [super updateConstraints];
}

I believe the updateConstraints method in MASExampleUpdateView.m is correct, but the documentation and MASExampleUpdateView.m should use the same method to update constraints.

Issue with animating constraints

I'm having a strange issue with animating a certain constraint.

I created a very simple project to demonstrate the issue:
https://github.com/mobitar/MasonryTest

In ListViewController.m, there's a method called addSampleView. If you uncomment this method, and hit the "Toggle" button, the list controller slides out with an animation, as intended.

If however you leave this line in, and the sample view is added, for some reason the list controller slides out and in when you hit the toggle button, but without animation.

Any idea why?

uicontrols in a uiview can not receive touch event

I setup a UIView to wrap UIControls, like:
aView
-- UISlider
-- UIImageView
-- UIImageView

in the aView's method: - (id)initWithFrame:(CGRect)frame, I setup all subviews and controls, make masonry layout.
Then add the aView on self.view. But the slider's thumb can not be moved.
Please help me to figure out.

How to update the constraint when keyboard shows up.

I have been working on login module. I have created the login view like this.

[loginview mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(@(kLoginContainerYPosition));
make.centerX.equalTo(self.view.mas_centerX);
make.width.equalTo(@(kLoginContainerViewWidth));
make.height.equalTo(@(kLoginContainerViewHeight));
}];

When keyboard pops up I tried to update login view y position like below. But could not able update view position.

pragma mark -

pragma Keyboard Notification method

  • (void)keyboardWillBeShown {

    [loginCompanyViewController.view mas_updateConstraints:^(MASConstraintMaker *make) {

    CGFloat kContentPaddingForIPad = kLoginContainerYPosition - 100;
    make.centerY.equalTo(@(kContentPaddingForIPad));

    }];
    }

Can you please help me out.

Using mixture of existing views for constraint

I don't quite understand this from the readme:

An array of a mixture of any of the previous types

make.height.equalTo(@[view1.mas_height, view2.mas_height]);

Does make.height.equalTo(@[view1.mas_height, view2.mas_height]); make the height of what ever view we're adding constraints to the average of the view1 and view2 heights?

Question: necessary to remove existing constraints?

When calling a block like so:

[self.descriptionLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  make.top.equalTo(self.titleLabel.mas_bottom).with.offset(8.f);
  make.left.equalTo(self.contentView.mas_left);
  make.right.equalTo(self.contentView.mas_right);
}];

Is it necessary to remove the existing constraints first?

iOS 7.1 :: View that adds subviews while the view is not entirely on the screen

I'm having some issues with the app that I'm developing right now. Not sure where is the problem but I can replicate it whenever I want. Not sure if this is a Masonry issue though. So far, I tested the drawer menu without autolayout on iOS7.1 and I'm not having the same problems there, that's why I think that at least autolayout is involved here.

I'm using this "drawer" menu:
https://github.com/monospacecollective/MSDynamicsDrawerViewController

This is how it looks usually (can't share it without hiding some parts):
ios-simulator-screen-shot-11-mar-2014-19 49 06

If you go and change from one view to another and you go "slow", letting the whole view load (sometimes it goes to the API on the background to load content), everything works fine.

The issue comes if you open the drawer menu before its content is entirely loaded, then the view seems that is cut in half and so the menu (sometimes disappears).
ios-simulator-screen-shot-11-mar-2014-19 47 59

I can't share my code but maybe someone has an idea about why this is happening, or you are having also some issues after upgrading to iOS 7.1. If nothing comes up I will try to replicate this on a separated project only for this purpose.

Thank you very much in advance! Sorry if you think that this is not to be posted here, I'm having some degree of desperation right now 👹

Animate a UIView to another location

If I have a view with constraints:

[self.summaryView makeConstraints:^(MASConstraintMaker *make) {

    self.animatableConstraint = make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(80, 10, 10, 10));
}];

And later I want to animate to another point like:

// TODO: Set new position here.

[UIView animateWithDuration:2.5
                 animations:^{
                     [self.summaryView layoutIfNeeded];
                 }
                 completion:^(BOOL finished) {
                 }];

How can I do this?

Centering not work as expected

I have a UIView (hegiht=80), and as subviews a label and a edit.

I have tried to center both in the Y axis. However, the heigth of both subviews change to be the same of the superview.

I expected to both controls to be centered.

   [self.view addSubview:scroll];
    self.view.backgroundColor = [UIColor darkGrayColor];

    UIEdgeInsets paddingInsets = UIEdgeInsetsMake(self.navigationController.navigationBar.frame.size.height + 30, self.padding, self.padding, self.padding);

    [scroll keepInsets:paddingInsets];

    UIView *back = [[UIView alloc] init];
    back.backgroundColor = [UIColor lightGrayColor];

    [scroll addSubview:back];

    [back mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(@0);
        make.left.equalTo(@0);
        make.width.equalTo(scroll.mas_width);
        make.height.equalTo(@80);
    }];

    [label mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(back);
        make.left.equalTo(@0);

        make.width.equalTo(@200);
        make.centerY.equalTo(back.mas_centerY);
    }];

    [edit mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(back);
        make.right.equalTo(back.mas_right);

        make.width.equalTo(label.mas_width);
        make.centerY.equalTo(back.mas_centerY);
    }];

Issues with multiple views inside a UIScrollView

Hi there,

First of all, I want to say that this library is really awesome and is one of the reasons that I'm using autolayout right now. Been using it for a new project and everything is working like a charm, really appreciate it.

But, I'm trying to use it on a ScrollView and I'm having a lot of trouble. I tried to solve this in multiple ways and different approaches and I'm not having any success at all. The more I try the less I feel I understand how Autolayout and Masonry works. Maybe that's the problem, not Masonry but the way Autolayout works in ScrollViews.

The main issue I have is that the scrollView only scrolls horizontally and not vertically, it's stuck.

Found this issue #12 and tried to always set the width of my subviews. I even copied exactly what he did there, but then I created like 50 views in the same scrollView and it doesn't scroll.

Been reading this https://developer.apple.com/library/ios/technotes/tn2154/_index.html but in this case, they use only one big view, and not multiple ones.

At this point, after so many hours trying, I think that I'd better see an example and start again than try to fix my own one so I created a new ViewController and added this code to the init:

    self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
    _scrollView.backgroundColor = [UIColor grayColor];
    [self.view addSubview:_scrollView];

    [_scrollView makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.view);
    }];

    NSNumber* height = [NSNumber numberWithInt:350];

    UIView *view1 = [[UIView alloc] initWithFrame:CGRectZero];
    view1.backgroundColor = [UIColor blueColor];
    [_scrollView addSubview:view1];


    UIView *view2 = [[UIView alloc] initWithFrame:CGRectZero];
    view2.backgroundColor = [UIColor greenColor];
    [_scrollView addSubview:view2];


    UIView *view3 = [[UIView alloc] initWithFrame:CGRectZero];
    view3.backgroundColor = [UIColor redColor];
    [_scrollView addSubview:view3];

    [view1 makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(@0);
        make.left.equalTo(@0);
        make.width.equalTo(_scrollView.width);
        make.height.equalTo(height);
    }];

    [view2 makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(view1.mas_bottom);
        make.left.equalTo(@0);
        make.width.equalTo(_scrollView.width);
        make.height.equalTo(height);
    }];

    [view3 makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(view2.mas_bottom);
        make.left.equalTo(@0);
        make.width.equalTo(_scrollView.width);
        make.height.equalTo(height);
    }];

This code adds the first view and the next two correctly, one using the bottom as a top reference, but the UISCrollView is not scrolling at all. I also tried to add everything inside a UIView. I even tried to get the last object Y position, but I get a very high number that doesn't make sense.

Should I have to set the contentSize of the scrollView ? but that's why I wanted the Y position for, I'm feeling that this is the wrong direction.

At this point I hope that somebody can help me, I will really appreciate it, and even better, seeing some example. I think I'm missing something here.

Thanks in advance :)

Update readme for v0.5

The most recent stuff is not covered yet, but it's too awesome to stay in the shadows :) I may do a PR if you are busy right now.

Priority doesn't work

Hello, i've code like this

self.nameLabel.text = "super long long long long text";
[self.nameLabel makeConstraints:^(MASConstraintMaker *make) {
    make.left.equalTo(self.contentView.left).offset(10);
    make.top.equalTo(self.contentView.top).offset(10);
    make.right.equalTo(self.contentView.right).offset(-10).priorityLow();
}];

As you can see it has the constraint make the the label all the way to right - 10px.
But when you add priority after offset it doesn't work, the label just overflow and ignore the right and offset.

In other words it's behaving the same like you don't specify any right constraint like code below

self.nameLabel.text = "super long long long long text";
[self.nameLabel makeConstraints:^(MASConstraintMaker *make) {
    make.left.equalTo(self.contentView.left).offset(10);
    make.top.equalTo(self.contentView.top).offset(10);
}];

Thank you

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.