iPhone auto layout images arrangement issue - ios

I want to arrange 3 Images on iPhone & iPad using auto layout.
3 Images should rezise preserving aspect ratio, and width of all 3 images should be same.
Same space from left and right sides for all 3 images.
See Example figure (Figure shows landscape and portrait mode) on this link:
Portrait: http://i.imgur.com/9KVXATE.png
Landscape: http://i.imgur.com/tDjj9K6.png
It is possible programatically getting width and height of screen/view but I want to do it using auto-layouts
Programatically:
//Inside this method
//- (void) didRotateFromInterfaceOrientation:
(UIInterfaceOrientation)fromInterfaceOrientation
//Main_View is the view in which the 3 images are kept
//ImageView1, ImageView2, ImageView3 are 3 image views
ImageView1.frame = CGRectMake(Main_View.frame.origin.x + 3, Main_View.frame.origin.y + 30, ((Main_View.frame.size.width / 3)-4), ((Main_View.frame.size.width / 3) - 4) * (82.0/75.0));
ImageView2.frame = CGRectMake(ImageView1.frame.size.width + 6, Main_View.frame.origin.y + 30, ((Main_View.frame.size.width / 3)-4), ((Main_View.frame.size.width / 3) - 4) * (82.0/75.0));
ImageView3.frame = CGRectMake(ImageView2.frame.size.width + ImageView1.frame.size.width + 9, Main_View.frame.origin.y + 30, ((Main_View.frame.size.width / 3)-4), ((Main_View.frame.size.width / 3) - 4) * (82.0/75.0));
Main_View changes its size(width,height). Then (ImageView1 width) is (Main_View width / 3), It Preserves aspect ratio too.
Programatically it works perfect

This is quite easy to do it with autolayout in interfacebuilder as well. But, there are few things which you might have to sacrifice when using autolayout in interface builder. You would want to arrange items the items in storyboard. The steps to do it are as follows:
Add three views to interface builder, like so,
Select all three pictures and add new constraint in interface builder with the button like this |---|, and select equal width and equal height.
Then, again select all three views and then from the menu select Editor -> Align -> Top Edges
Select the left most view and give it some offset to the left,
Select the right most view and give it some offset to the right,
Select one of the view and give some offset at the top and bottom.
Select second view control + drag it to first and select the horizontal separation and give some constant value and do the same for the second and third view.
Now, the constraints is complete. It could happen that when you select the multiple views at the same time and add some constraint, it might not have been added to one of the views. So might have to resolve this looking error and seeing the constraints for the view, if all those constraints we added is there.
You could keep the constraint that separate the view from the top margin or bottom margin and create outlet for it and then change to suit your need or you could set some parameter in storyboard itself.
Here is the screenshot from my ipad simulator for the horizontal orientation.
And here is for vertical orientation,
I hope I have answered your question. Do let me know if you have something with this.

