add a UIView and recalculate constraints with autolayout - ios

I need your help to make this:
I have a view which width is equal to the width of screen. In this view I have 2 subviews with width 1/2 of parent view and aspect 1:1, so the height of the parent view should be equal to the height of subviews.
After that I need to perform animation which should add to the parent view another view and transform a whole screen like this:
Should I use autolayout programmatically to achieve this? How to get this behaviour easier?

You can...
First, instead of making them half the parent view, I would:
Set the left border of the left view to the left border of the parent view.
Set the right border of the right view to the right border of the parent view.
Set the horizontal space between the left and right views = 0.
Set an equal widths constraint between the left and right views.
Then when you add the new view,
Remove the right border constraint of the right view.
Set the right border of the new view to the right border of the parent view.
Set the horizontal space between the right view and new view = 0.
Set an equal widths constraint between the right and new views.
Then call
[UIView animateWithDuration:0.5 animations:^{
[view layoutIfNeeded];
}];
Note that if the default is just two views, you could add the first set of constraints via storyboard (which is easier than doing it programmatically). The rest of it you can do programmatically: See Apple documentation.
Personally, I like this method, because you don't have to do any math on the size or positions of the views - autolayout will figure it out for you.

The easiest way would be.
In design time(Storyboard) add 3 views inside the parent view.
For all the child views (View 1,2 and 3) create a width constraint and create outlets for the same. When design is completed for all the views, set 0 as constant for the third view's width constraint.
Implement "viewDidLayoutSubviews" method for the view controller as below.
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
}
Inside this method, find the current width of the parent view, and store it in a variable "X".
When the view is loaded for first time, set the width constraint's constant as x/2 for first and second view.
When 3rd view is ready to display, set width constraint's constant as x/3 for all the three view inside an animation block.

Related

Why subview keep sticking to bottom and not adjusting according to parent UIView height

