Change frame of UIView and update the constraints of it childrens - ios

I need to change UI element based on what button was pressed, basically it is like a tab, but in just one part of my View Controller. The elements that I need to show/hide are UIView with multiple collection views and labels inside.
What I am doing right now Is defining both objects int he IB and programatically, when I need to show one I just set the width of one of them to 0 and set a new frame for the other one with the whole width I want. The problem with this approach is that even what the UIView is as I want it to be, the contents inside seem to keep the previous constraints (centered) and they don't "adapt" to the whole width.
Current Code:
var newFrame = self.view.frame
newFrame.origin.x = 0
newFrame.origin.y = self.blueView.frame.origin.y
newFrame.size.height = self.blueView.frame.size.height
if (showGreen){
self.greenView.frame = newFrame
self.greenView.hidden = false
self.blueView.frame.size.width = 0.0
self.blueView.hidden = true
}else{
self.blueView.frame = newFrame
self.blueView.hidden = false
self.greenView.frame.size.width = 0.0
self.greenView.hidden = true
}
In the IB I set the constraint for both views to have no separation between them and the margins.
I would like you to help me either in fixing this issue or with another way of achieving the desired behaviour behaviour.
Thank You.

you should change constraint.constant value, not the frame of UIView's,
make an IBOutlets for constraints you need, and change it this say:
self.widthConstraint.constant = newValue;
[UIView animateWithDuration:0.3 animations:^{
[self.view layoutIfNeeded];
}];

Related

Swift + UIView: How to change y coordinates?

I have a UIView called descriptionView and I want to hide it initially when the screen first loads by offsetting the y coordinate to be the screen size + the height of descriptionView itself:
However, in my controller, none of my frame changes do anything:
override func viewDidLoad() {
super.viewDidLoad()
...
// descriptionView.frame.origin.y = self.view.frame.height
// UIView.animateWithDuration(1, animations: {
// self.descriptionView.frame.origin.y = self.view.frame.height
// self.view.layoutIfNeeded()
// })
//
print("xxx")
descriptionView.frame = CGRectMake(0, self.view.frame.height, self.view.frame.width, 66)
// descriptionView.frame = CGRectOffset(descriptionView.frame, 0, descriptionView.frame.height)
}
No matter what I do it seems fixed at that visible position like in my storyboard. Can someone help?
In IB you are using NSAutoLayout, so you either need to manipulate the constraints, or tell the view to translate the mask to constraints.
If you want to set the frame directly then you will want to do this:
descriptionView.translatesAutoresizingMaskIntoConstraints = true
descriptionView.frame = CGRectMake(...)
Otherwise you can create IBOutlets to the height and width constraint from IB and update those:
self.descriptionViewHeight.constant = self.view.frame.width
Additionally, I would recommend doing frame manipulations inside of viewWillAppear: rather than viewDidLoad. viewDidLoad does not strictly guarantee final position.
Instead of editing the frame or descriptionView, edit its height constraint.
First, create an NSLayoutConstraint from this constraint by cmd-dragging the height constraint from the Interface Builder to your class (like you do for any UI object).
Then you can set the constant property of this constraint to 0.
(Yes, constant is declared as a varproperty...)
If you are using constraints, chaging the frame view myView.frame property will not affect on view actual position and size. Instead of this make constraint outlet and change it in your code, it will look like this:
descriptionView.heightConstraint.constant = 100
Also, if you want to hide something, you can use property myView.hidden = true, or myView.alpha = 0;

IOS: Hide/Reload tableView header

I created header for tableview(!not for the section) in story board with auto layout.
I want to have ability to show/hide it.
How can I do it?
I tried this code:
self.tableView.tableHeaderView.hidden = !flag;
CGRect frame = self.tableView.tableHeaderView.frame;
frame.size.height = flag? k_HEIGHT_TableViewHeader : 0;
self.tableView.tableHeaderView.frame = frame;
It works , But it gives me a lot of auto layout errors.
Also I can set it to nil. If so, how can I load header from storyboard?
Have you tried using [tableview reloadData] when you decide to hide/ show?
Because you created it with auto layout, rather than changing the frame, you should link the constraint for the height on your tableHeaderView from the storyboard to your class. Then when you want to collapse it, set the constraint.constant = 0 and expand it again by setting constraint.constant = k_HEIGHT_TableViewHeader. You will need to call layoutIfNeeded on the view afterwards as well.
This change can also be easily animated by wrapping the layoutIfNeeded in a UIView animation block
[UIView animateWithDuration:0.5 animations:^{[self.view layoutIfNeeded];}];
Auto Layout Animation Reference

