How to adjust views using auto layout? - iphone

I am using AutoLayout in my sample app. I have three views, topView, middleView, bottomView.Following are the constraint I need,
topView:
Always start at x origin 10.
Left and right margin 10.
Height should vary based on screen bounds(or superview).
middleView:
There should be 10 px vertical margin between top and middle view.
Left and right margin 10.
Height should vary based on screen bounds(or superview).
bottomView:
There should be 10 px vertical margin between middle and bottom view.
Left and right margin 10.
Height should be constant, say 30.
I want that based on device screen size, bottom view y origin should change so that middle and top view size will adjust.
Problem here is there is no way to find out, what should be the y origin of bottom view and interface is providing permanent constraint like:
Top space to superview for middle view.
Top space to superview for bottom view.
This is because there is no way to find out the height of views.
Only difficulty is determining height for top and middle view.

You don't seem to care what the height of the top and middle view is, so I'm just going to make a decision for you: they will have the same height. Add the following contraints to the common superview of which these three views (_topView,_middleView and _bottomView) are subviews:
NSString *vfl = #"V:|-(10)-[topView]-(10)-[middleView]-(10)-[bottomView(==30)]-(10)-|";
NSDictionary *dict = #{#"topView":_topView,#"middleView":_middleView,#"bottomView":_bottomView};
NSArray *a = [NSLayoutConstraints
constraintsWithVisualFormat: vfl
options: 0
metrics: nil
views: dict];
Make sure you align them horizontally as well:
NSArray *b = [NSLayoutConstraints
constraintsWithVisualFormat: #"H:|-(10)-[topView]-(10)-|"
options: 0
metrics: nil
views: dict];
NSArray *c = [NSLayoutConstraints
constraintsWithVisualFormat: #"H:|-(10)-[middleView]-(10)-|"
options: 0
metrics: nil
views: dict];
NSArray *d = [NSLayoutConstraints
constraintsWithVisualFormat: #"H:|-(10)-[bottomView]-(10)-|"
options: 0
metrics: nil
views: dict];
Edit
The middle view will be a label, as you say. Labels have an intrinsic content size. If you don't set the height of this view, the autolayout system will know what to do instinctively. (Neat, right?) By pinning the top of _topView to the top of the superview and its bottom to the top of the label, its height should be automatically calculated. I have changed the code to reflect this.
Edit 2
In order to add constraints in code, find a common ancestor (superview) of these three views and write [superview addConstraints:a],[superview addConstraints:b], etc... Make sure that autolayout in IB is turned off and that you set the translateResizingMasksToConstraints to NO.

Related

Swift - StackView in ScrollView doesn't scroll

I am trying to make a scrollable stack view inside a scrollview but it doesn't work.
I have built a structure like this:
If you can't see the image, this is the structure:
UIScrollView constrained to superview in all 4 directions
UIStackView (constrained to scrollview in all 4 directions + equal width)
Image Collection View (not constrained)
UIStackView (not constrained)
Stack of Labels (not constrained)
It doesn't scroll, can anyone see what I am missing?
You should set ContentView in your ScrollView with constraints like:
ScrollView's Constraints:
Leading to superView
Trailing to superView
Top to superView
Bottom to superView
These constraint's constants are 0
ContentView's Constraints:
Leading to superView
Trailing to superView
Top to superView
Bottom to superView
Equal height to ViewController's View (which is in the top of the view hierarchy)
Equal width to ViewController's View 
Note: You should set ContentView's height constraint's priority to 700 etc. (lower than default high value)
Attention:
Your stackViews and collectionView must have height for scrollable.
I hope it is works.
Enjoy.

How is scrollView page size calculated?

I have a scrollView embedded inside a UIView with a top constraint to the navigation bar.
My question is, how is the page size calculated of a UIScrollView (where scrollView.pagingEnabled = true)? I want each page to be the size of the aforementioned UIView, but it turns out that it's slightly bigger.
I set the contentSize as so in the view controller:
self.scrollView.contentSize = CGSizeMake(UIScreen.mainScreen().bounds.width, (UIScreen.mainScreen().bounds.height - 64) * 4)
I figured each page size would be UIScreen.mainScreen().bounds.height - 64 (because of the navigation bar and clock) but, like I said, the page turns out to be slightly bigger.
Try to set the height of the scrollView same as UIView that hosts it self.scrollView.superview.
Edit:
The 'slightly bigger' is probably the 64 points offset. You need to set self.automaticallyAdjustsScrollViewInsets = false inside yout viewController that hosts the scrollView to fix it

Vertically center subview using Auto-Layout