I created a UIView and set its layout like this
And inside the above UIView I created another small UIView and set layout like this
I changed the height of UIView like this
but small UIView is not automatically adjusting according to its parent UIView height, it keep sticking to bottom. I want that small UIView always stick to its parent bottom what ever parent UIView height is. How can I do that?
Constraints of viewBlue is w.r.t. ViewContainer (VC's View) not wrt viewGreen.
So do one of the follow :
Please check your view hierarchy in storyboard. Your viewBlue must be subview of viewGreen.
Right click on the viewBlue and drag it to viewGreen. This means you giving constraints to viewBlue wrt viewGreen . You get list of constraints that you can give wrt. Now give appropriate constraints which satisfy your conditions.
Either you need to make sure that your larger UIView contains the smaller view, as in the smaller one is contained in the larger one, then your constraints would be based on the larger view.
Your other, non - preferable option, is to give the smaller UIView a top constraint instead of a bottom constraint, and then it would be attached to the larger UIView.
Make sure that your subview is inside parent UIView and then select both the views (subview and parentview), click on add new constraint at bottom right in Xcode as per given screenshot. You can place subview according to parent view's height, leading, trailing edges etc.
You have to place Small view inside of Large View and then give it bottom constraint to its parent (Large View).
Whenever you change the height from Large View, the small view inside it will move and stick to its parent bottom.

Remove one view's layout constraints but keep its subviews'?

Working on a project in iOS 8 using storyboard and auto layout:
In storyboard, specified constraints for this view and its subviews
In code, in response to touch events, I'm going to change this view's size by setting its frame
To make both 1 and 2 warning free, I'm doing the following when first changing its size with code:
[theView removeConstraints:theView.constraints];
theView.translatesAutoresizingMaskIntoConstraints = YES;
theView.frame = CGRectMake(0,0,width,height);
If not doing the first line, Xcode will complain a whole bunch about constraint conflicts, however adding this line will remove all its subview's constraints as well. So my question is: is there way to just remove this uiview's constraints but not its subview, say a button on it still wants to center its self relative to this view's size and position?
First, you don't need to resize the view by setting frame otherwise what is the point of keeping the constraint at first place. You could have position that by simply having a correct initial frame.
Secondly, you have a mis-conception about "TO-WHOM" a constraint has been applied to.
say a button on it still wants to center its self relative to this view's size and position?
When you apply a position related constraint to a view you normally apply it to it's superview. Means if you want to position a subview in the horizontal centre of a view then the constraint is added on view not on the subview. That's why when you called a removeContraints: message on view that position constraint was removed and now your subview isn't bound to any constraint. However the width and height constraints are applied to subviews itself.
To solve this you need to make IBOutlets for constraint that you need to modify, which in your case should be width, height, horizontal x and top constraint; and then change the constant values for them respectively.
theView.widthConstraint.constant = newValue;

How to make ScrollView width = to device screen width?

I am making an app that has a (child) View inside a Scroll View. I understand I have to explicitly set the child View's width since the Scroll View won't provide that information to the child, but how can I make this child View's width auto-adjust based on the width of the device?
For example, in the below I've set the width to 380 which centers the "Quotes" in iPhone 6, but makes them slightly right of center in iPhone 5.
You can use auto layout to set the width of your subView equal to your main View by performing a control drag from your subView to your main View like this:
Then select "Equal Widths" from the popup
Select viewController
Stretch the view you want full screen size to the size of the screen
Click the central icon from the three choices along the bottom of the window
You will an icon pop up
The top 4 values will have a dotted red line joining them
click them all
at the bottom of the pop up you will see 'add 4 constraints'
click this
Done!
You can delete the constraint for width. The view will place it self horizontally becuase of the leading and trailing space to superview. No need for a specific width.
I think your scrollview will be scrolling vertically so in that case you probably need to provide a constraint for the height or your view, and update scrollview contentsize accordingly to this.
Since your child view is located in the view hierarchy of your view controller's view you can assign constraints between your child view and your view controller's view.
Ctrl drag from your child view to your view controller's view. You will see option to set them to have equal widths. Select it. Then adjust the constant if you want the width of your child view to be lower.
You can then add leading and trailing constraints between your child view and your scroll view.
Doing it in this way will also ensure that you set the content width of you scroll view dynamically and correctly.
Let me know if it works for you

UIScrollview won't scroll when Autolayout is used

I have a scrollview which has two subviews (iPad). The view hierarchy is as follows:
-- UIScrollView
-- UIView1
-- UIView2
The frame of the UIScrollView is the size of the screen, the frame of UIView1 is also the size of the screen, but the frame of UIView2 is (0,0,768,2000).
The scrollview doesn't scroll vertically. According to the apple documentation, the scrollview should automatically set its content size. Can anyone help me out with this issue as why the content size is not being set properly ?
P:S: When I use a single view inside the scrollview and set a proper vertical constraint, it scrolls properly.
Scrollview won't scroll if you enable autolayouts. Technically when you scroll, all the elements in the scrollview change their position. So use auto layout if you are fixing the position of the elements in the scrollview.
Instead use a UIView as a container view inside a scrollview which contains all other objects like button , label, imageview etc. And then you will be able to scroll.
Check the below link for more details:
https://developer.apple.com/library/ios/technotes/tn2154/_index.html
In your problem try to put proper values of content size. Also check if the vertical scrolling is enabled or not.
The question is old, but the correct answer would be to make sure the autolayout constraints are all set.
Vertically, you should have some constraint pinning your View1 to the Scroll View Top, another one pinning your View2 to the Scroll View Bottom, and one third one setting the vertical space between View1 and View2. Also check that the views themselves (View1 and View2) have constraints for their heights.
Horizontally, pin one of the views to the Scroll View in both leading and trailing space, and the other view left and right to the first one (so they will have equal widths).
Once all of those are set, the content should scroll correctly.
Use contentSize property of scroll view in code. The best way is to use 'viewDidLayoutSubviews' method
(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
_scrollView.contentSize = CGSizeMake(568, 594);
}
2.Always make horizontal space >=0 between lowest of inner views and a scroll view. Automatically, auto layout make suggestions like '-160' and this negative space will not scroll.
If the Content size is more than the scroll view frame then only scroll view scrolls otherwise not .
Main Point : Mistake is in set 'contentSize' of 'UIScrollView', you need to set manually.
As seem in your Question
scroll view frame = screen frame,
view 1 frame = screen frame,
Its okay but
view 2 frame = (0,0,768,2000), then it overlapping on first view because your view2 x,y position is (0,0), so may be your first view will not display.
If you want to vertically add view 1 after view 2 then your view 2 frame should be
view2.frame = CGRectMake(0,view1.frame.origin.y + view1.frame.size.height , 768,2000);
And after added both of view then you need to manage contentSize of UIScrollView , in your case such like
scrollView.contentSize = CGSizeMake(768, view1.frame.origin.y + view1.frame.size.height + 2000)
I put simple logic, That may be helpful in your case:
How to enable scrollview scroll automatically when used with AutoLayout:
Please see the below link which help you to fix it correctly:
https://medium.com/#pradeep_chauhan/how-to-configure-a-uiscrollview-with-auto-layout-in-interface-builder-218dcb4022d7
Question for above help guide:
Which view is parent view?
scrollView or parent of scrollView?
Answer:
- Parent Of ScrollView (Give equal with and Equal height to view which is parent of scrollview)

iOS autolayout-move a view located inside a tableviewcell to the center of the screen

I have a tableview with cells containing text views as well as imageviews. My project is currently using AutoLayout. My goal is to get the imageview to display in fullscreen when it is tapped. One option is to use a modal view controller, but I want to have this work sort of like the way tapping on images in the facebook app works, the app centers the image and fades the background.
Since I'm using autolayout, I cannot simply set the frame of the imageview to fill the screen. Instead, I need to use autolayout constraints. My image view has 5 constraints, a constraint setting a distance from the bottom of the cell, as well as the left an right sides, and one controlling the image height. The last is a vertical space constraint between the textview above the image view and the top of the image. While this would appear to conflict with the height and bottom constraints, for some reason interface builder forces me to have this. To avoid problems, I set this constraint's priority to be less than 1000 (the image should never overlap the textview anyways, since the tableview cell height is set so everything will fit perfectly).
To center the image, I set the distance from the left and right to be zero and remove the vertical space constraint. In order to center the image, I replace the bottom space constraint with a center y alignment constraint to the UIWindow as opposed to the tableviewcell. I want to have it be in the center of the screen, not the cell.
To get the main window I use this:
AppDelegate* myDelegate = (((AppDelegate*) [UIApplication sharedApplication].delegate));
//access main window using myDelegate.window
Then, to set the constraint:
//currently sets the distance from the bottom of the cell to 14
//changing it...
[cellselected removeConstraint:cellselected.imagebottomspace];
cellselected.imagebottomspace = [NSLayoutConstraint constraintWithItem:cellselected.viewimage attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:myDelegate.window attribute:NSLayoutAttributeCenterY multiplier:0 constant:0];
[cellselected addConstraint:cellselected.imagebottomspace];
However, this doesn't work. The changes in the width and height of the image view apply just fine. However, when readding the imagebottomspace constraint, I get an unsatisfiable layout--apparently the constraint conflicts with another constraint which sets the distance between the bottom and the image view to 14, the very constraint I just removed. So it seems that it isn't actually removing the constraint.
When I proceed and let the app break a constraint, the imageview moves, but to the wrong place. It isn't centering in the screen. It moves way up and off the screen.
Obviously what I'm doing isn't right. What am I doing wrong?
So I guess you want something like this:
First, you need to know that as of Xcode 4.6.3, the nib editor (“Interface Builder”) has a bug when setting up constraints in a table view cell. It should create the constraints between the subviews and the cell's content view, but instead it creates the constraints between the subviews and the cell itself. This tends to screw up layout at runtime. (This bug is fixed in Xcode 5 and later.)
The consequence of this is that you should either remove all of the constraints that were in the nib and recreate them in code, or just get rid of the nib and create the cell's entire view hierarchy in code.
Second, there's an easier way to do the image zooming. Here's the basic procedure when a cell is selected:
Convert the selected cell's image view bounds to a CGRect in the top-level view's coordinate system.
Create a new image view just for zooming and set its frame to that CGRect. Set its userInteractionEnabled to YES. Set its autoresizingMask to flexible width and height. Add a tap gesture recognizer.
Add the new image view as a subview of the top-level view.
Set the cell's image view's hidden property to YES.
In an animation block, set the new image view's frame to the top-level view's bounds.
Disable the table view's panGestureRecognizer.
When the new image view is tapped, reverse the procedure:
Convert the selected cell's image view bounds to a CGRect in the top-level view's coordinate system.
In an animation block, set the zoomed image view's frame to that CGRect.
In the animation completion block:
Remove the zoomed image view from its superview.
Set the cell's image view's hidden property to NO.
Enable the table view's panGestureRecognizer.
Since you're not moving the original image view, you don't have to mess with its constraints. Hidden views still participate in layout.
Since you're creating the new image view in code, it will have translatesAutoresizingMaskIntoConstraints set to YES by default. This means that you can just set its frame. Auto layout will automatically turn the frame into constraints.
You can find the full source code in this github repository.
I've just come across a similar issue. I think that the reason for these problems are that the views embedded in UIScrollViews exist in a different bounds system to those of the views outside it. This is effectively how scrolling works in the first place, think of it as just applying a variable offset to the views it contains. Autolayout doesn't know how to translate between these different coordinate systems so any constraints that bridge across aren't going to be applied the way you expect.
To quote from Erica Sadun's excellent book iOS Auto Layout Demystified (from the section 'Constraints, Hierarchies, and Bounds Systems'):
"Be aware of bounds systems. You should not relate a button on some
view, for example, with a text field inside a separate collection
view. If there's some sort of content view with its own bounds system
(such as collection views, scroll views, and table views), don’t hop
out of that to an entirely different bounds system in another view."

Resources