UIPopoverController Anchor Position - uipopovercontroller

I have a UIPopOverController for which the content controller is a UINavigationController.
I'm resizing the popover size according to the content size of the controller pushed/popped into it. Initally i'm presenting the popover by using the method presentPopoverFromRect:inView:permittedArrowDirections:animated:. The anchor position is pointing at the center of the rect which i passed as an argument. If i push a controller(whose content size is small) into the navigationController , the popover shrinks from the bottom and moves above the rect which i mentioned earlier.
I tried to present the popover everytime(for push/pop) , anchor position remains # same point But the animation gets affected , doesnt looks good.
what needs to be done to make the anchor position remains same irrespective of the change in popover size variation ?

I've encountered the same issue and it seems that calling the presentPopoverFromRect method again will keep the anchor at the same position
e.g.
[self.myPopOver presentPopoverFromRect:rectOrigin inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
Hope it works in your case as well

Change frame after presenting UIPopoverController:
[popupController presentPopoverFromRect:btn.frame inView:self.view permittedArrowDirections:0 animated:YES];
CGRect popupFrame = popupController.contentViewController.view.superview.superview.superview.frame;
popupFrame.origin.y = btn.frame.origin.y + btn.frame.size.height+75;
popupController.contentViewController.view.superview.superview.superview.frame = popupFrame;

Related

When rotating, UIPopoverController displayed from UITableViewCell is incorrectly placed

I have a popover that displays from a UITableViewCell in a UITableView, which is the only view in a modal dialog. This works fine in both landscape and portrait:
UIViewController *content = [[SetTimeClockTimeViewController alloc] init];
popover = [[UIPopoverController alloc] initWithContentViewController:content];
[popover setDelegate:self];
UITableViewCell *cell = [dataTable cellForRowAtIndexPath:[dataTable indexPathForSelectedRow]];
[popover presentPopoverFromRect:cell.frame inView:cell.superview permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
However, when the screen is rotated while the popover remains up, the popover shifts away from the cell (if I rotate back it shifts to the proper location). This happens if either orientation is the starting orientation. I tried implementing popoverController:willRepositionPopoverToRect:inView:, but nothing I've put in it appears to have fixed the problem. For example:
- (void)popoverController:(UIPopoverController *)popoverController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView *__autoreleasing *)view {
// TODO: Popover moves wrong when rotating
UITableViewCell *cell = [dataTable cellForRowAtIndexPath:[dataTable indexPathForSelectedRow]];
*rect = cell.frame;
*view = cell.superview;
}
I've tried telling the table to reloadData when rotating, using convertRect:toView to have self.view as the view, and calling presentPopoverFromRect:inView:permittedArrowDirections:animated in didRotateFromInterfaceOrientation:, but none of those seemed to fix the improper placement.
How can I ensure the popover is displayed from the new cell location after rotation?
Example of the popover displaying in portrait (arrow points to "Time" row):
After orientation to landscape (arrow should point to "Time" row):
Popovers displayed from a view do not maintain a relationship with the view, and might more often than not shift to incorrect places after rotation. This is unlike displaying from a bar button item, where the popover will move after layout. You should move the popover to the correct location in viewDidLayoutSubviews of the view controller.
Make sure to convert the returned rectangle to the view's correct coordinate system by using convertRect:toView: or convertRect:fromView:.
You should translate the rect to the superview using convertRect:toView. The most important part is to call it in willAnimateToInterfaceOrientation method.
The best solution I have seen for this is to use the cell(or in my case a UIButton) as the sourceView and the cell's bounds as the sourceRect.
i.e.
[popover
presentPopoverFromRect:cell.bounds //vs cell.frame
inView:cell //vs cell.superView
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];

Positioning/Sizing of a UIPopOver without an arrow

I am having trouble with setting the size and position of a UIPopOver without an arrow.
What i am trying to do is to bring up a popover view on the top left of the iPad screen and also have the content size that i have set.
I get different content size for the popover when i use an arrow and when i not. When i use the following code:
CGRect rec = CGRectMake(0, 0, 1, 1);
[self.displayOpPopover presentPopoverFromRect:rec inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
The result is:
and when i do:
[self.displayOpPopover presentPopoverFromRect:rec inView:self.view permittedArrowDirections:0 animated:YES];
The result is :
I have set 'use explicit size' for popovers in the storyboard (which is the size of the view when i have an arrow).
But the view somehow resizes itself when the arrow direction is 0.
Any suggestions as to how should i set the popover to the top left without an arrow.
Thanks !

Frame sizing of tableview within nested child controllers/subviews

I'm a bit confused by the proper frame sizing of a table view to fit within my screen.
Here's my setup of view controllers within view controllers:
UITabBarController
UINavigationController as one of the tab bar viewcontrollers; title bar hidden
ViewController - a container view controller because I need the option to place some controls beneath the UITableView, sometimes (but not in the current scenario)
UITableViewController
Now, my question is what the proper frame dimensions of the UITableview should be. Here's what I've got in the ViewController viewDidLoad method. I used subtracted 49.0 (the size of the tab bar) from 480.0. However, this leaves a black bar at the bottom. 20.0 appears to do it (coincidentally?) the size of the status bar, but I don't understand why that would be. Wouldn't the true pixel dimensions of the tableview be 480-49?
// MessageTableViewController is my subclass of UITableViewController
MessagesTableViewController *vcMessagesTable = [[MessagesTableViewController alloc] init];
CGRect tableViewFrame = CGRectMake(0, 0, 320.0, 480.0 - 49.0);
[[vcMessagesTable view] setFrame:tableViewFrame];
self.tableViewController = vcMessagesTable;
[self addChildViewController:vcMessagesTable];
[[self view] addSubview:vcMessagesTable.view];
Here's how it looks:
I've run into this problem also -- I think it would be best not to hard code the size but to refer to the size of one its ancestor controllers. In this case, the UINavigationController, that's the direct child of the tabBar controller should have the right frame to fill the whole screen minus the tabBar. So I would subtract (if you need to) from that frame height if you want space at the bottom, otherwise, just use that frame. I think that self.navigationController finds the nearest nav controller above your controller of interest.

How can I have a popover come from a tab instead of a view

I have a tabbar app, and I want a popover to come from one of the tabs. Is there a good/easy way to do this without changing views?
There isn't currently a way to directly (through a supported api call) get the frame of a specific tab bar item. What I do is just show the popup from the left end of the tab bar like this:
CGFloat tabBarHeight = self.tabBarController.tabBar.bounds.size.height;
CGRect rect = CGRectMake(0, 0, tabBarHeight, tabBarHeight);
[popoverController presentPopoverFromRect:rect
inView:self.tabBarController.tabBar
permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
You could try to estimate the position of the tab bar item taking the current orientation into account if you really wanted to and adjust the X coordinate of the rect above.
You could also look through the subviews of the tabbar and find the UITabBarButton object but that's not documented so it's not recommended.

centering a uipopover in iPad

I would like to create a new keyboard for the iPad.
I have designed a view that has the keys and all the underlying work to fill in a textbox as the user presses the keys, and passes the value back to the calling routine when the user presses the return button.
This all works ok.
Now - I want to create this view as a popover.
I have the basic operations complete (pops up and is dismissed)
But now I need some fine tuning help.
Here are my questions...
1) How do I create a popover window centered on the screen without a UIPopoverArrowDirectionAny selection?
2) Ensure the popover window is the size that I created it with in the XIB file (currently, it resizes and removes some of the rightmost size of the window)
Thanks
tony
To present it with no arrows pass 0 for "permittedArrowDirections":
[popOverController presentPopoverFromRect:rect inView:view permittedArrowDirections:0 animated:YES];
To center it, pass a 1x1 rect located at the center of your view:
CGRect rect = CGRectMake(viewWidth/2, viewHeight/2, 1, 1);
[popOverController presentPopoverFromRect:rect inView:view permittedArrowDirections:0 animated:YES];
Then you have a centered and arrow-free popover.
The bit about removing the arrow could break at any time. They didn't provide a UIPopoverArrowDirectionNone option for a reason, they may choose to throw an exception in the future when 0 is passed, or default to something. Use it at your own risk.
If you are using a UIPopoverController, it will have an arrow. Here are your choices.
UIPopoverArrowDirectionAny
UIPopoverArrowDirectionUp
UIPopoverArrowDirectionDown
UIPopoverArrowDirectionLeft
UIPopoverArrowDirectionRight
As you can see there is no UIPopoverArrowDirectionNone
As for the XIB size, in your ViewDidLoad Method of the implementation file, you can set the following.
self.contentSizeForViewInPopover = CGSizeMake(320.0, 360.0);
You can set the size any way you like for the popover.
I've just been working this one out but wanted to do as much in the storyboard as possible which changes the approach a bit:
1) Select the popover in the storyboard and un-tick Directions Up/Down/Left/Right to get rid of the arrows.
To center it on screen override prepare for segue and do something like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
UIStoryboardPopoverSegue* popover = (UIStoryboardPopoverSegue*)segue;
CGFloat horizontalInset = (self.view.frame.size.width - popover.popoverController.popoverContentSize.width) / (CGFloat)2.0;
CGFloat verticalInset = (self.view.frame.size.height - popover.popoverController.popoverContentSize.height) / (CGFloat)2.0;
popover.popoverController.popoverLayoutMargins =
UIEdgeInsetsMake(
verticalInset,
horizontalInset,
verticalInset,
horizontalInset);
}
In my case I also found that the popover segue's corner radius didn't match my design so I change the background color to clear to sort that out i.e. add this to the above block:
popover.popoverController.backgroundColor = [UIColor clearColor];
2) In the destination controller for the segue find the attribute 'Popover' and tick 'Use Explicit Size' and put the size of you want it to appear in popover mode.

Resources