I'm trying the simplest thing but it's not working correctly. I have a MKMapView called mapView in a controller and in the viewDidLoad, I'm doing:
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect myRect=CGRectMake(10.0f, 10.0f, 100.0f, 100.0f);
self.mapView.frame = myRect;
}
but the MKMapView is still taking up the whole controller screen. What am I doing wrong?
thx
If you have autolayout enabled, it will not pay attention to the frame. If you want to adjust the mapView size and/or position, I would turn off autolayout or add constraints in code.
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(10)-[mapView(100)]" options:0 metrics:nil views:#{#"mapView" : self.mapView}]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-(10)-[mapView(100)]" options:0 metrics:nil views:#{#"mapView" : self.mapView}]];
Related
I am adding a subview to a UICollectionViewCell. I am programmatically adding constraints to make it fill the cell, however the width does not fill the cell.
When I view it in the view debugger, it says the position is ambiguous. How can this be since I am specifying all 4 sides are pinned to the superview?
This is what the views look like in the debugger. The inner, white view should fit the parents width (blue border):
Inspecting the constraints on the parent view shows this with the "position ambiguous" warning:
The code I am using is as follows:
[self.contentView addSubview:calloutView];
calloutView.translatesAutoresizingMaskIntoConstraints = NO;
self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[calloutView]-0-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(calloutView) ]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[calloutView]-0-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(calloutView) ]];
The problem seems to be related to the use of contentView, you must use the cell itself to achieve what you want, this is the code and works, check the picture below
#import "CollectionViewCell.h"
#interface CollectionViewCell()
#property UIView * testView;
#end
#implementation CollectionViewCell
#synthesize testView;
-(void)awakeFromNib
{
[super awakeFromNib];
testView = [[UIView alloc]initWithFrame:CGRectZero];
testView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:testView];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-2-[testView]-2-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(testView) ]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-2-[testView]-2-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(testView) ]];
self.testView.layer.borderWidth = 2;
self.testView.layer.borderColor = [UIColor blueColor].CGColor;
}
#end
I hope this helps you, best regards
I need to add a background image view for my views for a project I've done using storyboards + autolayout. I want to add this image programmatically using code. so basically it should be from top layoutguide to bottom layoutguide, without going under them. I've tried few ways which failed horribly.
one way I first adjust the VC'c view before adding like this
id topGuide = self.topLayoutGuide;
UIView *superView = self.view;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings (superView, topGuide);
[self.view addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:[topGuide]-20-[superView]"
options:0
metrics:nil
views:viewsDictionary]
];
[self.view layoutSubviews];
but for some reason my imageview still goes under statusbar.
this is how I add the bg imageview
self.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Default"]];
self.backgroundView.contentMode = UIViewContentModeTop;
[self.view insertSubview:self.backgroundView atIndex:0];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[backgroundImageView]|" options:0 metrics:nil views:#{#"backgroundImageView":self.backgroundView}]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[backgroundImageView]|" options:0 metrics:nil views:#{#"backgroundImageView":self.backgroundView}]];
Adding the constraint related to the topLayoutGuide to self.view is useless. The view controller layout its root view (self.view) independently from AutoLayout, and will override the constraints effects (don't quote me on this, this is an observation more than a real understanding of the layout system).
Instead, add the first constraint (#"V:[topGuide]-20-[superView]") to self.backgroundView:
self.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Default"]];
self.backgroundView.contentMode = UIViewContentModeTop;
[self.view insertSubview:self.backgroundView atIndex:0];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[topGuide]-(20)-[backgroundImageView]|" options:0 metrics:nil views:#{#"backgroundImageView":self.backgroundView, #"topGuide": self.topLayoutGuide}]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[backgroundImageView]|" options:0 metrics:nil views:#{#"backgroundImageView":self.backgroundView}]];
[self.view layoutSubviews];
I want to build such interface:
With auto layout disabled, I successfully created those 6 buttons and well adjusted them through code in function of screen's height. However, when disabling auto layout, all other controllers become "messy" so I tried to create/adjust those buttons with auto layout enabled. And there is NO WAY to achieve such interface with auto layout enabled. My question is, is there any trick, solution to adjust those 6 buttons with auto layout enabled? Or perhaps there is a library? I'm really stacked.
Thank you for your help.
I see you found an answer, but I'll post mine anyway, because it uses a different approach. Trying to get the constraints correct in IB (in iOS 6) when there are so many dependencies among the 6 buttons is difficult (because of the constraints the system adds for you in IB), so I did it in code. I did it in such a way that the buttons take the whole screen in any size screen or any orientation without having to check the screen size:
#interface ViewController ()
#property (strong,nonatomic) NSMutableDictionary *viewsDict;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.viewsDict = [NSMutableDictionary dictionary];
for (int i=1; i<7; i++) {
UIButton *b = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[b setTitle:[NSString stringWithFormat:#"Button%d",i] forState:UIControlStateNormal];
[b setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.viewsDict setObject:b forKey:[NSString stringWithFormat:#"b%d",i]];
[self.view addSubview:b];
}
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|[b1][b2(==b1)]|" options:0 metrics:nil views:self.viewsDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|[b3][b4(==b3)]|" options:0 metrics:nil views:self.viewsDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|[b5][b6(==b5)]|" options:0 metrics:nil views:self.viewsDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[b1][b3(==b1)][b5(==b1)]|" options:0 metrics:nil views:self.viewsDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[b2][b4(==b2)][b6(==b2)]|" options:0 metrics:nil views:self.viewsDict]];
}
With autolayout, you will definitely want to wrap those six views in another UIView to prevent layout interactions between the buttons and other views. If that UIView has a fixed height and width, it might be as simple as that.
I'm trying to generate a view in code. Here's the hierachy of my view object
UIScrollView
UIView
UIButton
The ScrollView should be the same size as the window.
The button should be as big as possible.
I'm using iOS auto layout, so the constraint strings for all of my objects look like this
H:|[object]|
V:|[object]|
I've also set translatesAutoresizingMaskIntoConstraints to NO for each object.
The problem is that the button only gets the default button-size. Its parent view object (UIView) only gets the size its subviews need.
red: UIScrollView / yellow: UIView
How can I force those views to be as big as the scrollView?
When I use a UIView instead of th UIScrollView everything works great...
Here's some code:
- (void) viewDidLoad {
[super viewDidLoad];
// SCROLL VIEW
UIScrollView* scrollView = [UIScrollView new];
scrollView.backgroundColor=[UIColor redColor];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
//CONTAINER VIEW
UIView *containerView = [UIView new];
containerView.translatesAutoresizingMaskIntoConstraints = NO;
containerView.backgroundColor = [UIColor yellowColor];
[scrollView addSubview:containerView];
// CONSTRAINTS SCROLL VIEW - CONTAINER VIEW
[scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[containerView]|"
options:0 metrics:nil
views:#{#"containerView":containerView}]];
[scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[containerView]|"
options:0 metrics:nil
views:#{#"containerView":containerView}]];
// BUTTON
UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.translatesAutoresizingMaskIntoConstraints = NO;
[button setTitle:#"I'm way to small" forState:UIControlStateNormal];
[containerView addSubview:button];
// CONSTRAINTS CONTAINER VIEW - BUTTON
[containerView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[button]|"
options:0 metrics:nil
views:#{#"button":button}]];
[containerView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[button]|"
options:0 metrics:nil
views:#{#"button":button}]];
self.view = scrollView;
}
UPDATE:
I really don't know, why this is happening. If you set up the view in IB, connect the outlets and instanciate the view in code, the scrollview behaves like a normal view (which bounces vertically). Its contentSize is not calculated correctly. More here. But how to do it correctly?
A couple of observations:
Constraints for subviews in scroll views don't work like constraints in other views. They're used to set the contentSize of the scroll view. (See TN2154.) That way, you throw a bunch of stuff on a scroll view, set the constraints for the stuff inside it, and the contentSize is calculated for you. It's very cool feature, but it's antithetical to what you're trying to do here.
Worse, buttons will, unless you set an explicit constraint for their width and height of a button, will resize according to their content.
The net effect of these two observations is that your existing constraints say "(a) set my container to be the size of my button; (b) let my button resize itself dynamically to the size of the text; and (c) set my scrollview's contentSize according to the size of my container (which is the size of the button)."
I'm unclear as to what the business problem is. But here are some constraints that achieve what I think your technical question was:
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *view = self.view;
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.backgroundColor = [UIColor redColor]; // just so I can see it
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:scrollView];
UIView *containerView = [[UIView alloc] init];
containerView.backgroundColor = [UIColor yellowColor]; // just so I can see it
containerView.translatesAutoresizingMaskIntoConstraints = NO;
[scrollView addSubview:containerView];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.translatesAutoresizingMaskIntoConstraints = NO;
[button setTitle:#"I'm the right size" forState:UIControlStateNormal];
[containerView addSubview:button];
NSDictionary *views = NSDictionaryOfVariableBindings(scrollView, button, view, containerView);
// set the scrollview to be the size of the root view
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[scrollView]|"
options:0
metrics:nil
views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[scrollView]|"
options:0
metrics:nil
views:views]];
// set the container to the size of the main view, and simultaneously
// set the scrollview's contentSize to match the size of the container
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[containerView(==view)]|"
options:0
metrics:nil
views:views]];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[containerView(==view)]|"
options:0
metrics:nil
views:views]];
// set the button size to be the size of the container view
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[button(==containerView)]"
options:0
metrics:nil
views:views]];
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[button(==containerView)]"
options:0
metrics:nil
views:views]];
}
Frankly, I don't understand the business intent of your UI, as this feels like a contortion of auto layout to achieve a very simply UI. I don't know why you have a scroll view if you have "screen sized" content in it (unless you were paging through buttons). I don't know why you'd have a content view with a single item in it. I don't understand why you're using a full-screen button (I'd just put a tap gesture on the root view at that point and call it a day).
I'll assume you have good reasons for all of this, but it might make sense to back up, ask what is your desired user experience is, and then approach the problem fresh to see if there's a more efficient way to achieve the desired effect.
When I rotate an image it moves right. It shouldn't. It seems like the center is set to the wrong point. See screenshot: In both states - rotated and not - the center of the "+" shouldn't change.
I am positioning a UIImageView using auto layout like this:
- (void)viewDidLoad {
...
addIconImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"AddCardIcon.png"]];
[addIconImageView setContentMode:UIViewContentModeCenter];
[addIconImageView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:addIconImageView];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[addIconImageView]-(10)-|"
options:nil
metrics:nil
views:NSDictionaryOfVariableBindings(addIconImageView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat: #"V:|-[addIconImageView]-|"
options:NSLayoutFormatAlignAllCenterY
metrics:nil
views:NSDictionaryOfVariableBindings(addIconImageView)]];
...
}
And here's what I do to rotate the image
[UIView animateWithDuration:0.2
animations:^{
addIconImageView.transform = CGAffineTransformRotate(addIconImageView.transform, M_PI/4);
} completion:^(BOOL finished) {
}
];
How come the move right on rotation and how can I avoid it?
My first guess is that your image asset isn't perfectly square.
Resize AddCardIcon.png so that it has identical width and height and doesn't have any transparent padding on any side.
Otherwise, manually determine the center of the + and set addIconImageView.layer.anchorPoint