So guys,
I have a profile view that contains several informations. Some of them don't have to be set e.g. Biografie. So depending if its set, I would like to hide the Biografie View (checkout screenshot) and reposition the UserData View and the ActivityData View AND change the Size of their superview to fill the space made by the Biografie View.
Here is my actual structure of my TableViewHeader:
The other point that i have to care about is that, the UILabel have to be mutliline and fit its content.
So my questions:
How do I reposition the UserData & ActivityData View to fill the
space made by the hidden BiografieView?
How do I make the Biografie
View height fit the UILabels text?
Please keep in mind that I'm using Autolayout. So I have to use constraints to modify the positions right?
To be honest.. Basically it should be like Instagram, when adding a Biografie. I hope I made it clear what I want..
Edit 1
I have tried your suggestion Damien, but nothing is changing:
NSLog(#"Height %f, Width %f", self.labelBiografie.frame.size.height, self.labelBiografie.frame.size.width);
if ([self.profileUser objectForKey:kGSUserBiografieKey]) {
self.labelBiografie.text = [self.profileUser objectForKey:kGSUserBiografieKey];
[self.labelBiografie sizeToFit];
}else{
[self.labelBiografie setHidden:YES];
[self.countContainer setConstraintConstant:-self.labelBiografie.frame.size.height forAttribute:NSLayoutAttributeCenterY];
[self.tableHeaderViewChildVIew setConstraintConstant:-self.labelBiografie.frame.size.height forAttribute:NSLayoutAttributeHeight];
self.tableView.tableHeaderView = self.tableHeaderViewChildVIew;
}
EDIT 2:
Using this Project (UIView-UpdateAutoLayoutConstraints
) I'm getting following error on the methods:
Line 56: [self hideView:hidden byAttribute:NSLayoutAttributeHeight];
Line 85: [self setConstraintConstant:0 forAttribute:attribute];
Line 23:
[self.superview addConstraint: [NSLayoutConstraint constraintWithItem:self attribute:attribute relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:constant]];
ERROR:
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:0x8c1b8e0 V:|-(0)-[UIButton:0x8c6fb40] (Names: '|':UIView:0x8c6f630 )>",
"<NSLayoutConstraint:0x8c19dc0 V:[UIButton:0x8c6fb40(100)]>",
"<NSLayoutConstraint:0x8c1d740 V:[UIButton:0x8c6fb40]-(NSSpace(8))-[UILabel:0x8c70900]>",
"<NSLayoutConstraint:0x8c20df0 V:[UILabel:0x8c70900]-(NSSpace(8))-[UIView:0x8c16a00]>",
"<NSLayoutConstraint:0x8c20fa0 V:[UIView:0x8c16a00(40)]>",
"<NSLayoutConstraint:0x8c23790 V:[UIView:0x8c16a00]-(0)-| (Names: '|':UIView:0x8c6f630 )>",
"<NSAutoresizingMaskLayoutConstraint:0x8c78e60 h=--& v=--& V:[UIView:0x8c6f630(217)]>",
"<NSLayoutConstraint:0x8c5d000 V:[UILabel:0x8c70900(0)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x8c20df0 V:[UILabel:0x8c70900]-(NSSpace(8))-[UIView:0x8c16a00]>
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.
This error shows up on the Demo-Project out of the box, on my on Project it also get returned when i hide the view..
I built a category to answer to this problem I also already encountered :
Hide autolayout UIView : How to get existing NSLayoutConstraint to update this one
EDIT:
If you use autolayout, do not use view.frame any more and don't forget to set all you autolayout view like this:
myView.translatesAutoresizingMaskIntoConstraints = NO;
Using this category https://github.com/damienromito/UIView-UpdateAutoLayoutConstraints
if(!user.biografie && user.biografie.lenght == 0)
{
[biografieLabel setConstraintConstant:0 forAttribute:NSLayoutAttributeHeight];
}else
{
biografieLabel.text = user.biografie;
}
For your question two , the first solution would be to had a height constraint between the uilabel and its container's height(BiografieView) .
NSLayoutConstraint *constraint = [NSLayoutConstraint
constraintWithItem:biografieView /// change here
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:biografieLabel /// change here
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0];
[view addConstraint:constraint];
Don't forget to set uilabel.numberOfLine = 0 ,
the height of this one will be automatically updated
BUT, BUT, BUT...* (better solution for your case)
If you have only one uilabel in your biografie view, remove this container. The uilabel is also a uiview, and you will not have this problem any more.
Related
I dynamically add an UIImageView (as thumbnail) and its NSLayoutConstraints in my UIView which in the cell of a table. I have two problems about this.
After an image view added, if the user inserts text to this table still an image is being shown. I mean, instead of text table prints one more image. However, if I stop and re-run the application, this time text is shown as it should be. Still, if I write a text picture is coming. Why and what should I do?
I set image and its constraints like this:
-(void)setThumbnail:(UIImageView)imageView {
[self.messageView addSubview:imageView];
NSLayoutConstraint *leadingOfThumbnail = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.messageView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:8.f];
NSLayoutConstraint *trailingOfThumbnail = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.messageView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:-8.f];
NSLayoutConstraint *topOfThumbnail = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.messageView attribute:NSLayoutAttributeTop multiplier:1.0 constant:8.f];
NSLayoutConstraint *bottomOfThumbnail = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.messageView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-8.f];
[self.messageView addConstraint:leadingOfThumbnail];
[self.messageView addConstraint:trailingOfThumbnail];
[self.messageView addConstraint:topOfThumbnail];
[self.messageView addConstraint:bottomOfThumbnail];
[self.messageView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.messageView removeConstraints:[self.messageTextLabel constraints]];
}
And while loading, I get a constraint error. It says:
2016-10-07 09:35:32.532 application[3733:2922397] 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) (
"NSAutoresizingMaskLayoutConstraint:0x1281474d0 h=--& v=--& UIImageView:0x126d7e020.midY == + 100",
"NSAutoresizingMaskLayoutConstraint:0x128147520 h=--& v=--& V:[UIImageView:0x126d7e020(200)]",
"NSLayoutConstraint:0x126d6c880 V:|-(8)-[UIImageView:0x126d7e020] (Names: '|':UIView:0x1281480d0 )" )
Will attempt to recover by breaking constraint NSLayoutConstraint:0x126d6c880 V:|-(8)-[UIImageView:0x126d7e020] (Names: '|':UIView:0x1281480d0 )
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
I checked, leading and top constrains set by me causes this error. Already they are not working correct. My image is 200 * 200, thus it does not need height and width constraint. I only want 8 pt leading, trailing, top, bottom from message view. What is the problem?
Thank you.
Explanation edit for first question: Table puts UIImageView randomly, multiple cells - not as it should be.
You may want to implement the prepareForReuse method and do some cleanup there, set the imageView to nil and remove it from the subview here.
This method gets called when your cell is dequeued and about to be reused in the tableview.
For the first issue, you can simply set cell image to nil after dequeing from tableview.
For the second issue, after ImageView initialization add this line, to avoid that autoresizingmask is translated to constraints:
imageView.translatesAutoresizingMaskIntoConstraints = false
I believe that your problem is because of the dequeCell functionality. UITbableView recycle cells. So if you place an image in one cell, there is a chance that it will appear in another cell.
To solve this, you need to place some conditions in your cellForRowAtIndexPath.
These conditions would check if you want text in your current cell or image or both.
If it only needs text, you need to remove the image from that cell.
If you still face problems, please share your cellForRowAtIndexPath code.
I have a toolbar with a UIImageView I added programmatically. When I tried adding NSConstraint to the UIImageView to center it in the toolbar view. When I ran it on the simulator, it crashed.
Here's my code:
UIImageView *image = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0,
nav.frame.size.width, nav.frame.size.height)];
image.image = [UIImage imageNamed:[imageTop objectAtIndex:2]];
[imageToolbar addSubview:image];
[imageToolbar addConstraint:[NSLayoutConstraint constraintWithItem:image
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:imageToolbar
attribute:NSLayoutAttributeCenterX
multiplier:1.0 constant:0]];
[imageToolbar addConstraint:[NSLayoutConstraint constraintWithItem:image
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:imageToolbar
attribute:NSLayoutAttributeCenterY
multiplier:1.0 constant:0]];
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:0x7fcfc2536f50 UIImageView:0x7fcfc2536d50.centerX == UIToolbar:0x7fcfc2525610.centerX>",
"<NSLayoutConstraint:0x7fcfc252dad0 UIView:0x7fcfc252c750.trailingMargin == UIToolbar:0x7fcfc2525610.trailing - 16>",
"<NSLayoutConstraint:0x7fcfc252db20 UIToolbar:0x7fcfc2525610.leading == UIView:0x7fcfc252c750.leadingMargin - 16>",
"<NSAutoresizingMaskLayoutConstraint:0x7fcfc254fea0 h=--& v=--& UIImageView:0x7fcfc2536d50.midX == + 160>",
"<NSLayoutConstraint:0x7fcfc2551110 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7fcfc252c750(375)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7fcfc2536f50 UIImageView:0x7fcfc2536d50.centerX == UIToolbar:0x7fcfc2525610.centerX>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in may also be helpful.
Thanks.
You have created an UIImageView but you have not added that image view to the interface. You cannot add constraints for a view that is not in the interface. If you do, you will, uh, crash.
Also, you have neglected to set translatesAutoresizingMaskIntoConstraints to NO. If you neglect to do that, then when you add your own constraints, you will have a constraint conflict and you will, uh, crash.
Really, it's just a matter of reading the error message in the console. As my old folk dancing teacher used to say, "The music tells you what to do!"
I have a UITableViewSubclass (style: UITableViewCellStyleValue1) that has a custom label that is essentially a replacement for the normal textLabel label. It should be left aligned with the normal textLabel but has a width to end 8 points to the left of the normal detailTextLabel. I get the desired effect, but when the cells are used, an exception is thrown about being unable to satisfy the constraints simultaneously.
What I don't understand is why it complains, there is no apparent conflict. Calling [self layoutIfNeeded] after setting up the constraints silences the exception. Alternatively, lowering the priority of the constraint that configures the trailing property (for example, UILayoutPriorityDefaultHigh instead of the default UILayoutPriorityRequired) also silences the exception, obviously because I'm informing the Auto Layout engine that it's okay to break/ignore that constraint.
I'm assuming that the standard UITableView implementation maybe oddly lays out the textLabel and textLabel in a fashion that makes it initially impossible to describe the view described. For example, if the textLabel was actually placed on the right side of the cell and detailTextLabel was placed on the left side, then the layout I've described would be impossible.
When does Auto Layout take effect, in the context of this scenario. Is it jumping the gun and attempting to layout things before it's supposed to?
No Storyboards or XIBs are being used. Purely code based.
#import "EBTStoreTableViewCell.h"
#interface EBTStoreTableViewCell ()
#property (nonatomic, readonly, weak) UILabel *storeNameLabel;
#end
#implementation EBTStoreTableViewCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier];
if (self) {
self.textLabel.text = #" ";
self.detailTextLabel.text = #" ";
UILabel *storeNameLabel = [[UILabel alloc] init];
storeNameLabel.translatesAutoresizingMaskIntoConstraints = NO;
[storeNameLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
[self.contentView addSubview:storeNameLabel];
_storeNameLabel = storeNameLabel;
[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:storeNameLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.textLabel attribute:NSLayoutAttributeLeading multiplier:1.0f constant:0.0f]];
[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:storeNameLabel attribute:NSLayoutAttributeBaseline relatedBy:NSLayoutRelationEqual toItem:self.textLabel attribute:NSLayoutAttributeBaseline multiplier:1.0f constant:0.0f]];
[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:storeNameLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.detailTextLabel attribute:NSLayoutAttributeLeading multiplier:1.0f constant:-8.0f]];
// [self layoutIfNeeded]; // doing this makes the issue go away
}
return self;
}
// Setters ommited
#end
This the exception message I get:
2014-04-23 11:50:42.092 Application[32507:60b] 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:0xde03910 UILabel:0xde036b0.leading == UILabel:0xde00590.leading>",
"<NSLayoutConstraint:0xde03a30 UILabel:0xde036b0.trailing == UITableViewLabel:0xde00c10.leading - 8>",
"<NSAutoresizingMaskLayoutConstraint:0xde01920 h=--& v=--& UILabel:0xde00590.midX ==>",
"<NSAutoresizingMaskLayoutConstraint:0xde1de50 h=--& v=--& H:[UILabel:0xde00590(0)]>",
"<NSAutoresizingMaskLayoutConstraint:0x17f50a10 h=--& v=--& UITableViewLabel:0xde00c10.midX ==>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xde03a30 UILabel:0xde036b0.trailing == UITableViewLabel:0xde00c10.leading - 8>
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.
You shouldn't mix and match using the textLabel and detailTextLabel. These can not be constrained as their size are managed internally and might produce unexpected results.
You should create your own labels, and then places constraints on them.
From the docs for UITableViewCell:
When creating cells, you can customize them yourself or use one of several predefined styles. The predefined cell styles are the simplest option. With the predefined styles, the cell provides label and image subviews whose positions and styling are fixed. All you have to do is provide the text and image content to go into those fixed views. To use a cell with a predefined style, initialize it using the initWithStyle:reuseIdentifier: method or configure the cell with that style in Xcode. To set the text and images of the cell, use the textLabel, detailTextLabel, and imageView properties.
If you want to go beyond the predefined styles, you can add subviews to the contentView property of the cell. When adding subviews, you are responsible for positioning those views and setting their content yourself.
I'm building a complicated project where, among other things, I need to set a UIPageViewController as a childview of a main view. I'm using autolayout, and using constraints to order the various elements on the main view.
The problem is, that when I try to run the app, it crashes due to conflicting NSAutoresizingMaskLayoutConstraints.
2013-10-28 16:22:18.419 Red Event App[1658:60b] 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:0x145c1990 V:|-(20)-[UINavigationBar:0x145bf6b0] (Names: '|':UIView:0x145bf620 )>",
"<NSLayoutConstraint:0x145bf510 V:[UINavigationBar:0x145bf6b0]-(0)-[UIView:0x145bef70]>",
"<NSLayoutConstraint:0x145d0550 UIView:0x145a8c10.top == UIView:0x145bf620.top>",
"<NSAutoresizingMaskLayoutConstraint:0x145b3a40 h=-&- v=-&- UIView:0x145a8c10.midY == UIView:0x145bef70.midY + 56.5>",
"<NSAutoresizingMaskLayoutConstraint:0x145b3a70 h=-&- v=-&- UIView:0x145a8c10.height == UIView:0x145bef70.height + 113>"
)
The usual cure for this is setting TranslatesAutoresizingMaskIntoConstraints to no.
However, when I do this the child views of the UIPageViewController start to ignore the bounds of the PageViewController, and end up (as far as I can see) with an origin of (0,0).
I've tried to fix the position by setting the frames by hand both when setting up the datasource (_itemViewControllers):
- (void)setupLeafs{
_itemViewControllers = [[NSMutableArray alloc]init];
for(NSString *pagename in _datasource){
RWNode *page = [_xml getPage:pagename];
UIViewController *viewController = [RWNavigationController getViewControllerFromDictionary:[page getDictionaryFromNode]];
viewController.view.frame = CGRectMake(self.view.frame.origin.x,self.view.frame.origin.y,self.view.frame.size.width, self.view.frame.size.height);
[_itemViewControllers addObject:viewController];
}
}
and when getting the page
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
UIViewController *nextViewController = [self getPreviousLeaf:viewController];
nextViewController.view.frame = CGRectMake(self.view.frame.origin.x,self.view.frame.origin.y,self.view.frame.size.width, self.view.frame.size.height);
return nextViewController;
}
but neither have any effect.
I need the constraints for what I'm doing, so sticking to Masks is not an option. I think what I'm looking for is a way to put constraints on the UIPageViewController children after they've been added (by whatever process calls viewControllerBeforeViewController). But I'd really like to hear about any way that this problem can be solved.
Edit:
I have found a hack to solve the problem. I'm not quite sure if what I'm listing here is the entire solution, but it is what I notice right now, after more than a month of tinkering with the code.
First, in the view controller that sets up the pageviewcontroller, I have the following two lines, after I've initialized the pageviewcontroller
UIView *pageView = self.pageViewController.view;
pageView.frame = self.view.frame;
Not that I have set [self.view setTranslatesAutoresizingMaskIntoConstraints:NO]; in this view controller.
Secondly, on the child controllers I check whether the view is being used inside or outside of a pageviewcontroller. Only if the view is not being used in a pageviewcontroller is [self.view setTranslatesAutoresizingMaskIntoConstraints:NO]; set on the child view.
Now, this works (for me) at the moment. But I would really like a solution that is less hacky.
When using AutoLayout, you should never directly set the frame of a view. Constraints are used to do this for you. Normally if you want to set your own constraints in a view, you override the updateConstraints method of your UIViews. Make sure the content views for the page controller allow for their edges to be resized since they will be sized to fit the page view's frame. Your constraints and view setup will need to account for this, or you you will get unsatisfiable constraint errors.
While I don't know exactly what you are trying to achieve visually, here are two pieces of advice that might help you:
Firstly, remember to remove all existing constraints from a UIView before adding new ones in code. Don't mix constraints from Interface Builder with constraints in code, it will drive you insane. Example:
- (void)viewDidLoad
{
[super viewDidLoad];
// remove all constraints
[self.view removeConstraints:self.view.constraints];
// add new constraints
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[webView]|"
options:0
metrics:nil
views:#{#"webView": self.webView}]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[webView]|"
options:0
metrics:nil
views:#{#"webView": self.webView}]];
}
Secondly, you can have NSLayoutConstraint outlets, just like any other outlets from a XIB or a Storyboard. That way, you can adjust certain properties of a constraint at runtime:
// in your header:
#property (nonatomic, weak) IBOutlet NSLayoutConstraint *myConstraint;
// somewhere in your code where you need to adjust the constraint:
self.myConstraint.constant = 100;
I hope this helps a little bit :)
I can't give you the answer, but perhaps I can give you some debug advice.. copy the log information into a text editor and replace the memory address information for the views with meaningful names. (use the debugger to find which properties the memory addresses map to if you can't figure it out). Then you will find it a bit easier to understand the log information and trace the conflict. Here is an example (although i'm just guessing your view hierarchy)
"<NSLayoutConstraint:0x145c1990 V:|-(20)-[UINavigationBar:NAVBAR] (Names: '|':UIView:ROOTVIEW )>",
"<NSLayoutConstraint:0x145bf510 V:[UINavigationBar:NAVBAR]-(0)-[UIView:PAGECONTAINER]>",
"<NSLayoutConstraint:0x145d0550 UIView:PAGEVIEW.top == UIView:ROOTVIEW.top>",
"<NSAutoresizingMaskLayoutConstraint:0x145b3a40 h=-&- v=-&- UIView:PAGEVIEW.midY == UIView:PAGECONTAINER.midY + 56.5>",
"<NSAutoresizingMaskLayoutConstraint:0x145b3a70 h=-&- v=-&- UIView:PAGEVIEW.height == UIView:PAGECONTAINER.height + 113>"
At a guess, the last two autoresizingmasklayoutconstraints look strange to me, they don't look clearly defined.
I just ran into a similar situation. If I set any constraints on the UIPageViewController's view, it would cause conflicts with the autoresizing mask constraints.
What works for me is to set translatesAutoresizingMaskIntoConstraints to NO for UIPageController view, then add constraints to the parent view for the pageController view's top, left, width, and height.
self.pageController.view.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:self.pageController.view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0];
NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:self.pageController.view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0];
NSLayoutConstraint *constraint3 = [NSLayoutConstraint constraintWithItem:self.pageController.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:1.0 constant:-60.0];
NSLayoutConstraint *constraint4 = [NSLayoutConstraint constraintWithItem:self.pageController.view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0];
[self.view addConstraints:#[constraint1, constraint2, constraint3, constraint4]];
My goal is to add a logo to the bottom left corner of a UINavigationBar, and to add constraints so that it stays there upon rotation.
Here's what I've tried:
UIView* navBarView = [[self navigationController] navigationBar];
UIImageView* logoImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"asdf"]];
[navBarView addSubview:logoImageView];
NSLayoutConstraint *logoConstraintLeftAlign =
[NSLayoutConstraint constraintWithItem:logoImageView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:navBarView
attribute:NSLayoutAttributeLeft
multiplier:1.0f
constant:0.0f];
NSLayoutConstraint *logoConstraintBottomAlign =
[NSLayoutConstraint constraintWithItem:logoImageView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:navBarView
attribute:NSLayoutAttributeBottom
multiplier:1.0f
constant:0.0f];
[navBarView addConstraint:logoConstraintLeftAlign];
[navBarView addConstraint:logoConstraintBottomAlign];
But that produces errors regarding some conflicting constraints:
2013-10-17 13:34:07.202 WTTest6[6551:a0b] 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:0x13196350 UIImageView:0x13198280.bottom == UINavigationBar:0x9d98970.bottom>",
"<NSAutoresizingMaskLayoutConstraint:0x1318a6c0 h=--& v=--& UIImageView:0x13198280.midY == + 12>",
"<NSAutoresizingMaskLayoutConstraint:0x1318a6f0 h=--& v=--& V:[UIImageView:0x13198280(24)]>",
"<NSAutoresizingMaskLayoutConstraint:0x131aa0e0 h=-&- v=--& V:[UINavigationBar:0x9d98970(44)]>"
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x13196350 UIImageView:0x13198280.bottom == UINavigationBar:0x9d98970.bottom>
I looked at the refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints, but was a bit overwhelmed by it, as I am just working with constraints for the first time.
I tried setting the frame of the logoImageView, which worked for the default orientation. I suppose I'd have to change the frame each time the orientation changes. But that seems contrary to the point of using AutoLayout and constraints.
So my question is, Can I use constraints to anchor the view like I want, and if so, how do I avoid the NSAutoresizingMaskLayoutConstraint "problem"?
Note that I looked at Putting a custom UIView at the bottom of a UINavigationBar but that suggested using the titleView of the UINavigationBarItem, which is centered, and thus does not help with the left alignment.
Well first off, what I found is that basically ANY time I add a constraint to something and I get conflicts, it's because I did NOT add this to the object I am adding the constraint to:
[someUIView setTranslatesAutoresizingMaskIntoConstraints:NO];
DO NOT put this on the container view, just the subViews.
Set 'autoresizingMask' on 'navigationBar' subviews for your layout.
keep setTranslatesAutoresizingMaskIntoConstraints = YES on all subviews.
It works for me.