So I have a very basic UIPresentationController that basically display contentView centered on screen, it's size is determined by view controller preferredContentSize. (Its very much similar to regular modal view controller presented as FormSheet).
What I'm trying to achieve, is to be able to update size of this view controllers' view dynamically, by just changing it's preferredContentSize.
When I set preferredContentSize, my subclass of UIPresentationController receive information about it in:
-(void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container
But how can I from here resize the view frame with animation ? If I just call:
-(void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container
{
[UIView animateWithDuration:1.0 animations:^{
self.presentedView.frame = [self frameOfPresentedViewInContainerView];
} completion:nil];
}
Immediately gets called containerViewWillLayoutSubviews and frame is changed without animation.
-(void)containerViewWillLayoutSubviews
{
self.presentedView.frame = [self frameOfPresentedViewInContainerView];
}
Please help me find a way, to resize it with animation. It must be possible, since it resizes with animation for example when rotation happens.
Instead of setting the frame from within preferredContentSizeDidChangeForChildContentContainer
, you only need to call setNeedsLayout
and layoutIfNeeded
on the container view.
This causes containerViewWillLayoutSubviews
to be invoked, which will update the frame using your animation configuration.
Objective-C:
- (void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container
{
[UIView animateWithDuration:1.0 animations:^{
[self.containerView setNeedsLayout];
[self.containerView layoutIfNeeded];
} completion:nil];
}
Swift:
override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) {
super.preferredContentSizeDidChange(forChildContentContainer: container)
guard let containerView = containerView else {
return
}
UIView.animate(withDuration: 1.0, animations: {
containerView.setNeedsLayout()
containerView.layoutIfNeeded()
})
}
Alternatively you could not have the animate block in preferredContentSizeDidChange...
, and instead place the assignment of preferredContentSize
in an animate block.
This way you have more control over the animation speed of individual transitions.
Objective-C:
- (void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container
{
[self.containerView setNeedsLayout];
[self.containerView layoutIfNeeded];
}
// In view controller:
[UIView animateWithDuration:0.25 animations:^{
self.preferredContentSize = CGSizeMake(self.view.bounds.width, 500.f);
}];
Swift:
override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) {
super.preferredContentSizeDidChange(forChildContentContainer: container)
guard let containerView = containerView else {
return
}
containerView.setNeedsLayout()
containerView.layoutIfNeeded()
}
// In view controller
UIView.animate(withDuration: 0.25) {
self.preferredContentSize = CGSize(width: self.view.width, height: 500)
}
You have to use auto layout. Make an outlet from your containers height constraint:
@property (nonatomic, strong, readwrite) IBOutlet NSLayoutConstraint *drawerViewHeightConstraint;
then add the following code:
- (void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container
{
[super preferredContentSizeDidChangeForChildContentContainer:container];
self.drawerViewHeightConstraint.constant = container.preferredContentSize.height;
[UIView animateWithDuration:0.25
animations:^{
[self.view layoutIfNeeded];
}];
}
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