30

I am presenting a modal view controller. If it matters, it is scrolling up from the bottom. How can I control what portion of the screen it occupies?

EDIT: I have the following in the modal view controller. It's not helping.

- (void)viewDidLoad {
    TestResultView *trv = [[TestResultView alloc]initWithTest: [Model m].currentTest];
    self.view = trv;
    trv.frame = CGRectMake(0, 320, 320, 160);
    [trv release];
    [super viewDidLoad];
}
William Jockusch
  • 26,513
  • 49
  • 182
  • 323

3 Answers3

38

You can modify the frame of the view controller, but if you're using UIViewController's -presentModalViewController:animated: method, the view behind will be unloaded once your modal view is finished animating onto the screen (This assumes you're on an iPhone) and you'll see a white screen where your background view should be. iOS assumes that your modal view controller will be a full-screen view controller, and dumps the other view to save memory.

If you really want to show a view over part of the screen, you should instead add the UIView (no UIViewController) to your current UIViewController's view as a subview, and then animate it onscreen yourself. I think something like this would work in your UIViewController class that will present the view:

// Add the view as a subview and position it offscreen just below the current view
UIView *myHalfView = [[UIView alloc] initWithFrame:someAppropriateFrame];
[self.view addSubview:myHalfView];
CGRect offScreenFrame = myHalfView.bounds;
offScreenFrame.origin = CGPointMake(0.0, CGRectGetMaxY(self.view.frame));

// Now animate the view upwards
[UIView beginAnimations:nil context:nil];
// Move the view upwards the height of your sliding view so it's entirely onscreen
myHalfView.center = CGPointMake(myHalfView.center.x, myHalfView.center.y - myHalfView.bounds.size.height);
[UIView commitAnimations];
[myHalfView release];

For bonus points, you could fade the view in by setting

myHalfView.alpha = 0.0;

before the UIView animation block, and setting

myHalfView.alpha = 1.0;

inside the block after animating the center property.

When you're done, you can do something similar but in reverse to slide the view offscreen. You can add an animationDidStop selector to the UIView animation block to be notified when the view has slid off screen so that you can remove it from the view hierarchy.

From an aesthetic point of view, you should also be careful how you do this since having a view slide up is a standard behavior, and if your view looks like a normal view but stops halfway, users may feel (even briefly) that the app has frozen. They'll figure it out, but it will leave a bad feeling about your app if not handled carefully. Mainly, I would avoid using standard full-screen cues like including a UINavigationController at the top of your view to help users understand what's going on. Half-sheets tend to be UIActionSheets on the iPhone, so think in that direction.

atticus
  • 960
  • 7
  • 10
  • 1
    +1, nice solution! Just a quick one: Last line is missing a left bracket "[". – pille Jul 22 '12 at 20:06
  • 3
    This is a clever answer. However, I think you're going to be pulling your hair out if you start rotating the device and expect this view to behave. This is why Apple introduced an API to handle this. It's called a container view that allows you to have one VC that is the container of any number of other VC's. Very very powerful api. Look up UIViewController Containment. Will containment you can bring as many views that belong to separate VC's onto the screen, or move them around however you see fit. – SmileBot Sep 24 '13 at 18:29
26

That is nice, the above accepted answer explains a nice hack to present subViews which feel like ModalViews, but what if it is an iPad, and i can indeed give it a modalViewController which doesnt cover the entire screen.

In case of iPads, I dont think the underneath view will be unloaded. ( because there are options where we can present the modalView on iPads, which dont cover the entire screen )

ModalViewController in the end is a controller itself, and like any other controller has a root view, whose properties can be editted, if we can get hold of it.

Here is what will give you a custom frame of the ModalView :

MyViewController *viewController = [[MyViewController alloc] init];
viewConroller.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:viewController animated:YES];
    //superView of viewController's view is modalViewController's view, which we were after
viewController.view.superview.frame = CGRectMake(x,y,w,h);
    //x y w h - can have desired values.
dsaw
  • 577
  • 5
  • 12
20

I would add to @dsaw's answer that the superview of the modal view does not seem to rotate its coordinate system in landscape mode. Here is the code that I used in my own app:

MyViewController* modalVC = [[MyViewController alloc] init];        
modalVC.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:modalVC animated:NO];
CGRect r = CGRectMake(self.view.bounds.size.width/2 - 236,
                      self.view.bounds.size.height/2 - 130,
                      472, 260);
r = [self.view convertRect:r toView:modalVC.view.superview.superview];
modalVC.view.superview.frame = r;

While the superview may not rotate itself with the iPad, it does seem to do the right thing and keep the modal view centered if I rotate the iPad after showing the modal view.

bugloaf
  • 2,890
  • 3
  • 30
  • 49
  • 1
    great, but which method of the parentview is called when such a view dismisses? the parent´s view viewdidappear for example will not be called.. – user944351 May 23 '12 at 09:43
  • This worked well for me. Best solution I've seen for custom sized modal views. Too bad you can't do it with segues (as far as I can gather. I experimented some). – Philippe Sabourin Dec 17 '12 at 21:25
  • Hi bugloaf, I did the same and it works fine for ViewControllers alone but for ViewControllers with navigation not so. Please answer my question @ http://stackoverflow.com/questions/15802633/presenting-a-view-controller-of-custom-size-with-navigation – Satheesh Apr 04 '13 at 05:16