I'm trying to figure out how to center vertically a view using Auto-Layout.
I'm new to this technology so it makes me some problems...
This is my controller in Interface Builder:
The gray part is the superview and it contains a custom view (the yellow one) and a label (the red one); the yellow view is fixed at the bottom of the superview and it has fixe height and width. The red view has fixed width and height, too.
My goal is to center vertically my red view in the visible part of the gray view, whose visible height is superview.height - yellowView.height.
How can I do that?
Thank you so much!
The easiest way to do it, would be to make the gray view a subview of the main view too, and then you can just give the label a centerY constraint in IB or in code. If you can't so that for some reason, you can change the constant value of a centerY constraint in code, giving it a value of 1/2 the height of the yellow view. Give the label a centerY constraint in IB and make an IBOutlet to it (I call it centerCon in my example). The fixed height of my yellow view was 200.
- (void)viewDidLoad {
[super viewDidLoad];
self.centerCon.constant = 100;
}
One of the simplest solutions here will be like this:
redView.center = CGPointMake(superview.width/2, (superview.height - yellowView.height)/2);

Is is possible to have a XIB then set the size and have everything scale to fit in a UIView?

I'm new to iOS development and I'm not sure if what I want to do is possible.
Basically I'm retrieving some products via a webservice and I want to display each one across the screen, 4 squares per row. Each one of these squares (with image and name of product) is a UIView which has a .h,.m and xib file. I create each view like this:
CategoryItemView *catItem = [[[NSBundle mainBundle] loadNibNamed:#"CategoryItemView" owner:self options:nil] objectAtIndex:0];
[categoryItems addObject:catItem];
and I position it like:
while (colCount < cols && items < [categoryItems count]) {
CGRect viewRect = CGRectMake( x * colCount + pad , (row * (x-pad)) + pad*row + pad, x - pad, x - pad );
CategoryItemView* myView = [categoryItems objectAtIndex:items];
myView.frame = viewRect;
[self.view addSubview:myView];
colCount++;
items++;
}
I want to use a xib so I can layout all the elements. However I cannot find a way to lay out the xib so that when positioning the UIView like this all the elements are scaled to fit and keep their relative positions in the UIView. Is this possible?
Update: You can view a 2 class example here thats not working http://home.glasscubes.com/share/s/d57sb19
thanks
autoresizingMask is the property you are looking for on those views.
From the docs:
autoresizingMask
An integer bit mask that determines how the receiver resizes itself
when its superview’s bounds change.
#property(nonatomic) UIViewAutoresizing autoresizingMask
Discussion
When a view’s bounds change, that view automatically resizes its
subviews according to each subview’s autoresizing mask. You specify
the value of this mask by combining the constants described in
UIViewAutoresizing using the C bitwise OR operator. Combining these
constants lets you specify which dimensions of the view should grow or
shrink relative to the superview. The default value of this property
is UIViewAutoresizingNone, which indicates that the view should not be
resized at all.
When more than one option along the same axis is set, the default
behavior is to distribute the size difference proportionally among the
flexible portions. The larger the flexible portion, relative to the
other flexible portions, the more it is likely to grow. For example,
suppose this property includes the UIViewAutoresizingFlexibleWidth and
UIViewAutoresizingFlexibleRightMargin constants but does not include
the UIViewAutoresizingFlexibleLeftMargin constant, thus indicating
that the width of the view’s left margin is fixed but that the view’s
width and right margin may change. Thus, the view appears anchored to
the left side of its superview while both the view width and the gap
to the right of the view increase.
If the autoresizing behaviors do not offer the precise layout that you
need for your views, you can use a custom container view and override
its layoutSubviews method to position your subviews more precisely.

Center multiple UIViews in a row its superview?

How would I go about placing arrays of identical sized uiviews at their superviews center?
For example: I have an array of (x number) of 50x50 sized views.. that I place right next to each other in a line. How can I center that line of 50x50 views, to the center of their superview?
Is there an easier way than what I'm thinking I'd have to do?
My approach would to take the count of views inside the array, and multiply it by 50. This would give me the width of the images together.
Then subtract that width from the width of the superview. Then place the subviews based off that math.
Is there an easier approach to go about doing this?
What you are suggesting is one way of doing it. Another way that has the advantage of keeping the views centered when you rotate the device is to do this:
Create a basic UIView to use as a container
Set the container bounds property to (0, 0, 50 * x, 50)
Layout the 50x50 subviews inside the container so they fill it
Add the container view as a subview of the main view
Set the center property of the container to the center of the superview
Set the autoresizingMask property of the container view to UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin
Use the center property of the UIView
Apple documentation says that: The center property can be used to adjust the position of the view without changing its size.
So you would do something like this:
Create a UIView that will contain all the 50x50 Views with a width of [array count] x 50;
Then add all the 50x50 views to this Container View.
Add this view to the desired view and then set its center point to its superview center point.
Something like this:
[my50x50ContainerView setFrame:CGRectMake(0.0, 0.0, [50x050ViewsArray count] x 50, 50.0)];
[self.view addSubview:my50x50ContainerView];
my50x50ContainerView.center = self.view.center;