The iPad app pdf expert displays popovers which seem to consist only of the header. Which kind of popover is this? I can't find something about it in the Apple docs. But it seems to be a standard UI element. Or is it a custom view?
Its nothing like a custom view. Its just without UINavigationController.
ViewController *viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
UIPopoverController * popover = [[UIPopoverController alloc] initWithContentViewController:viewController];
popover.delegate = self;
popover.popoverContentSize = CGSizeMake(644, 425);
[popover presentPopoverFromRect:button.frame inView:self.view permittedArrowDirections: UIPopoverArrowDirectionLeft | UIPopoverArrowDirectionUp animated:YES];
This will solve you problem. Check it out.!!
Related
I am updating an old app to the new adaptive size way of doing things and having difficulty getting a popover with a navigation controller to work.
My goal: I want to be able to open a popover from a button when the app is either compact and regular horizontal. The popover has a tableview and uses a navigation controller to push view controllers when the user touches a row on the table. I can get the popover to open correctly, but I can’t figure out who to make the pushes work.
Here’s the code that opens the popover:
OptionsController *vc = [[OptionsController alloc] initWithNibName:#"OptionsView" bundle:nil];
vc.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popover = [vc popoverPresentationController];
popover.delegate = self;
[self presentViewController:vc animated: YES completion: nil];
popover.permittedArrowDirections = UIPopoverArrowDirectionUp; // change as necessary
popover.sourceView = self.view;
CGRect popoverRect = [self.view convertRect:[sender frame] fromView:[sender superview]];
popover.sourceRect = popoverRect;
This code correctly opens a popover in either compact or regular size.
In the OptionsController’s didSelectRowAtIndexPath method, I have this(controllersArray is an array of UIViewControllers, each of which corresponds to a row in the table):
UIViewController *nextController = [self.controllersArray objectAtIndex: [indexPath row]];
[self.navigationController pushViewController:nextController animated:YES];
All this executes, but no push occurs, so the next view never appears.
I clearly am not understanding something about using the UIViewController’s navigationController, or how to install a navigationController to make this work. After three or four days of digging around to try to understand how to make this work, I'd appreciate any insights, or links to documentation about how to do this. Thanks in advance.
Crud - this has a very easy answer. Just took me thinking a different way and digging through Larcerax's comments. Here's how to make this work:
OptionsController *vc = [[OptionsController alloc] initWithStyle:UITableViewStylePlain];
vc.title = #"Options";
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController: vc];
nc.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popover = [nc popoverPresentationController];
popover.delegate = self;
[self presentViewController:nc animated: YES completion: nil];
popover.permittedArrowDirections = UIPopoverArrowDirectionUp; // change as necessary
popover.sourceView = self.view;
CGRect popoverRect = [self.view convertRect:[sender frame] fromView:[sender superview]];
popover.sourceRect = popoverRect;
The difference is that I create the UINavigationController in the usual manner...
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController: vc];
...set the navigationController's presentation style to popover, then get the popoverPresentationController from the navigationController - before I was doing those two methods on the UIViewController.
nc.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popover = [nc popoverPresentationController];
Finally, I present the navigationController:
nc.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popover = [nc popoverPresentationController];
This approach presents a popover, in compact and regular horizontal sizes, that contains navigation controller functionality: just what I wanted.
Thanks again to Larcerax whose answer wasn't what I needed, but made me re-think what I was doing in a different way. As usual, StackOverflow comes through.
Here's what you should try. I use about 10-40 navigation controllers per app for the apps I work on and I've had this same sort of issue, I've not used popovers, but I've subclassed the crap out of navigation controllers and view controllers to have encountered your same problem. The thing is that if you do this:
UIViewController * ff = [UIViewController new]
[self presnetViewController:ff ... blah blah blah
There is apparently NO navigation system attached to the modal view controller and therefore you can't navigate to anything else, you can only close the modal and move on. So, this is what I do to resolve this and it works everytime, well it works everytime for UIViewControllers, give it a shot
see the following, it's not for popovers, but the principle is the same:
NSHTermsOfServiceViewController * pvc = [NSHTermsOfServiceViewController new];
UIBarButtonItem * backBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"exit-button"] style:UIBarButtonItemStylePlain target:self action:#selector(backerPressed)];
NSHNavigationController * ssf = [[NSHNavigationController alloc] initWithRootViewController:pvc];
[[pvc navigationItem] setLeftBarButtonItem:backBarButtonItem];
[[self navigationController] presentViewController:ssf animated:true completion:nil];
NSHTermsOfServiceViewController <== is a subclass of another subclass of a UIViewcontroller, it's basically a UIViewController on steroids, that's all
NSHNavigationController is a UINavigationController that is subclassed and pumped up on steroids for animations
The flow is this:
create a viewController
create a new UINavigationController
Set the view controller you created in step 1 as the root view controller of the navigation controller created in step 2
present the NAVIGATION CONTROLLER, not the UIViewController, you can present this navigationController from a view controller like so ..
v
[self presentViewController:ssf animated:true completion:nil];
or you can present it from the current view controller's navigation controller which is what I prefer, like so:
[[self navigationController] presentViewController:ssf animated:true completion:nil];
Your code, modified, the only problem is that I don't know if you can present a UIPopOverViewController by rooting it inside a navigation controller
OptionsController *vc = [[OptionsController alloc] initWithNibName:#"OptionsView" bundle:nil];
UIPopoverPresentationController *popover = [vc popoverPresentationController];
UINavigationController * stuff = [[NSHNavigationController alloc] initWithRootViewController:popover];
stuff.modalPresentationStyle = UIModalPresentationPopover;
stuff.delegate = self;
[self.navigationController presentViewController:stuff animated: YES completion: nil];
popover.permittedArrowDirections = UIPopoverArrowDirectionUp; // change as necessary
popover.sourceView = self.view;
CGRect popoverRect = [self.view convertRect:[sender frame] fromView:[sender superview]];
popover.sourceRect = popoverRect;
Yep, my bad, doesn't work for popover, I just tried it
So, with that said, is it absolutely necessary to use a popover? Why are you using this and now just a UIViewcontroller that you reconfigure to look like a popover and then you have what you need?
Here's this, I just tried it with the Ipad simulator, and it allowed a push, just as it should have.
NSHLoginViewController * pvc = [NSHLoginViewController new];
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:pvc];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:navController];
UIView * stuff = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 1000, 1000)];
[self.view addSubview:stuff];
[popover presentPopoverFromRect:[[self contentView] nameField].frame inView:stuff permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
this: [[self contentView] nameField].frame is just a uitextfield, nothing special, that's all, and the method above presented the login viewcontroller, when I put in my credentials, I pressed log in and it pusehed the next viewcontroller as it normally would, there's probalby something wrong with the touches being intercepted by your uitableview or whatever, perhaps not, but this method did work for me.
I just ran into a very frustrating problem. I don't know if it's an iOS8 bug or it's something else.
I'm loading the view from a nib, which looks like this:
Here ist my code:
UIViewController *popoverViewController = [[UIViewController alloc] init];
[popoverViewController setView:poppverViewFromNib];
_popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverViewController];
[_popverController presentPopoverFromRect:CGRectMake(100, 100, 10, 10) inView:[self view] permittedArrowDirections:UIPopverArrowDirectionAny animated:YES];
The iOS simulator as well as the real device are displaying the viewController modally like you can see here:
EDIT
As requested in comments, I tell you what I expect when using UIPopoverController:
I expect an UIPopover, not a modalViewController.
So here my question to all of those how didn't get it: Why does my UIPopoverController does not display as a popover but as modalViewController? How can I fix it?
Read the documentation. Popover presentation is only available for horizontally regular size classes. Currently, this is only on iPad. Popover presentation on iPhone will always be executed as full screen modal presentation. See here.
You are lucky that iOS8 doesn't crash, as iOS7 and below, if you used UIPopoverController on a phone idiom, your app would crash. UIPopoverController is deprecated in iOS8 in favor of popover modal presentation. This is why your app does not crash.
You could keep the same code for UIPopoverController as iOS 7
just set ViewController.preferredContentSize = CGSizeMake(300, 290);
It will work.
Other Solution
iOS 8 has a new PopOverController called UIPopoverPresentationController
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController *navController = [storyboard instantiateViewControllerWithIdentifier:#"Terms_NC"];
navController.preferredContentSize = CGSizeMake(300, 290);
// Present the view controller using the popover style.
navController.modalPresentationStyle = UIModalPresentationPopover;
[self presentViewController:navController animated: YES completion: nil];
// Get the popover presentation controller and configure it.
UIPopoverPresentationController *presentationController =
[navController popoverPresentationController];
presentationController.permittedArrowDirections =0;
presentationController.sourceView = self.view;
presentationController.sourceRect = CGRectMake(100, 100, 300, 340);
I'm trying to show a popover with a title, creating a root view controller and instantiating it with my viewController. But, when I show the popover, the content is not shown. Here is the code:
UIViewController *popContentViewController = [[sb instantiateViewControllerWithIdentifier:#"videosTutoriais"] init];
UINavigationController *controller = [[UINavigationController alloc] initWithRootViewController:popContentViewController];
_popover = [[UIPopoverController alloc] initWithContentViewController:controller];
_popover.delegate = self;
[popContentViewController release];
[controller release];
//dados.myPopoverController = popOverController;
[[self popover] presentPopoverFromRect:ancora.bounds inView:ancora permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Just to be more specific, the title of popover appears normally, but the content doesn't.
Just double check that popContentViewController is not nil. You have the identifier #"videosTutoriais" which looks like it might be a scanning error.
From your code, you are releasing the controller before you display in on the screen. Try releasing it after or in the dealloc method. If you are unsure about memory management. I suggest you try ARC instead to avoid silly errors and mistakes such as this.
The code looked like this:
sb = [UIStoryboard storyboardWithName:#"MainStoryboard_iPad" bundle:nil];
UINavigationController *controller = [[sb instantiateViewControllerWithIdentifier:#"navTutorial"] init];
_popover = [[UIPopoverController alloc] initWithContentViewController:controller];
[[self popover] presentPopoverFromRect:ancora.bounds inView:ancora permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
[controller release];
I would like to create a subview which loads notifications similar to Facebook in its iOS app. Does anyone know how to build that?
Thanks!
Something like that:
http://www.techarp.com/article/Apple/Facebook_Notifications/facebook.jpg
I suggest you to use a UIPopoverController.
UIViewController *viewController = [[UIViewController alloc] initWithNibName:#"UIViewControllerNibName" bundle:nil];
viewController.delegate = self;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:navController];
navController.contentSizeForViewInPopover = CGSizeMake(400, 200);
viewController.contentSizeForViewInPopover = CGSizeMake(400, 200);
poopover.delegate = self;
CGRect rect = CGRectMake(0, 0, yourWidth, yourHeight);
[popover presentPopoverFromRect:locRect inView:parentView permittedArrowDirections:UIPopoverArrowDirectionLeft animated:TRUE];
viewController is the UIViewController inside the popover, and there you can add, for example, a UITableView to show notifications. UIPopoverController is responsible of showing the popup view. Of course in presentPopoverFromRect: method you have to pass the frame the popover anchors to, the view in which present the popover, the arrow directions allowed and the animate flag in order to show the popover in an animated manner. Finally, with delegation you can communicate to the class that is allocing the popover (self.delegate = self).
I'm implementing printInteractionControllerParentViewController: as required by UIPrintInteractionControllerDelegate to customise the popover showing the print options. Which this is ran, the popover appears at the size of the full height of the (portrait) iPad, before shrinking down to the normal size.
Any advice on how to have the popover appear in a more sensible way would be helpful.
Here's my implementation:
- (UIViewController*)printInteractionControllerParentViewController:(UIPrintInteractionController*)printInteractionController {
UINavigationController* navigationController = [[UINavigationController alloc] init];
popover = [[UIPopoverController alloc] initWithContentViewController:navigationController];
[popover setPopoverBackgroundViewClass:[CustomPopoverBackgroundView class]];
[popover presentPopoverFromRect:_printButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
[popover.contentViewController.view setBackgroundColor:backgroundColor];
return navigationController;
}
Try setting the contentSizeForViewInPopover for the viewcontroller:
yourViewController.contentSizeForViewInPopover = CGSizeMake(320.0, 750.0);
You could set this when you initialize our controller.