I have a view hierarchy under a UIViewController that consists of a main view and a few subviews of the main view, all defined in a storyboard, and all connected using IBOutlet.
I would like to set the position and size of the subviews relative to the main view.
I've tried setting them in viewDidLoad and viewWillAppear. Neither work, and when called, the main view has valid frame values but the subviews all have frames of (0,0,0,0).
If I do nothing, the subviews appear exactly where positioned on the storyboard. I need to make the following code work, but I don't know where to put it.
CGRect newFrame = CGRectMake(10,10,50,50);
[subView setFrame:newFrame];
Another way to ask this question:
Where and when do the frames of storyboard subviews get set?
Or, should I just create all the subviews with code?
when using autolayout you can set frame of the views (if the frame is calculated from super view's frame) in viewDidLayoutSubviews method or the other way I use is calling this method [view setTranslatesAutoresizingMaskIntoConstraints:YES]; and then [view setFrame:...];. Hope this helps.
The position and size of subviews can be set when the UIViewController calls viewDidAppear but that causes the presentation to jump. Setting the position and size of a UITableView in viewDid/WillLayoutSubviews does not work.
Related
I'm using Storyboard with autolayout. In my ViewController I have a basic structure: one UIScrollView and one contentView (UIView) that contains different labels). Then I have different elements that I add in the viewDidAppear method of the class inside my contentView , then in order to recalculate it's frame size I do this:
- (void)fixContentViewHeight
{
_contentView.frame = CGRectMake(_contentView.frame.origin.x, _contentView.frame.origin.y, _contentView.frame.size.width, operators.frame.origin.y + operators.frame.size.height);
//constraint for contentView height
_contentViewHeight.constant = operators.frame.origin.y + operators.frame.size.height;
}
- (void)fixScrollViewHeight
{
_scrollView.frame = _contentView.frame;
_scrollView.contentSize = _contentView.frame.size;
}
where operators is the LAST placed element of contentView, it's always on the bottom of the frame. I call these 2 methods inside the viewDidAppear and they make the view scrollable, the problem is that the frame of contentView doesn't get updated so the last elements are always unclickable (because they're placed outside the frame of the view).
What am I doing wrong? Why the scrollView becomes scrollable but the contentView keeps it's old frame?
If you have autolayout constraints affecting the height of _contentView You will not be able to change its height by setting the frame, as the constraints will override that.
You will need to (and should be) adding new / modifying constraints in your code when you are adding new elements. then calling
_contentView.layoutIfNeeded()
After all the updates to let the UI update if it needs to, which it should.
Please update UI On Main Queue
dispatch_async(dispatch_get_main_queue(), ^{
// update any UI on Main queue
});
I think that all your frame related information should be inside viewWillLayoutSubviews() and viewDidLayoutSubviews(). You can add stuff in viewDidLoad() but for any frame management I would use mentioned methods.
In your particular situation use former, viewDidLayoutSubviews(). However, you can resolve these kind of issues using constraints connected to the code as #Simon McLoughlin mentioned. 'scrollView becomes unscrollable' means that you should update contentSize as well so keep an eye on that as well.
Try to add vertical space constraint between scroll view and your last placed element.
I create a view called boundView using IB and Auto Layout,then in the controller I call [self.boundView layoutIfNeeded],then I pass self.boundView.frame.size to a method to generate the size of boundView's subview CardView. And then use the
PlayingCardView *playingCardView = [[PlayingCardView alloc]initWithFrame:frame];
to create subview programmatically. I do use NSLog to check that the size of subview is smaller than superview. But when I use [self.boundView addSubview:CardView] to add the subview. It is larger than superview!
Is there something wrong with the coordinate?Or it is because I combine the Auto Layout with the view I create by code?
Where are you doing this? If it is in viewDidLoad then the autolayout sizes will not have been calculated yet. Try doing it in viewDidLayoutSubviews.
I have a UIViewController with a UICollectionView and a UIView at the bottom. The way I put it together is displayed in the image below
The yellow square is the UICollectionView and the red is the UIView. This works out just fine. But now I want to resize the UIView because it sometimes contains more info and needs to be bigger. So I tried this:
[self setFrame:CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height + 10)];
But this expands the UIView at the bottom and it is not visible. I guess this is because I do not have the correct constraints? I also tried to subtract the origin.y with the same amount and this works only the UICollectionView doesn't get resized with the new height. So how do I tackle this problem?
If you are using autolayout, you should not be setting the frame from your code. Instead you should modify the constant of a constraint that is causing your view to be the incorrect size. You can have an IBOutlet to that constraint and you can change it's constant property. Then call setNeedsLayout on your view controller's view
When setting constraints on your storyboard or in a xib file, animations perform animations on the constraints instead of the sizes and positions.
First create a outlet reference of the constraint which will change (in your case the top space of your UIView to the top layout guide) in the header file of your view controller.
When you want to animate a view, you now have to update its constraints and ask to layout the views.
For example :
[UIView animateWithDuration:0.2
animations:^{
viewYConstraint.constant -= 44;
[self.view layoutIfNeeded];
}
]
//Now don't forget to update constraints
[self.view updateConstraints];
I would think this is a simple question, but I cannot seem to find a way to do this.
I have a view that is a subview of my uiviewcontroller. Within that view, I have another view. To clarify, this is the architecture:
>UIViewController.view
--->Subview A
------->Subview B
I want to get the frame of subview b within uiviewcontroller.view.
Is this possible? subviewB.frame gives me the frame of the view within Subview A.
Use the UIView convertRect:toView: method:
CGRect frameRelativeToViewControllerView = [subviewB convertRect:subviewB.bounds toView:viewController.view];
I have a custom view that is added to the view controllers view
[self.view addSubview:myView];
In the view I added :
self.autoresizingMask = self.superview.autoresizingMask;
But my view's DrawRect method is not called when auto rotating... Why? I need the view's bounds to change so I can redraw it on auto rotate ...
What is the value of self.superview.autoresizingMask? That's probably why nothing's changing. Either explicitly set the autoresizing mask to what you want it to do, or if that doesn't provide enough control, use the ViewController's willAnimationRotationToInterfaceOrientation method to explicitly set the subview's frame or trigger a setNeedsDisplay: on the subview.