I have a UIPopover
being displayed from a UIBarButtonItem
in my iPad app. It contains a UINavigationViewController
, which has a sort of settings window as its root view controller. The settings window is a subclass of UITableViewController
(style set to grouped), and tapping any of its cells pushes different "chooser" view controllers on the nav controller that are also subclasses of UITableViewController
.
For each of the chooser views, in viewDidAppear
, I'm setting contentSizeForViewInPopover
appropriately:
self.contentSizeForViewInPopover = CGSizeMake(320, self.items.count * 44);
But it doesn't animate the change; when the navigation animation finishes, the popover snaps to the new height (width never changes from 320). Navigating backward animates the size change (accomplished with the technique from this answer), but forward never does.
I've tried obtaining a reference to the popover it's in and using setPopoverContentSize:animated:
but it doesn't work. I've looked at other questions to no avail.
How do I get it to always animate the size change properly?
Update: I've set up a simple test project to try this out. It's a tab bar application for iPad set up in Xcode. I added a tab bar item to the navigation bar in one of the view controllers. When that button is pressed, the controller presents a popover that contains a navigation controller that has a very simple UITableViewController
subclass, called TestContentViewController
, as its root view controller.
In viewDidLoad
of that subclass, I randomly generate a number of items:
self.numItems = arc4random() % 10 + 3;
This is my number of rows; number of sections is 1. In cellForRowAtIndexPath
I just set the cell's label text and return it. When a row is selected, I generate another instance of the same class and push it on the stack.
Without doing anything at all with the contentSizeForViewInPopover
property on any VC, the popover just goes to its maximum height and stays there no matter how many rows are in my table view.
If I set the size in viewDidAppear, like this:
-(void)viewDidAppear:(BOOL)animated
{
self.contentSizeForViewInPopover = CGSizeMake(320, self.numItems * 44);
[super viewDidAppear:animated];
{
If I do the same thing but in viewWillAppear
:
If I do the same thing in viewDidLoad
, it's basically the same as viewWillAppear
except it appears at the right size at first.
I've tried setting the nav controller's delegate to be the VC that presents the popover, and then set the popover's height (setPopoverContentSize:animated:
) in navigationController:didShowViewController:animated:
, but the resultant height is off by a little bit. I think the size I set there needs to take into account the extra height of the navigation bar built into the top of the popover. And the animation when pushing a new controller on the stack is weird.
Update again: See here for the same problem solved with the newer UIPopoverPresentationController
.
Try to do the following for all UITableViewController, I tried it and it works for me!
- (void)setSize:(BOOL)fake
{
CGSize view_size;
int sections_height, rows_height;
//if you dynamically change the number of visible rows
//for example overriding numberOfRowsInSection:section
//this can help you to evaluate the correct popover height
int sections = [self.tableView numberOfSections];
int rows = 0;
for(int i = 0; i < sections; i++){
rows += [self.tableView numberOfRowsInSection:i];
}
sections_height = sections * 30 /*section height*/;
rows_height = rows * 44 /*row height*/;
view_size = CGSizeMake(320 /*fixed width*/, sections_height + rows_height);
if(fake){
view_size.width -= 1;
view_size.height -= 1;
}
[self setContentSizeForViewInPopover:view_size];
}
- (void)viewDidLoad
{
[super viewDidLoad];
//...
[self setSize:FALSE];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self setSize:TRUE];
}
- (void)viewDidAppear:(BOOL)animated
{
[self setSize:FALSE];
[super viewDidAppear:animated];
}
I think you were close if you tried keeping a reference to the popoverController and used setPopoverContentSize:animated:
What works for me is this combination of setPopoverContentSize:animated:
AND contentSizeForViewInPopover
in that specific order, for each controller your put on the stack:
-(void)viewDidAppear:(BOOL)animated
{
[self.popoverController setPopoverContentSize:whateverSize animated:true];
self.contentSizeForViewInPopover = whateverSize;
[super viewDidAppear:animated];
}
In this case, self.popoverController is a reference I keep in each controllers that is pushed on the stack, it would probably be cleaner to use a singleton variable for that.
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