Center multiple UIViews in a row its superview? - iphone

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;

Related

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

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.

UIView resize evenly

I have a uiview subclass that i want to expand evenly. I mean I want the origin point of the view to be in the center, and have the width and height expand the same amount. Right now the origin point is in the top left, (0,0), and it expands down to the right. How would I go about doing this?
When you change the width and height of the frame, also change the x and y position of the frame by half those amounts.
For example, if your frame is currently (40, 60, 100, 200) and you want it to be wider by 20 and higher by 30, make it (30, 45, 120, 230).
I suggest, if I understand you problem that you get the size of the superview in which the view is located. Let this view be view. Then, let your view be myView.
So all you have to do is the following :
Take half of the size of the screen for width and height values, and to position the origin of your view.
UIView view = myView.superview;
if (nil != view) {
// Make sure your view won't extend by itself with this
myView.autoresizingMask = UIViewAutoresizingNone;
// Get The size of the parent view
CGSize size = view.bounds.size;
// Set the new frame of your view
myView.frame = CGRectMake(size.width/2.0f,
size.height/2.0f,
size.width/2.0f,
size.width/2.0f);
}
And now your view is positioned correctly

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.

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.