popover full screen in iOS 8 - ios

I have the following code for a UIPopoverController. It is working fine in iOS 7. However, in iOS 8, the popover becomes full-screen which I do not want. How do I keep the popover from filling the entire screen in iOS8?
CGRect buttonFrame = [[[[[self tabBarController] tabBar] subviews] objectAtIndex:index+1] frame];
popover = [[UIPopoverController alloc]initWithContentViewController:viewmapmenu] ;
popover.popoverContentSize = CGSizeMake(95, 128.0) ;
popover.delegate = self ;
[popover presentPopoverFromRect:buttonFrame inView:self.tabBarController.tabBar permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES] ;

Try to add this delegate method.
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller;{
return UIModalPresentationNone;
}

See, here is the situation. if you are presenting the popover in iPhone then it will not work in iOS 8 as Apple has completely restricted it even if it was previously working. Now you cannot present popover in iPhone as all the access to the private methods of UIPopover is blocked.
You can look into the FPopover Library in github to use popover in iPhone:-
https://github.com/50pixels/FPPopover

Related

bad orientation in screen with multiple viewcontrollers/ views in iOS 7, landscape only (iOS 8 is fine)

I'm using TheSidebarController to implement add a sliding menu into an iOS application. This is the library I'm using, but I've found the same issue in other libraries, like ECSlidingViewController, etc. They essentially work by adding multiple view controllers onto a containing view controller, nothing too crazy.
The issue is, when you make the app a landscape app, all the screens in the container- the menu, the content screen- seem to think they're in portrait mode, and get cut off half way. You can see the issue in this screenshot where the table is cut off:
http://imgur.com/xD5MUei
I've been trying to get this to work in any way I can, and no luck.
The library I'm using + example project can be found here:
https://github.com/jondanao/TheSidebarController
Any help is greatly appreciated :)
EDIT: people are saying I can stretch the table out to make it look normal, but this just masks the underlying problem, which is the app and/or the screens still think they're in portrait orientation. As a quick example, if I take the example project, and in LeftViewController substitute the following code:
- (void)dismissThisViewController
{
UIViewController* vc = [[UIViewController alloc] init];
UINavigationController* pulldown = [[UINavigationController alloc] initWithRootViewController:vc];
pulldown.view.frame = CGRectMake(pulldown.view.frame.origin.x, -[[UIApplication sharedApplication] delegate].window.frame.size.height,
pulldown.view.frame.size.width, pulldown.view.frame.size.height);
[[[UIApplication sharedApplication] delegate].window addSubview:pulldown.view];
[UIView animateWithDuration:.5 animations:^{
pulldown.view.frame = CGRectMake(pulldown.view.frame.origin.x, 0,
pulldown.view.frame.size.width, pulldown.view.frame.size.height);
} completion:^(BOOL finished) {
;
}];
}
The viewcontroller comes in sideways, not from the top.
This was a strange one... I had to set the frame of the content view controller, which made sense, but then I had to reset it every time the content was refreshed:
- (void)setContentViewController:(UIViewController *)contentViewController
{
// Old View Controller
UIViewController *oldViewController = self.contentViewController;
[oldViewController willMoveToParentViewController:nil];
[oldViewController.view removeFromSuperview];
[oldViewController removeFromParentViewController];
// New View Controller
UIViewController *newViewController = contentViewController;
[self.contentContainerViewController addChildViewController:newViewController];
[self.contentContainerViewController.view addSubview:newViewController.view];
[newViewController didMoveToParentViewController:self.contentContainerViewController];
_contentViewController = newViewController;
if ([DeviceDetection isDeviceiPad]) {
_contentViewController.view.frame = CGRectMake(0, 0, 1024, 768);
}
}
Did you check if it's has something to do with the new interface orientation?
https://developer.apple.com/library/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS8.html
chapter -> Supporting New Screen Sizes and Scales
In CenterViewController.h make the class a subclass of a UITableViewController instead.
Then comment out [self.view addSubview:self.tableView]; in CenterViewController.m.
Done!
In centerViewController.m, when you create the tableview, add this line:
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth;

UIPopoverController content appears too big

