Vertically center subview using Auto-Layout - iphone

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);

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

UIView positioning related questions (iOS)

I have a bunch of questions:
How do I position a UIView so that it is on the bottom of the view I am adding it to?
How can I add a subview to a view so that it is positioned in the corner of the superview with a small gap (Like if I want a 'x' cross sign for closing something)
Is their a utility class for easy UIView positioning (and rotation)?
Any references, open source tutorials etc. will be more then welcome!
(a) How do I position a UIView so that it is on the bottom of the view I am adding it to?
OK, let's say you want to position button as a subview at the bottom of view form, you calculate the origin.y of the subview button by subtracting button's height from the height of the form
CGRect buttonFrame = button.frame;
buttonFrame.origin.y = form.bounds.size.height - buttonFrame.size.height;
button.frame = buttonFrame;
[form addSubview:button];
You can change origin horizontal position as well. You want it on the bottom left of form?
buttonFrame.origin.x = 0;
Or on the right edge of form?
buttonFrame.origin.x = form.bounds.size.width - buttonFrame.size.width;
Or in the middle (horizontally) of form?
buttonFrame.origin.x = (form.bounds.size.width - buttonFrame.size.width) / 2;
or another way using CGRectGetMidX (found in CGGeometry utility methods):
buttonFrame.origin.x = CGRectGetMidX(form.bounds) - buttonFrame.size.width/2;
Autoresizing handles adjusting the frame when the parent view's size changes. But you still have to position it first.
int xOffset = 20;
int yOffset = 20;
CGRect BottomRight_NewFrame = CGRectMake((superview.frame.size.width - subview.frame.size.width-xOffset), (superview.frame.size.height - subview.frame.size.height-yOffset), subview.frame.size.width, subview.frame.size.height);
subview.frame = BottomFrame;
You can use the new Autolayout feature of iOS 6 or the old Struts & Springs in the Interface Builder to achieve this.
This tutorial explains both:
http://msmvps.com/blogs/kevinmcneish/archive/2012/12/10/tutorial-ios-6-auto-layout-versus-springs-and-struts.aspx
Or you can set the autoresizing mask programatically. It is explained pretty well here:
UIView autoresizingMask - Interface Builder to Code - Programmatically create struts and springs - Swift or Objective-C
It's easy enough to just set the frame, e.g. (untested code )
subview.frame = CGRectMake((superview.frame.origin.x - subview.frame.origin.size.width/2)-20, (superview.view.frame.origin.y - subview.frame.origin.size.height/2)-20, subview.view.frame.size.width, subview.view.frame.size.height);
if you'll be doing a lot of this then create a utility class or method.
Autolayout will help you position the views and maintain those positions if the size of the superview changes. If the superview isn't going to change, you don't really need to mess with constraints -- you can just set the position of the subview appropra
If you're adding view viewB to view viewA:
a) To position viewB so that it's bottom edge corresponds to the bottom edge of viewA:
viewB.frame.origin.y = viewA.bounds.size.height - viewB.bounds.size.height;
b) You don't say which corner, but it's just a matter of doing the math. For example, the upper right corner of viewA is at {viewA.bounds.size.x, 0} in viewA's coordinate system. If you want to put viewB there, set it's origin to:
{viewA.bounds.size.x-viewB.bounds.size.x, 0}
If you want to add a margin, you can add that to the computation:
int margin = 10;
{viewA.bounds.size.x-viewB.bounds.size.x-margin, margin}
d) Use NSLayoutConstraint to access the autolayout system's constraints programmatically. There's a nice visual format language, so that for your question (a) you could set the constraint for viewA to:
V:|-[viewB]-0-|
The V means that you're working in the vertical direction, |'s represent the edges (top and bottom, thanks to the V) of the superview (that's viewA), and the 0 means that the distance between viewB and the bottom of its superview should be 0.
You can setup constraints in iOS6 but if you want to work on older os's you need to position them manually. Math.

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;

UIScrollView contentSize Issue - With example code

Within my view I create a scrollview with a width of 320 and a height of 70.
Responding to the user touching a button, I expand the scrollview, so it is 380(h) x 320(w) in size.
The code for this is shown below:
CGRect scrollviewFrame = CGRectMake(0, 30, 320, 380);
[scrollView setFrame:scrollviewFrame];
[self layoutScrollImages:YES];
CGSize srect = CGSizeMake([scrollView bounds].size.width, (kNumImages * (kScrollObjHeight + 10)));
[scrollView setContentSize:srect];
The constants mentioned in the above snippet are defined as:
const CGFloat kScrollObjHeight = 80;
const NSUInteger kNumImages = 100;
As I debug this project, I can see that srect is 320 (w) x 8000 (h) in size; however my issue is the scrollable area (where the user can actually touch to scroll the scrollview) remains the same as when it was it's original size.
I'm obviously missing something, does anyone know what it is?
have created a sample project to illustrate the issue I am having, it is available here: http://dl.dropbox.com/u/9930498/ScrollViewTest.zip
The problem in your sample is you have a very odd structure for loading your views. As such the view you're adding to the DetailScrollView instance is the root view of the DetailScrollView.xib, not the scrollview itself, which I believe is what you were expecting.
Fastest way to fix your problem is to adjust the root view in DetailScrollView.xib to autoresize width and height.
A UIView cannot respond to touches that are outside of the bounds of its superview. In your example, it appears that you expand the scroll view, but the scroll view's parent is still only 100 units high.
You should imagine the scrollView as a window, where by the window I mean the frame of the scrollView, which is also the coordinates that the scrollView detects your touches. By setting the contentView as 320 (w) x 8000 (h) you only change the content of the scroll view, which is the complete area behind that window.
By expanding content view, the scrollView can scroll a broader area, but in order to detect touches in a bigger rect, you should change frame of the scroll view.