Change size of views inside ContainerView programmatically

I have a container view which is equally divided between two UIViews like this:
The portion in black is my UIView 1, which I am currently not using. My UIView 2 contains a UISegmented Bar and a UITableView.
The hierarchy of my views look something like this:
Now, my requirement is I want to resize my view2 to cover entire container view dynamically and view1 to go away based on some condition. Currently I am not worried about that condition, I just tried to resize my view2 using the following code inside - (void)viewDidLoad
CGRect newFrame = self.view2.frame;
newFrame.size.width = 200;
newFrame.size.height = 200;
newFrame.origin.x=0;
newFrame.origin.y=0;
[self.view2 setFrame:newFrame];
Here view2 is the outlet to my view2 in interface builder.
But, nothing is changing from the above code. I tried to find any other way but had no help. So please help me find out my mistake in my current technique or tell me how some other technique to do it.
Thanks in advance!
The code to change frame seems fine, just remove the view from superview, set the frame and add to superview again programmatically.
[self.view2 removeFromSuperview];
// set the frame
CGRect newFrame = self.view2.frame;
newFrame.size.width = 200;
newFrame.size.height = 200;
newFrame.origin.x=0;
newFrame.origin.y=0;
[self.view2 setFrame:newFrame];
//add self.view2 again wherever it was
[myView addSubView:self.view2];

How to make UIScrollView height equal to content height?

I have an UIScrollView and horizontally scrollable content. I can properly set up the content size, etc, but I need to place another similar ScrollView just below the first one. So, I need to make height of the ScrollView to be equal to height of its content. Currently I use this code, but it does not work. I attached screenshot with issue and the code:
//setting the correct content size of scrollView (self.contentSize is already calculated)
self.imageScrollView.contentSize = self.contentSize;
//creating temporary CGRect
CGRect frame = self.imageScrollView.frame;
//Changing the height and re-assigning new frame to imageScrollView
frame.size.height = self.contentSize.height;
self.imageScrollView.frame = frame;
Look at the screenshot: the imageScrollView is just below NavBar. The content still scrollable and the size of ScrollView is smaller than content size.
You can't set the frame's height using frame.size.height = self.contentSize.height;
Instead use frame = CGRectMake(x, y, width, height); Ex:
self.imageScrollView.frame = CGRectMake(self.imageScrollView.frame.origin.x, self.imageScrollView.frame.origin.y, self.imageScrollView.frame.size.width, self.contentSize.height);
And from the looks of things, I suspect the content size of your imageScrollView is correct, but it's being hidden by your nav bar. In which case, I recommend setting imageScrollView frame's origin to the height of the nav bar, ex:
self.imageScrollView.frame = CGRectMake(self.imageScrollView.frame.origin.x, self.navigationController.navigationBar.frame.size.height, self.imageScrollView.frame.size.width, self.contentSize.height);
Update #1: Here's a link to a great answer explaining why you can't set the frame in the way you've attempted: ios frame change one property (eg width)
So basically you can edit a lone CGRect structure by changing a single property, but you can NOT update a CGRect in that way if it's a property of another object -- in this case a property of a frame.
Update #2: Also, to change the position of elements in your interface, place the code in viewDidLayoutSubviews, not in viewDidLoad.
Update #3: To have the code in viewDidLayoutSubviews only processed once, enclose it in a conditional, ex:
bool subviewsLaidout;
- (void)viewDidLoad {
subviewsLaidout = NO;
}
- (void)viewDidLayoutSubviews {
if (!subviewsLaidout) {
self.imageScrollView.frame = CGRectMake(self.imageScrollView.frame.origin.x, self.navigationController.navigationBar.frame.size.height, self.imageScrollView.frame.size.width, self.contentSize.height);
subviewsLaidout = YES;
}
}

How to move/push other uiviews when inserting a new uiview

I have a button and on click event of it i want to insert a UIView. I know how to insert a UIView however i am not able to push/move other UIView's that are below it so that i can accommodate the added UIView.
I have already looked at this link but it does not serve my purpose
Any suggestions?
In the method of the button create the new view and add it as a subview. Set the frame.origin.x to 0 minus the width of the view (if you want it to push from the left) so it is not visible and change that value to where you want it to be inside [UIView animateWithDuration:animations:].
[UIView animateWithDuration:1.0 animations:^(void){
[newView setFrame:({
CGRect frame = newView.frame;
frame.origin.x = 150; // If you want it to start at x = 150
frame;
})];
// If you want to move other views too, just add them in this block
}];
If you don't get what I'm doing to set the frame, check out the first tip in this post.

Resources