(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
// i assume here that you have three imageviews img1, img2, img3
float viewWidth = [UIScreen mainScreen].bounds.size.width;
float viewHeight = [UIScreen mainScreen].bounds.size.height;
if (toInterfaceOrientation == UIInterfaceOrientationPortrait){
// your portrait mode code here
}
else{
NSLog(#"bounds are (%f,%f)", viewHeight,viewWidth);
img1.width = viewHeight/3; //i used "viewHeight" because of landscape mode
img2.width = viewHeight/3;
img3.width = viewHeight/3;
// and then set centre of imageview according to your requirement
}
}

Related

How do I add constraints so that my view's dimensions do not change when the orientation changes?

I want my view to have the following properties (the numbers are arbitrarily chosen):
width is equal to height divided by 1.2
stays at the bottom right of the screen
height is 1/7 of the screen's height when in portrait
width and height does not change when the orientation changes
The first three requirements can be easily translated into UILayoutConstraints. I have done them with SnapKit just because it reads more clearly. You should see what I mean even if you have never used SnapKit before.
let myView = UIView(frame: .zero)
myView.backgroundColor = .green
view.addSubview(myView)
myView.snp.makeConstraints { (make) in
make.right.equalToSuperview().offset(-8)
make.bottom.equalToSuperview().offset(-8)
make.width.equalTo(myView.snp.height).dividedBy(1.2)
make.height.equalTo(view.snp.height).dividedBy(7) // *
}
The problem is the last bullet point. When I rotate the device from portrait to landscape, what was originally the width before the rotation, becomes the height after the rotation. This causes my view to become smaller as a result.
Basically, I want to replace the constraint marked with * with something like this:
make.height.equalTo(max(view.snp.height, view.snp.width)).dividedBy(7)
but I don't think max(a, b) is a thing in SnapKit or the UILayoutConstraint API.
Surely there is some other way of expressing "equal to whichever length is longer", right?
P.S. I didn't tag this with snapkit because I would also accept an answer that uses the UILayoutConstraint API.
Looks like you have 2 options:
Hardcode the height value.
Try to use nativeBounds:
This rectangle is based on the device in a portrait-up orientation. This value does not change as the device rotates.
In this case the height is always be for portrait mode.
myView.snp.makeConstraints { make in
make.right.bottom.equalToSuperview().offset(-8)
let screenHeight = UIScreen.main.nativeBounds.height / UIScreen.main.nativeScale
let height = screenHeight / 7
make.width.equalTo(height).dividedBy(1.2)
make.height.equalTo(height)
}

ios - Adjust button width and height based on screen size

I am trying to adjust button sizes according to the device they are run on. iPhone SE is small compared to iPhone 8 and as a result the buttons do not fully appear.
I tried using the following code to adjust the size of the buttons according to the screen size but it did not show any changes.
roundedCornerDeliveryButton.layer.cornerRadius = 8
roundedCornerKitHomeButton.layer.cornerRadius = 8
widthMultiplier = Double(self.view.frame.size.width) / 69
heightMultiplier = Double(self.view.frame.size.height) / 321
roundedCornerDeliveryButton.frame.size.width = roundedCornerDeliveryButton.frame.width * CGFloat(widthMultiplier)
roundedCornerDeliveryButton.frame.size.height = roundedCornerDeliveryButton.frame.height * CGFloat(heightMultiplier)
roundedCornerKitHomeButton.frame.size.width = roundedCornerKitHomeButton.frame.width * CGFloat(widthMultiplier)
roundedCornerKitHomeButton.frame.size.height = roundedCornerKitHomeButton.frame.height * CGFloat(heightMultiplier)
roundedCornerDeliveryButton.frame.origin = CGPoint(x: roundedCornerDeliveryButton.frame.origin.x * CGFloat(widthMultiplier), y: roundedCornerDeliveryButton.frame.origin.y * CGFloat(heightMultiplier))
roundedCornerKitHomeButton.frame.origin = CGPoint(x: roundedCornerKitHomeButton.frame.origin.x * CGFloat(widthMultiplier), y: roundedCornerKitHomeButton.frame.origin.y * CGFloat(heightMultiplier))
How would I do this?
There are a few ways to do this, but it comes down to how you declared your buttons in the first place.
If your buttons are declared in Storyboard or Xib file, you probably should be using layout constraints.
For example, if you want a button to take 1/3rd, you start by defining a layout constraint with the top view of the view controller with "Equal Width", then you edit that constraint and change its multiplier to 1:3
The layout system will do its magic to ensure the constraints is respected and the button is always 1/3rd the screen width.
You can declare several constraints like that to automatically respect different constraints, like making sure your button height is always taller than 36pt, width is never wider than 400pt, etc. Just have to define the proper priorities and the constraints.
Defining your sizing constraints this way has the advantage of being inspectable in the Xib as you can quickly change device type & orientation and make sure everything works before even running your code.
Good luck!
To make the button fit its content use
button.sizeToFit()
Also it's better to do it with auto-layout
self.view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor)
])
You can add this constraint if you want it proportionally
button.widthAnchor.constraint(equalTo:self.view.widthAnchor,multiplier:0.75)

Swift 4 - Editing label frame.size.height with negative number

So I have a label that I've made in Xcode's storyboard which I want to later edit in my code. I want it to simulate something like a vertical bar so I am editing its height by doing:
answerE.frame.size.height = -200
The problem comes from the negative number, I want the label to "grow" up so the height has to be negative from its original position... I have the line in code in a simple action on button press, but each time the line is executed the label moves "up" and eventually after 3-4 clicks is out of the screen.
I just want to edit its height, what is the correct way and what am I doing wrong?
My exact line in code is:
label.frame.size.height = -CGFloat(Double(x)/Double(y) * (200))
If you have added the label in storyboard, why not you use constraints to get the result.
Add leading, trailing , bottom and fixed height constraint and connect IBOutlet to height constraint. Change the constant value of height constraint at the event which you want to perform.
If I'm right, you want the label to gain height, keeping the same bottom edge, but the top edge moving up.
In order to do this, you want to change the frame.origin.y as you change the frame.size.height at the same amount, as its placement (and so top edge) is determined by its origin. So maybe make it zero height, place it where you want it in storyboard, and then when you want it to 'grow' by x:
label.frame.size.height = label.frame.height + x
label.frame.origin.y = label.frame.origin.y - x

Full width view does not contain same frame width as parent

