I am doing this and I am curious whether it is the best way, or a dumb way!
I have a bunch of 40 pixel wide images, each one is like a Scrabble tile. My app wants to display some and center them on the screen. Only it don't know how many there are going to be! Could be between 3 and 10.
So I think best thing is if I count how many, multiple by 40, so I know how many pixels wide the whole thing will be, and then let's pretend it's 280 pixels - I will create a 280 px wide UIView, stick all the tiles in there, and then use Autolayout to center that UIView on the device.
That way if user rotates device, no problem!
Is this the best way? Also I am going to need to let the user drag the tiles out of that UIView and into another place on screen. Will that be possible?
Three approaches leap out at me:
I think your solution of using a container view is perfectly fine. But, you don't have to mess around with determining the size of the images. You can just define the relation between the container and the image views, and it will resize the container to conform to the intrinsic size of the image views (or if you explicitly define the size of the image views, that's fine, too). And you can then center the container (and not give it any explicit width/height constraints):
// create container
UIView *containerView = [[UIView alloc] init];
containerView.backgroundColor = [UIColor clearColor];
containerView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:containerView];
// create image views
UIImageView *imageView1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"1.png"]];
imageView1.translatesAutoresizingMaskIntoConstraints = NO;
[containerView addSubview:imageView1];
UIImageView *imageView2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"2.png"]];
imageView2.translatesAutoresizingMaskIntoConstraints = NO;
[containerView addSubview:imageView2];
NSDictionary *views = NSDictionaryOfVariableBindings(containerView, imageView1, imageView2);
// define the container in relation to the two image views
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[imageView1]-[imageView2]|" options:0 metrics:nil views:views]];
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[imageView1]-|" options:0 metrics:nil views:views]];
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[imageView2]-|" options:0 metrics:nil views:views]];
// center the container
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:containerView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:containerView.superview
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:containerView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:containerView.superview
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0]];
Another common solution with constraints is to create two extra UIView
objects (sometimes called "spacer views"), for which you'll specify a background color of [UIColor clearColor]
, and put them on the left and right of your image views, and define them to go to the margins of the superview, and define the right view to be the same width of the left view. While I'm sure you're building your constraints as you're going along, if we were going to write the visual format language (VFL) for two imageviews to be centered on the screen, it might look like:
@"H:|[leftView][imageView1]-[imageView2][rightView(==leftView)]|"
Alternatively, you could eliminate the need for the container view or the two spacer views on the left and right by creating NSLayoutAttributeCenterX
constraints using constraintWithItem
, and specifying multiplier
for the various image views so that they're spaced the way you want. While this technique eliminates the need for these two spacer views, I also think it's a little less intuitive.
But it might look like:
[imageViewArray enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) {
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:view.superview
attribute:NSLayoutAttributeCenterX
multiplier:2.0 * (idx + 1) / ([imageViewArray count] + 1)
constant:0];
[view.superview addConstraint:constraint];
}];
This admittedly employs a slightly different spacing of the image views, but in some scenarios it's fine.
Personally, I'd lean towards the first approach, but any of these work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With