How to I change the size of modal dialog? Why is this not working?
SlingDialogViewController *slingDialog = [[SlingDialogViewController alloc] init];
slingDialog.modalPresentationStyle = UIModalPresentationFormSheet;
slingDialog.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
slingDialog.view.superview.frame = CGRectMake(0, 0, 900, 700);
[self presentModalViewController:slingDialog animated:YES];
Do this:
SlingDialogViewController *slingDialog = [[SlingDialogViewController alloc] init];
slingDialog.modalPresentationStyle = UIModalPresentationFormSheet;
slingDialog.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:navController animated:YES completion:nil];
slingDialog.view.superview.frame = CGRectMake(0, 0, 900, 700);
slingDialog.view.superview.center = self.view.center;
It's important to call presentViewController:animated:completion first, from my experience at least.
The modal controllers in iOS have fixed sizes. I don't recommend trying to change them, it never works reliably.
A workaround is to implement it by yourself. A modal (presented) controller is a very simple functionality:
A view overlapping your presenting controller, so that it can't be clicked (and it is dimming the contents to make them look backgroundish)
A child view controller (and its view) added to your controller.
Related
I'm trying to make a modal popup appear when scanning QR codes.
I have a .xib file that has the necessary views and is linked to my custom view controller. The usual stuff, except that I have a navigation controller so that I can add a close button at the top later and/or in case I need to push another screen.
To make things a little more complicated, I do not have direct access to the view controller (code is in a manager file). This is the code to create and launch the popup:
self.m_scannerVC = [[BarcodeScannerVC alloc] initWithNibName:NSStringFromClass([BarcodeScannerVC class]) bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.m_scannerVC];
// Set the navigation controller to be a modal popup.
navigationController.modalTransitionStyle = UIModalPresentationFormSheet;
// Set the size of the popup here.
navigationController.preferredContentSize = CGSizeMake(100, 200);
UIWindow *win = [[UIApplication sharedApplication].delegate window];
UINavigationController * winNav = (UINavigationController *)win.rootViewController;
winNav.providesPresentationContextTransitionStyle = YES;
winNav.definesPresentationContext = YES;
winNav.topViewController.providesPresentationContextTransitionStyle = YES;
winNav.topViewController.definesPresentationContext = YES;
winNav.modalPresentationStyle = UIModalPresentationOverCurrentContext;
winNav.topViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
// And now present the view in a modal fashion.
[winNav.topViewController presentViewController:navigationController animated:YES completion:^{
// Once presented, set the capture layer to fix inside our camera preview box.
[self.captureLayer setFrame:self.m_scannerVC.m_viewCameraPreview.layer.bounds];
// Adding the camera AVCaptureVideoPreviewLayer to our view's layer.
[self.m_scannerVC.m_viewCameraPreview.layer addSublayer:self.captureLayer];
// Start the camera capture session as soon as the view appears completely.
[self.captureSession startRunning];
}];
Any tips on what I am doing wrong will be greatly appreciated!
I found out why, I'm so stupid!
navigationController.modalTransitionStyle = UIModalPresentationFormSheet;
should be
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
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 have a ViewController that contains a textfield. When the user begins editing the text, I want to display
a ViewController that the user can use to select the font for the textfield. I am using Xcode 5 with
storyboards and compiling for IOS 7. This is where I present the view controller...
- (void)textViewDidBeginEditing:(UITextView *)textView
{
FTViewController *fontSelector = [[FTViewController alloc] init];
[self presentViewController:fontSelector animated:YES completion:nil];
}
I am using a Cocoapods project called FTFontSelector to pick the font. In the FTViewController that gets
presented, I have the following code that runs when the view controller loads. This code adds a UIToolbar
with two buttons, one of which I would like to be used to dismiss the view controller, but all of the
attempts I have made at making this happen have not worked.
- (void)loadView;
{
CGRect frame = [[UIScreen mainScreen] applicationFrame];
self.textView = [[UITextView alloc] initWithFrame:frame];
self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.textView.textAlignment = NSTextAlignmentLeft;
self.textView.font = [UIFont systemFontOfSize:FONT_SIZE];
self.textView.text = #"Hello World!";
self.changeFontButton = [[UIBarButtonItem alloc] initWithTitle:#"Font"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(changeFont:)];
self.dismissFontButton = [[UIBarButtonItem alloc] initWithTitle:#"Dismiss"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(dismissFont:)];
UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(frame), 44)];
toolbar.tintColor = [UIColor lightGrayColor];
toolbar.translucent = YES;
toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
toolbar.items = #[self.changeFontButton, self.dismissFontButton];
self.textView.inputAccessoryView = toolbar;
self.view = self.textView;
}
This is the method I call to dismiss the view controller that I need help with. I have commented out
what I have tried.
- (void)dismissFont:(id)sender;
{
[self.textView resignFirstResponder];
// This crashes!
//[[self presentingViewController] dismissViewControllerAnimated:NO completion:nil];
}
I suspect part of my problem is that there is no navigation controller in my presented view controller,
but when I tried to add one, the text went behind the view (I could see a few pixels of the top of the text),
and there was no back button, so something I tried to do there was wrong.
I am still pretty new to IOS programmng, so there is a lot I still don't understand. I have the rest of
my app working pretty well now, but this last piece is giving me a headache. I am hoping someone here can
show me how to dismiss this view controller.
[[self presentingViewController] dismissViewControllerAnimated:NO completion:nil];
sends a message to the parent view controller of your view controller. This is clearly not what you want. At best it would dismiss your view controller.
[self dismissViewControllerAnimated:YES completion:NULL];
is what you should do.
From -dismissViewControllerAnimated:completion:
The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, it automatically forwards the message to the presenting view controller.
In this case your view controller (self) is the presenting view controller.
I'm developing for iPad and I have the following problem:
I'm trying to show a modal with his own size and his own UINavigationController, I already done that, but when I present the modal with his UINavigationController, I get this:
I want the UINavigationController to fit to modal size. I leave the code of how I'm presenting the modal:
- (void)createANewEvent:(id)sender
{
AddEditEventViewController *addEditEventViewController = [[(ScheduleViewController *)self.viewContainer storyboard] instantiateViewControllerWithIdentifier:#"AddEditEventViewControllerID"];
addEditEventViewController.modalPresentationStyle = UIModalPresentationFormSheet;
addEditEventViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:addEditEventViewController];
[self.viewContainer presentViewController:navigationController animated:YES completion:nil];
}
How I resize the modal:
AddEditEventViewController.m
// Resize the view
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 548, 768);
self.view.superview.backgroundColor = [UIColor clearColor];
}
Hope you can help me!
Thanks in advance! :)
A view should never modify its superview's size or position.
The problem is that you're setting modalPresentationStyle on the root view controller instead of the view controller you're presenting, navigationController.
Delete:
addEditEventViewController.modalPresentationStyle = UIModalPresentationFormSheet;
addEditEventViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
Delete the viewWillLayoutSubviews method you posted.
Add:
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
navigationController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
I would sub-class UINavigationController and implement the method:
preferredContentSize
Something like
- (CGSize) perferredContentSize {
return CGSizeMake(548,768);
}
That's all you should need to do to have properly resized modal views.
and have it return a CGSize structure with the size that you want the modal to be. This is the 'correct' way to do it per Apple documentation.
In conjunction, remove the viewWillLayoutSubviews method, that's just going to cause problems sometime in the future.
After [self.viewContainer presentViewController....] add:
navigationController.view.superview.bounds = CGRectMake(0, 0, 548, 768);
and get rid of your viewWillLayoutSubviews
How to display a modal popup that look like from a UITableViewCell (look like option ), which displaying a custom controller?
I'm trying to achieve something like contact app does ( see below ) :
Below is my current implementation, which only displaying common modal :
TSCAliasViewController *V2 = [[TSCAliasViewController alloc] initWithNibName:nil bundle:nil];
V2.modalPresentationStyle = UIModalPresentationFormSheet;
V2.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:V2 animated:YES];
V2.view.superview.frame = CGRectMake(0, 0, 400, 300);
V2.view.superview.center = self.formView.center;
Any idea?
You need to use UIPopoverController. Currently it works on iPad only!