I am new to AutoLayout and struggling with it a bit. I have a UIImageView which is part of an UIView. When the app is running on a 3.5 inch device, I want the UIImageView to resize according to the change of the screen size.
I am not sure how to achieve this. From what I have seen so far, you can only set a fixed width and height of the views, is it possible to make them dynamically resize ? In other words, how can the UIImageView resize accordingly to the super view's height ?
Choose your ImageView in Interface Biulder.
Press pin button.
Set the constraints.
Example
This code will size the UIImageView according to its superview's width and height.
UIImageView *myImageView = [[UIImageView alloc] initWithImage:theImage];
[self.view addSubview:myImageView];
[myImageView setTranslatesAutoresizingMaskIntoConstraints:NO];
NSArray *imageViewConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[myImageView]|" options:0 metrics:nil views:#{#"myImageView": myImageView}];
[self.view addConstraints:imageViewConstraints];
imageViewConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[myImageView]|" options:0 metrics:nil views:#{#"myImageView": myImageView}];
[self.view addConstraints:imageViewConstraints];
Me too faced same problem.It may help someone,
If you are designing in InterfaceBuilder or Storyboard just pin all the edges to superview (i.e)Leading Space,Trailing Space,Top Space and Bottom Spoace to UIView.
That's it
select the imageView. Now go and add a pin with bottom spacing from super view.
Related
This question already has answers here:
UITableView within UIScrollView using autolayout
(5 answers)
Closed 7 years ago.
I have this views hierarchy in a xib file:
UIView
UIScrollView
UIView
UIView
UITableView
UIButton
Let's call contentView the UIView that is the direct child of the UIScrollView. I've set its top, bottom, leading and trailing constraints to pin the scroll view. Then, since I'm populating the table view at runtime and I don't know its height beforehand, I set the scroll view's contentSize in code:
[self.scrollView setContentSize:CGSizeMake(self.contentView.frame.size.width, self.tableView.frame.size.height)];
But I don't make this work... what could I be missing?
AppsDev, check this video out it helped me a lot doing UIScrollView via storyboard
https://www.youtube.com/watch?v=UnQsFlMGDsI
Also never set the scrollView's contentSize as it has to be determined by scrollView on its own and that's why we have AutoLayout.
I believe we should have one tag for uiscrollview-autolayout
Don't set the content size manually. Instead,
Constrain your contentView's four edges to the edges of the scrollView.
Constrain your contentView's width to be equal to the scrollView's width. (This will prevent the content from being wider than the scrollView.)
Constrain the contentView's top and sides to the corresponding edges of the child view.
Constrain the contentView's sides and bottom to the sides and bottom of the tableView.
Now here's where it gets tricky: constrain the bottom of the child view to be equal to the top of the table view. However, unless you explicitly set a height constraint on the child view, you'll get a layout error that the height of the scrollView's contents will be ambiguous. To get around this, you can set the child's placeholder height to make Interface Builder happy, but then you'll also have to set its height somewhere at runtime.
Now you should be set. The scrollView can now calculate the full height and width of its contents by examining the constraint hierarchy, and you don't have to set its content height manually.
I finally managed to make this work by following the #Sana answer and also this post to be able to scroll the table view content.
Thanks u all for replying.
Just for example:
UIView *containerView = [[UIView alloc] init];
UIScrollView *scrollView = [[UIScrollView alloc] init];
[containerView addSubview:scrollView];
containerView.translatesAutoresizingMaskIntoConstraints = NO;
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(containerView, scrollView);
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[scrollView]|"
options:kNilOptions
metrics:nil
views:viewsDictionary]];
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[scrollView]|"
options:kNilOptions
metrics:nil
views:viewsDictionary]];
Use this code My code help you.
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[self.scrollView setContentSize:CGSizeMake(self.contentView.frame.size.width, self.tableView.frame.size.height)];
}
I have a CollectionViewCell where i want to add a imageView. This imageView should be set to exact size, so it is proportional without cutting, something out of the image by resizing. How can i do this? Do i need to do it programmatically or can it be done in autolayout?
The example of this is the images on this picture below. where they have the exaact height as the images?
You can add constraint at runtime programmatically.
By calculating image's height and width and than add constraint for it's height and width.
Constraint for it's X and Y should be set before this
[imageView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[myView(==width)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(imageView)]];
[imageView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[myView(==height)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(imageView)]];
I am trying to create a UILabel inside a UIImageView but it doesn't fit correctly into the UIImageView bounds. I can set it fine when running in portrait, but when I turn the device to landscape it seems to lose the orientation and it appears outside the UIImageView.
Is there some way to clip the UILabel into the UIImageView?
You can achieve it by adding appropriate constraints to both your label and imageview. Here's a sample code which fixes your label from left, right and bottom of imageview :
// align yourLabel from the left and right
[yourImageview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[yourLabel]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(yourLabel)]];
// align yourLabel from the bottom
[yourImageview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[yourLabel]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(yourLabel)]];
I have a very simple view. It is just a view with a UISCrollView and an UIImageView below. Inside the UIScrollView I have a very large UIImageView. Now I need to set the UIScrollview it's contentsize using autolayout.
But I can't figure it out how I can do that ? Here is how my storyboard looks like.
I've tried to put the UIImageView inside a UIView and make that UIView the only child of de UIScrollView but that is also not working. Turning off autloayout is not an option because all my other views are using autolayout
Any help on this ?
You should set many constraints to make it working in the right way. If I understand corretly, you want something similar:
View
----------------------------------
| ScrollView |
|--------------------------------|
|| ||
|| ||
|| ||
|--------------------------------|
|ImageView |
|--------------------------------|
|| ||
|--------------------------------|
----------------------------------
In this case you should set the constraints to be the top of the Scrollview exactly the View's top.
The ImageView's top is the ScrollView's bottom, the ImageView's bottom is the View's bottom.
And inside the ScrollView to things similarly.
If you will have each needed constraint it will work.
The contentSize of a UIScrollView can be implicitly set through the NSLayoutConstraints within the UIScrollView.
The way this would be done (If you wanted the image view to fit snugly in the UIScrollView) is:
UIImageView *imageView = ...
UIScrollView *scrollView = ...
NSDictionary *viewsDictionary = #{#"imageView" : imageView};
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[imageView]|"
options:kNilOptions
metrics:nil
views:viewsDictionary]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[imageView]|"
options:kNilOptions
metrics:nil
views:viewsDictionary]];
The contentSize would be equal to the size of the UIImageView.
Obviously to place the UIScrollView that would just be the same as placing any other view in it's subview.
I use bordering view by creating such constraints in scrollView for example:
H:|[borderView(400)]|
V:|[borderView(600)]|
May be you can use your's UIImageView as bordering view.
I made a few UIScrollView's in different views, they all worked without Autolayout.
I turned Autolayout on, because it was better for my app.
But since then, there's a big problem with my UIScrollView's:
No one is scrolling, they don't work.
Here's my code for a UIScrollView:
.m:
-(viewDidLoad) {
scrollerHome.contentSize = CGSizeMake(320, 1000);
scrollerHome.scrollEnabled = YES;
[self.view addSubview:scrollerHome];
scrollerHome.showsHorizontalScrollIndicator = false;
scrollerHome.showsVerticalScrollIndicator = false;
[super viewDidLoad];
}
.h:
#interface ViewController : UIViewController{
IBOutlet UIScrollView *scrollerHome;
}
Do I have to add some code because I turned on Autolayout?
You should call [super viewDidLoad] before doing anything !
In autolayout, you do not set the contentSize manually. Autolayout works slightly differently with scrollviews, whereby the contentSize of the scroll view is dictated by the constraints of the scrollview's subviews.
If you're trying to force the contentSize to some large size (for example, you're implementing some infinite scroller), you can just add a subview of the appropriate size, e.g.:
UIView *containerView = [[UIView alloc] init];
containerView.translatesAutoresizingMaskIntoConstraints = NO;
[self.scrollView addSubview:containerView];
NSDictionary *views = NSDictionaryOfVariableBindings(containerView);
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[containerView]|" options:0 metrics:nil views:views]];
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[containerView(1000)]|" options:0 metrics:nil views:views]];
But if you were trying to set the contentSize in anticipation of adding subviews, you generally don't have to do anything, such as the above snippet. Just add your subviews, provide their constraints, and autolayout will adjust the scroll view's contentSize automatically.
As mentioned above, with autolayout, you can just add the subviews to your scrollview (with their constraints), and the contentSize will be calculated automatically for you.
There is a trick here, though. You sometimes you want to size a subview based upon the dimensions of the screen. But the usual technique of using the | symbols won't work. For example, for an imageview1 inside a scrollview, the usual #"H:|[imageview1]|" won't set the imageview1 to be the width of the screen, but rather it will define the scroll view's contentSize to match the width of imageview1, but it says nothing about what the width of that image view should be!
So, it's useful to capture a reference to the scroll view's superview. That way, you can use something like #"H:|[imageview1(==superview)]|", which not only says "make the scroll view's contentSize equal to the width of imageview1", but also "define the width of imageview1 to be equal to the width of the scroll view's superview."
Thus, for example, to add three images in a paging scroll view, you might do something like:
UIImageView *imageview1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"_DSC0004.jpg"]];
imageview1.contentMode = UIViewContentModeScaleAspectFit;
imageview1.translatesAutoresizingMaskIntoConstraints = NO;
[self.scrollView addSubview:imageview1];
UIImageView *imageview2 = ... // configured similar to imageview1
UIImageView *imageview3 = ... // configured similar to imageview1
UIView *superview = self.scrollView.superview;
NSDictionary *views = NSDictionaryOfVariableBindings(imageview1, imageview2, imageview3, superview);
// not only define the image view's relation with their immediate scroll view,
// but also explicitly set the size in relation to the superview, too!
[superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[imageview1(==superview)][imageview2(==superview)][imageview3(==superview)]|" options:0 metrics:nil views:views]];
[superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[imageview1(==superview)]|" options:0 metrics:nil views:views]];
[superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[imageview2(==superview)]|" options:0 metrics:nil views:views]];
[superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[imageview3(==superview)]|" options:0 metrics:nil views:views]];
self.scrollView.pagingEnabled = YES;
From the Apple iOS 6.0 release notes:
"In general, Auto Layout considers the top, left, bottom, and right edges of a view to be the visible edges. That is, if you pin a view to the left edge of its superview, you’re really pinning it to the minimum x-value of the superview’s bounds. Changing the bounds origin of the superview does not change the position of the view.
The UIScrollView class scrolls its content by changing the origin of its bounds. To make this work with Auto Layout, the top, left, bottom, and right edges within a scroll view now mean the edges of its content view."
You can find the full notes here and find the answer to your question in the section that I quoted from. They give code examples on how to use UIScrollView in a mixed Auto Layout environment.