iSee
iSee

Reputation: 604

Adding Auto Layout constraints programmatically to a subview of constant width and height

I have a UIView of size 20x40 which has been added as a subview of a ViewController. The smaller UIView is draggable across the screen and depending on the position it has been dragged to, the UIView will reset the 'X' coordinate to stick to the screen edge.

However, I want to use/learn 'Auto Layout' to add constraints to this subView to maintain the same width and height in both landscape and portrait mode.

Code so far:

self.anotherView = [[UIView alloc] initWithFrame: CGRectMake (0.0,(self.view.frame.size.height/2)-45.0f-self.navigationController.navigationBar.frame.size.height,20.0,45.0f)];
    UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(dragging:)];
    [self.anotherView addGestureRecognizer:panRecognizer];
    [self.anotherView setBackgroundColor: [UIColor blueColor]];
    self.anotherView.translatesAutoresizingMaskIntoConstraints = NO;

    [self.view addSubview: self.anotherView];
    [self.view bringSubviewToFront:self.anotherView];

    NSDictionary *views = @{@"subview" : self.anotherView, @"superview" : self.view};


    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[subview(==20)]|" options:NSLayoutFormatAlignAllBaseline metrics:nil views:views]];


    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[subview(==40)]" options:NSLayoutFormatAlignAllBaseline metrics:nil views:views]];


    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.anotherView attribute:NSLayoutAttributeBaseline relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:self.view.bounds.size.height];
        [self.view addConstraint:constraint];

However, the above code gives me the following error:

Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x8b4ef80 H:|-(0)-[UIView:0x8b4eab0]   (Names: '|':UIView:0x8b4cc80 )>",
    "<NSLayoutConstraint:0x8b4f020 H:[UIView:0x8b4eab0(20)]>",
    "<NSLayoutConstraint:0x8b4f0f0 H:[UIView:0x8b4eab0]-(0)-|   (Names: '|':UIView:0x8b4cc80 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x8aa1d30 h=--& v=--& H:[UIView:0x8b4cc80(320)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x8b4f0f0 H:[UIView:0x8b4eab0]-(0)-|   (Names: '|':UIView:0x8b4cc80 )>

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

What exactly am I doing wrong here? Also, I am using Storyboard and only this view is added as the subView to the ViewController. Please find below the screenshot of how the UI looks at present.

The blue view is freely draggable across the screen!

Upvotes: 0

Views: 3905

Answers (1)

jrturton
jrturton

Reputation: 119242

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[subview(==20)]|" options:NSLayoutFormatAlignAllBaseline metrics:nil views:views]];

This is saying that you want the subview to be 20 points wide and also pinned to the left and right edges of the superview, which is a table cell's content view and therefore 320 points wide.

If you only want to constrain the width of the view, don't include the superview indicators (|)in the VFL string, as you've done with the vertical constraint, or use an autolayout helper category with some nice constrain-to-size methods.

To have a variable position, you need a separate constraint pinning the left edge of the view to its superview, and the constant of this constraint will be updated as the user drags.

Upvotes: 2

Related Questions