Im trying to present a UIViewController that contains a UIWebView inside a UIPopOverController.
The problem is, that the ViewController inside the popOverController "acts" as if it has an entire screen size so i get scroll indicators and scrolling instead of it just "surrendering" to the container size.
Any suggestions?
NSMutableArray *filesArr = AppDelegate.appContentManager.filesArray;
BIDContent *cellContent = ((BIDContent *)[filesArr objectAtIndex:indexPath.row]);
BIDPreviewPopupViewController *popUpContent = [self.storyboard instantiateViewControllerWithIdentifier:#"previewPopup"];
popUpContent.pageContent = cellContent;
_popOverDisplay = [[UIPopoverController alloc] initWithContentViewController:popUpContent];
[_popOverDisplay setPopoverContentSize:CGSizeMake(self.view.frame.size.width/2.0, self.view.frame.size.height/2.0)];
popUpContent.view.frame = CGRectMake(0, 0, _popOverDisplay.popoverContentSize.width, _popOverDisplay.popoverContentSize.height);
[_popOverDisplay presentPopoverFromRect:[tableView cellForRowAtIndexPath:indexPath].frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:TRUE];
Forgot about a "hidden" gem in the UIWebView - "scales page to fit". Once I turned this on, all was good!

UIPopoverController Width Not Setting

My popovers are sizing incorrectly in iOS 7. The height is working fine, but the width is not getting set at all. The popover has a very skinny width, no matter what I set it to. It still works in iOS 6 but breaks in iOS 7. Is there something new I need to do with popovers in 7 that I'm missing?
Here's the code that works in iOS 6 and not iOS 7:
self.mediaPicker = [[UIImagePickerController alloc] init];
self.mediaPicker.contentSizeForViewInPopover = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height);
self.cameraPickerPopover = [[UIPopoverController alloc] initWithContentViewController:self.mediaPicker];
self.cameraPickerPopover.popoverContentSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height);
self.cameraPickerPopover.delegate = self;
[self.cameraPickerPopover presentPopoverFromRect:self.toolbar.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:animated];
I found out contentSizeForeViewInPopover is deprecated in iOS 7 so I updated the code as follows and it's still not working:
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
self.mediaPicker.contentSizeForViewInPopover = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height);
} else {
self.mediaPicker.preferredContentSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height);
}
The answer provided here
How to change the size width of UIImagePickerController on iPad?
is correct, except that for iOS 7, the contentSizeForViewInPopover property should be replaced by the preferredContentSize property.
The UIImagePickerController's delegate implements the UIImagePickerControllerDelegate and the UINavigationControllerDelegate protocols.
Adding the following method in the delegate implementation solves the issue in iOS 7 for me :
- (void)navigationController:(UINavigationController*)navigationController willShowViewController:(UIViewController*)viewController animated:(BOOL)animated
{
if (SYSTEM_VERSION_GREATER_THAN(#"7.0"))
viewController.preferredContentSize = CGSizeMake(800,800);
else
viewController.contentSizeForViewInPopover = CGSizeMake(800, 800);
}

UIPopover crashing when rotated

I have a universal app that displays buttons inside an actionsheet.
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:[dataObj.preferences objectForKey:#"appts_name"], #"Reserve", nil];
[actionSheet showInView:self.view];
On an iPad that automatically gets changed to a UIPopoverController. This displays and acts fine, however if I have the above popover being displayed and change orientation on the iPad then tap one of the buttons, it crashes in that buttons method where I am wanting to display another popover, saying that
-[UIPopoverController presentPopoverFromRect:inView:permittedArrowDirections:animated:]: Popovers cannot be presented from a view which does not have a window.
If I do not rotate the iPad and just tap a button it executes the same code just fine.
UINavigationController *navBar = [[UINavigationController alloc] initWithRootViewController:addItemView];
popOver = [[UIPopoverController alloc] initWithContentViewController:navBar];
if (viewPopover) {
if (self.view.window != nil) {
CLS_LOG(#"Rect: %# - View: %#", NSStringFromCGRect(rectPopover), viewPopover);
[popOver presentPopoverFromRect:rectPopover inView:viewPopover permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
} else {
// We should NEVER get here but just incase. I don't want the app to crash.
CLS_LOG(#"No viewPopover or rectPopover - %# - %#", viewPopover, NSStringFromCGRect(rectPopover));
}
Log from the CLS_LOG
-[AppointmentViewController showAppointmentAdd] line 148 $ Rect: {{341.333, 592}, {1, 1}} - View: <UIScrollView: 0xc8c5d40; frame = (1044 0; 768 872); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0xc8c7780>; contentOffset: {-0, 188}>
rectPopover and viewPopover are legit. Why is the popOver crashing saying it isn't in a window, but only when I rotate the device?
EDIT:
I found out it is being caused because after orientation change, I am reloading the view to account for the new sizes. It seems this takes precedence in the window. It also only seems to affect the UIActionSheet.
Have you tried tried redisplaying the popover after rotation?
You know when the rotation is occurring (willRotateToInterfaceOrientation:), and then you can redisplay the popover controller according to it's new anchor point.

iPad custom size of modal view controller

I have a couple of modal view controllers of certain size. I'm trying to avoid the use of custom views (creating full screen black translucent overlay over current view, add the modal view over that view, do the animations, etc) to present it because there is no modalPresentationStyle that fits the size of my controllers.
Now I'm using UIModalPresentationPageSheet but my view is smaller in height and I have an ugly blank space
Desired presentation
_______________
| _______ |
| | | |
| | MyVC | |
| | | |
| ------- |
---------------
Actual presentation
_______________
| | | |
| | MyVC | |
| | | |
| |-------| |
| | blank | |
---------------
If I use the UIModalPresentationFormSheet the container is smaller in width.
I'm trying to figure out how to do it but I don't know if it's possible. What is the solution to the problem of presenting a modal VC smaller than any of the presentationStyles? The only solution is to arrange a "custom modal view controller engine"? Popovers doesn't fit my design requirements :(
As some other users here, I also had the problem that the origin of the modal view controller was not correct. After some experiments, I found a solution that worked for me:
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, <width>, <height>);
}
I obtained the following result (link text) by using:
self.modalPresentationStyle = UIModalPresentationFormSheet;
and by presenting it as a modal view controller. Let me know if you need further help.
All these answers will not work on ios8 SDK.
This will work:
AboutViewController * _aboutViewController = [[AboutViewController alloc] init];
_aboutViewController.modalPresentationStyle = UIModalPresentationFormSheet;
if(IS_IOS8)
{
_aboutViewController.preferredContentSize = CGSizeMake(300, 300);
}
[self presentViewController:_aboutViewController animated:YES completion:nil];
In AboutViewController.m
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
if(!IS_IOS8)
{
self.view.superview.bounds = CGRectMake(0, 0, 300, 300);
}
}
IS_IOS8
#define IS_IOS8 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8)
In iOS 8 you can also use UIPresentationController which gives you more customization options.
I had an issue getting the custom sized modal to center until I figured out what ViewController.view.superview.frame was set to initially. It is determined based on the UIModalPresentation type. superview.center isn't even needed(as far as my testing shows).
Also, I set the coordinates dynamically using [UIScreen mainScreen].applicationFrame, only supporting landscape orientation for now. You have to do a conditional check to support both portrait and landscape by flipping the X/Y and Height/Width values.
Here was my first working solution for iOS 6.0:
ViewController.modalPresentationStyle = UIModalPresentationFormSheet;
ViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:ViewController animated:YES completion:nil];
ViewController.view.superview.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
ViewController.view.superview.frame = CGRectMake(
// Calcuation based on landscape orientation (width=height)
([UIScreen mainScreen].applicationFrame.size.height/2)-(320/2),// X
([UIScreen mainScreen].applicationFrame.size.width/2)-(320/2),// Y
320,// Width
320// Height
);
And then I looked at the previous answer and face palmed. Shortens my solution a tad by replacing the last line with:
ViewController.view.superview.bounds = CGRectMake(0, 0, 320, 320);
EDIT for final solution and remarks.
The best way to do this is to change the bounds property on the superview of the view being presented inside the formsheet. When you present a view modally, the presented view is embedded inside another view.
You should set the bounds property of the superview to the same rect as the view's bounds. First add a private ivar in your class:
#implementation MySpecialFormsheet {
CGRect _realBounds;
}
It's best to do this in viewWillAppear:. Add the following code to the view controller that is being presented modally:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.view.superview.bounds = _realBounds;
}
You need to cache _realBounds in your viewDidLoad method:
- (void)viewDidLoad {
_realBounds = self.view.bounds;
[super viewDidLoad];
}
even for reducing the forma sheet height and width you can use
[self.view.superview setBounds:CGRectMake(0, 0, 450, 480)];
This is my solution for a NOT autolayout view (never tried with autolayout) and compliant with iOS 7 and iOS 8.
At first be sure to call the modal view in this way:
CloudSettingsViewController *cloudController = [[CloudSettingsViewController alloc] initWithNibName:#"CloudSettingsView" bundle:nil];
CGRect originalBounds = cloudController.view.bounds;
cloudController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
cloudController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:cloudController animated:YES completion:nil];
With iOS 8 set the preferredContentSize in the viewDidLoad method of the modal view.
- (void)viewDidLoad {
[super viewDidLoad];
// backup of the original size (selected in interface builder)
height = self.view.frame.size.height;
width = self.view.frame.size.width;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8) // versioni successive ios 8
self.preferredContentSize = CGSizeMake(width, height); // this is necessary to get the correct size of the modal view
}
This works ALSO when the modal view needs to display the keyboard on iPad.
With previous versions of iOS 8 you should set the bounds after presentViewController call:
[currentController presentViewController:controlPanelController animated:YES completion:nil];
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8)
cloudController.view.superview.bounds = originalBounds;//it's important to do this after
The approaches described above need to be tweaked for iOS7:
// set desired bounds, then call -presentFromViewController:
#implementation PresentedViewController
{
CGRect _presentationBounds;
}
- (void)presentFromViewController:(UIViewController *)viewController
{
self.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
self.modalPresentationStyle = UIModalPresentationFormSheet;
_presentationBounds = self.view.bounds;
[viewController presentViewController:self animated:YES completion:nil];
}
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
if (!CGRectIsEmpty(_presentationBounds))
{
self.view.superview.bounds = _presentationBounds;
_presentationBounds = CGRectZero;
}
}
(This code also works on iOS6.)
Even I was struggling with the same issue for quite a while. After giving few tries from many of the answers given here I came up with a solution that worked for me pretty well.
Here is the code while presenting the view controller.
SomeViewController *sovcObj = [[SomeViewController alloc] initWithNibName:#"SyncOptionsViewController" bundle:nil];
someObj.modalPresentationStyle = UIModalPresentationFormSheet;
someObj.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:someObj animated:YES completion:nil];
someObj.view.superview.bounds = CGRectMake(0, 0, 400, 400); // whatever width and height you want
In the xib (if you are using one) in the 'Simulated Metrics' section select 'Freeform' size.
Apart from this you need to write the below code in your presented view controller (i.e.., SomeViewController in this example)
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 400, 400); // whatever width and height you want
}
This code also works for iOS 7 as well
One solution is to use UIModalPresentationPageSheet to present a page sheet and then immediately resize the modal view. This is fully explained in this answer to another question.
Resize the modal view "after" it is presented using presentModalViewController method.See this link to resize modal View https://coderwall.com/p/vebqaq
You can use MZFormSheetController like this:
MZFormSheetController *formSheet = [[MZFormSheetController alloc] initWithSize:customSize viewController:presentedViewController];
[presentingViewController mz_presentFormSheetController:formSheet animated:YES completionHandler:nil];
This solution worked for me as I had the same issue.
My modal view structure is the following (I use UIModalPresentationCurrentContext at both presenting and presented controllers to achieve transparency in the presented VC)
ModalViewController
> UIView (view) - resized to the same size as the presenting controller but has semi-translucent background - done automatically
>> UIView (contentView) - the true view with the content of the popup - this is the one that got consistently placed at the top of the screen all the time
In ModalViewController I overwrote the following method to fix the positioning issue:
- (void) viewWillLayoutSubviews(){
[super viewWillLayoutSubviews];
CGRect r = self.view.bounds();
self.contentView.center = CGPointMake(r.size.width/2,r.size.height/2);
}
I actually create and size the content view first but in different method.
Hope this helps someone.

Resources