I'm having an issue where I have a UIImageView that spans the entire width of the screen using the following constraints.
Align Leading to : Superview (Equals: -20)
Align Trailing to : Superview (Equals: -20)
Top Space to : Top Layout Guide (Equals: 0)
Aspect Ratio : 1:1
The image assumes the width of the screen while gaining aspect ratio (in this case a square). The issue comes with when I started attempting to make a circle out of the image, that I noticed that my UIIMageView's frames do not have proper values.
You'll have to excuse to code below for not being in Objective-C as I'm using Java through RoboVM but with very little effort you can mentally convert the code to Objective-C as it's pretty straightforward.
public class MyViewController extends UIViewController {
#IBOutlet private UIImageView myImageView;
#Override public void viewDidLoad() {
System.out.println("Image view width: " + myImageView.getFrame().getWidth());
System.out.println("Superview width: " + this.getView().getFrame().getWidth());
}
}
The results of running the application with this Controller shows the following:
Image view width: 240.0
Superview width: 320.0
When cutting the frame width of the image in half and applying that to the CALayer#cornerRadius property, the image does not make a complete circle, however when using half of the superviews width (Which is actually the size of the image) the result is a perfect circle.
In viewDidLoad, it has just loaded your view from the XIB or storyboard, not sized it yet. The size should be correct when viewWillAppear is called. So try putting your code in viewWillAppear and see if that helps.
The reason you need the -20 margin is because your superview has a margin of 20, and the constraints are created by default to 'Relative to margin' - if you uncheck that, you can set the 'real' constraint - in this case zero rather than -20
If you select the constraint in the assistant editor, you will see the check box to toggle this value

iOS view positioning depending on screen size using constraints

I have been reading documentation/tutorials and playing around with constraints in Xcode and still can achieve what I need.
The issue is that I need to position views (labels, images) and spread them vertically depending on the screen size of the device (focusing on iPhone for now). The css equivalent would be to use margins with percentages.
The labels/images, images don't need to grow or shrink.
As an example I have this in my Interface Builder.
To illustrate the problem I have constraints from top to bottom as follows:
Top image has a "Vertical Space Constraint" (or Top Space) to the "Top Layout Guide.Bottom" of 63
The "Membership" label has "Top Space" of 32
The Membership # has "Top Space" of 16
The white view has "Top Space" of 32 and bottom of 16
The imageview has "Top Space" of 32
The label has "Top Space" of 32
The button has "Top Space" of 20
This measures are correct for the iPhone 6. Now what I have been trying to achieve is to fit the same information in a smaller screen (iPhone 3.5 and 4 inch) by contracting the constraints values. I've tried using the multiplier but didn't work (or didn't know how to use it properly). I tried adding constraints to wAny hCompact but only worked for one of the constraints (top image to top margin), all the other constraints got overridden.
So this is how it looks in iPhone 6.
And this is how I want it to look in iPhone 4 (3.5 inch).
Thanks in advance.
Okey so in such cases i outlet the NSLayoutConstraints in their corresponding ViewController and i start manipulating them based on the screen size at runtime , usually in the viewWillAppear or viewDidAppear , for your case i will assume some facts and show you a small example :
you want the top constraint of the top image to be 10% of the total height of the view
you want the top constraint of the membership label to be 7% of the total height of the view .
you want the top constraint of the membership hash to be 5% of the total height of the view .
you want the top constraint of the white view to be 7% of the total height of the view and the bottom to be 5% of the total height of the view .
you want the top constraint of the image to be 7% of the total height of the view .
you want the top constraint of the label to be 7% of the total height of the view .
you want the top constraint of the button to be 6% of the total height of the view .
so based on those assumptions i would do the following :
-(void)myLayOutMethod
{
//here you set the percentage of every constraint of the view .
CGFloat screenHeight = self.view.frame.height ;
CGFloat topImageConstraintValue = screenHeight/0.10f ;
CGFloat topMembershipLabelConstraintValue = screenHeight/0.07f ;
CGFloat topMembershipHashConstraintValue = screenHeight/0.05f ;
CGFloat topWhiteViewConstraintValue = screenHeight/0.07f ;
CGFloat bottomWhiteViewConstraintValue = screenHeight/0.05f ;
CGFloat topImageConstraintValue = screenHeight/0.07f ;
CGFloat topLabelConstraintValue = screenHeight/0.07f ;
CGFloat topButtonConstraintValue = screenHeight/0.06 ;
//now you start making changes to those constraints .
self.topImageConstraint.constant = topImageConstraintValue;
self.topMembershipLabelConstraint.constant = topMembershipLabelConstraintValue ;
self.topMembershipHashConstraint.constant = topMembershipHashConstraintValue ;
self.topWhiteViewConstraint.constant = topWhiteViewConstraintValue ;
self.bottomWhiteViewConstraint.constant = bottomWhiteViewConstraintValue ;
self.topImageConstraint.constant = topImageConstraintValue ;
self.topLabelConstraint.constant = topLabelConstraintValue;
self.topButtonConstraint.constant = topButtonConstraintValue ;
[self.view layoutIfNeeded];
}
off course all of these percentages are dummy values you can change them as you want , and another thing making outlets of NSLayoutConstraint is the same as making outlets from any other UIKit control , you simply find the constraint and drag it to your class

Resources