UIPopoverController automatically resizing to max height on pushViewController

时光毁灭记忆、已成空白 提交于 2019-11-28 03:03:37
borked

This fixed it for me after I had the same issue (coincidently also today):

EDIT : As contentSizeForViewInPopover is deprecated in iOS7.0 so use preferredContentSize.

Original answer below:

In your detailViewController add this:

- (void)viewWillAppear:(BOOL)animated {

    CGSize size = CGSizeMake(320, 480); // size of view in popover
    self.contentSizeForViewInPopover = size;

    [super viewWillAppear:animated];

}

You also want to add something similar to your original DeviceDetailViewController to prevent resizing when tapping the back NavbarItem.

Much like handling it in viewWillAppear, another way to deal with this is to override contentSizeForViewInPopover. Very terse:

-(CGSize)contentSizeForViewInPopover
{
    return self.view.bounds.size;
}
MUH Mobile Inc.

For IOS5

I recommend you do it in:

- (void)viewDidLoad {
    [super viewDidLoad];

    CGSize size = CGSizeMake(320, 480); // size of view in popover
    self.contentSizeForViewInPopover = size;

}

I had a similar issue.

I had a popover present from a button in a toolbar. The popover was set to a specific size. It was a table view. When the table row was selected, a new view controller with a navigation controller was called.

When the back button was selected, the popover became the default size (320x1100 I believe), instead of the specific size that I desired.

The original code was:

  MyTableViewController *myVC = [[MyTableViewController alloc] init];
  UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myVC];

  UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:navController];
  popover.delegate = self;

  popover.popoverContentSize = CGSizeMake(400.0, 500.0);

  [myVC release];
  [navController release];
  [popover release];

I added one line to solve the problem. Granted it is kind of a work around because I had to subtract the height of the header. Maybe one of you could enlighten me with a better method. Anyway, it works.

  MyTableViewController *myVC = [[MyTableViewController alloc] init];

  UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myVC];

  UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:navController];
  popover.delegate = self;

  popover.popoverContentSize = CGSizeMake(400.0, 500.0);

  //Subtract the height of the header to match the total popover size (not just the view).
  myVC.contentSizeForViewInPopover = CGSizeMake(400.0, 500-44);

  [myVC release];
  [navController release];
  [popover release];

I believe that when a nav controller is involved, and the back button is pressed, it causes the popover to default to its default size. By adding the contentSizeForViewInPopover property for the view controller myVC, it forces the specific size.

Hope this is helpful.

Kurt

For iOS 7 use the following:

- (void)viewDidLoad
{
    [super viewDidLoad];

    CGSize size = CGSizeMake(320, 768); // size of view in popover
    self.preferredContentSize = size;
}

UIViewController.contentSizeForViewInPopover has been deprecated first in iOS 7.

In response to graphical glitches with animations:

The UIPopoverController animations conflict with the UINavigation controllers animations, if you create the popover with a UINavigationController inside it. It results in graphical glitches when animating. To fix the issue, set animated parameter to false when pushing other controllers, or when displaying the toolbar.

Pushing View Controllers:

[self.navigationController pushViewController:detailViewController animated:NO];

Making the Toolbar visible:

[[self navigationController] setToolbarHidden:NO animated:NO]; 

Setting the animated:NO will make the animations look correct in a UIPopoverController.

Why not just set the contentSizeForViewInPopover before you push the next controller onto the navigation stack? No need to set sizes in viewWillAppear and such.

[nextController setContentSizeForViewInPopover:[self contentSizeForViewInPopover]];
[[self navigationController] pushViewController:nextController animated:YES];

Works on IOS 5.1

Slight varient on borked's advice (which pointed me in the right direction, thanks for that!), here's what I do when pushing a new controller to maintain the size before pushing it:

productViewController.contentSizeForViewInPopover = self.view.bounds.size;
self.contentSizeForViewInPopover = self.view.bounds.size;

[self.navigationController pushViewController:productViewController animated:YES];

I like this because I don't have to hardcode the popover values in every view controller (good since I use them at various heights).

The self.contentSizeForViewInPopover line is to preserve the size when the user hits back. I guess you could put this line somewhere else, like viewWillAppear or wherever you like.

Seems to work...

In the -(void)viewDidLoad of all the view controllers you are using in navigation write the code:

self setContentSizeForViewInPopover:CGSizeMake(320, 500)];

There are two ways to set the contentSizeForViewInPopover in the storyboard. You can set your view controllers that are with your navigation controller, to FreeForm and set the root views to the desired size. Or, you can keep the simulated metric as inferred and check "Use Explicit Size" and set the size you want there.

Then, in each view controller that is within your navigation controller, add the following...

- (void)viewDidAppear:(BOOL)animated {
     [super viewDidAppear:animated];

     ["yourpopoverController" setPopoverContentSize:CGSizeMake(self.
           contentSizeForViewInPopover.width, seld.contentSizeForViewInPopover.height + self.
           navigationController.navigationBar.frame.size.height) animated:YES];
}

In the transition animation, the new view will come in aligned with the top, and then the height will be adjusted accordingly.

This way, you don't have to override contentSizeForViewInPopover, or specify some other size specifically in your view controllers. It's all in the storyboard.

If one of your view controllers has a variable height, then you do need to override contentSizeForViewInPopover in that view like so...

- (CGSize)contentSizeForViewInPopover {
    return CGSizeMake(450, "calculate your height here");
}

This stuff may have worked once but not with xCode 6 wherein contentSizeForViewInPopover is deprecated. Luckily it's respected at storyboard load time. I downloaded an xml editor (Xmplify) and hacked the storyboard. Set the key contentSizeForViewInPopover to the size you want. Save and replace (make a copy first) storyboard.

More specifically :

< viewController>

     <value key="contentSizeForViewInPopover" type="size" width="450" height="280" / >

</viewController>

Don't work for me, when i use this:

[UIPopoverController 
    [UINavigationController] = root vc = [UIViewController vc1] => [UIViewController vc2] 
]

When appear popover is all good, press button on vc1 and push vc2 to navigation controller

Next return to vc1 (root) pressing button in vc2 (popToRootViewController method);

We can see that popover change own size, but vc1 size is old... WHAT IS THIS???

Ok, now work... Add popover property in my controller

self.contentSizeForViewInPopover = (CGSize){400, 200};
self.navigationController.contentSizeForViewInPopover = self.contentSizeForViewInPopover;
self.popover.popoverContentSize = self.contentSizeForViewInPopover;

Running Swift 4 and iOS 11 the only possible solution was for me. To use showViewController:sender: and showDetailViewController:sender: instead of presentViewController:animated:completion:.

From the Apple Doc

The showViewController:sender: and showDetailViewController:sender: methods offer the most adaptive and flexible way to display view controllers. These methods let the presenting view controller decide how best to handle the presentation. For example, a container view controller might incorporate the view controller as a child instead of presenting it modally. The default behavior presents the view controller modally.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!