my UIPopOverController loses its content sometimes, when being rotated (not reproducable) or if for example I open some content from a tableview in landscape, rotate the device to portrait and then open the same content in portrait.
The Popovercontroller is displayed but no content is visible i.e. it is black.... has anyone stumbled upon this or anything similar?
I encountered similar problems when using UIPopoverController after rotation occurred (UIPopoverController's size changed strangely, it repositioned itself to strange places in screen etc).
The trick that worked for me was to overload the UIViewController's didRotateFromOrientation:(UIInterfaceOrientation) method in the app. So overload the method from your app's UIViewController class that is being displayed when UIPopoverController is displayed and call UIPopoverController's presentPopoverFromRect: method again from there:
-(void) didRotateFromOrientation:(UIInterfaceOrientation)uiOrientation {
if (popoverController.popoverVisible) {
// Define rect to be the UI component's rect where you want to tie the popoverController
CGRect rect = CGRectMake(...);
// This method will reposition the popover correctly
[popoverController presentPopoverFromRect:rect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:NO];
}
}
Note that if you are tying UIPopoverController to UIBarButtonItem using UIPopoverController's presentPopoverFromBarButtonItem: method, the system should then automatically take care of positioning the popover correctly after the rotation.
Related
Probably a bit of a newbie question, but .... I am writing an iPhone app which uses UITabBarController.
In Interface Builder I've setup the tab bar in MainWindow.xib. I have 4 tabs, and each one is set to load the xib for the appropriate UIViewController subclass. I have created the views in the xib files for each UIViewController subclass in Interface Builder.
All is working well in that I can tap each tab and it shows the view for the correct UIViewController
But what I really want is for the view for one of the UIViewController subclasses to have a semi-transparent border of approx 30px on all 4 edges, so that it shows the edges of the view behind, kind of greyed out.
IE. the first tab is the main application, and that takes up the whole screen (minus the status and tab bar areas).Tab 2 is to save, and I want it to look like a small modal window over the top of the main app.
(If I were doing this as a html web app, the terminology and technology I'd be using would be a jQuery overlay)
Does this make sense?
I've tried playing with presentModalViewController but this makes it worse in that it takes up the entire screen including the status and tab bar areas.
Any help or pointers very much appreciated
Cheers
Nathan
Your UIViewController cannot be transparent to the view below it because the iphone may unload the view below it that is not currently being shown (to save memory).
The best solution I have used is to take a picture of the current view before you push your new view controller and then use that as the background image (fake the transparency). Here's how I implemented this:
NewViewController *newView = [[NewViewController alloc] init];
shareVC.imageBackground = [Utilities getScreenshot:self.view];
[self presentModalViewController:newView animated:YES];
[newView release];
then on your newViewController do this (on viewDidLoad, viewWillAppear, etc):
[imageView setImage:imageBackground];
and here's the screenshot function
+(UIImage *)getScreenshot:(UIView *)_view {
//take a screenshow of the parent view so we can add it as a background to the modal view
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
UIGraphicsBeginImageContextWithOptions(_view.window.bounds.size, NO, [UIScreen mainScreen].scale);
else
UIGraphicsBeginImageContext(_view.window.bounds.size);
[_view.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
You then need to setup your new view with a UIImageView as the background and pick the right Alpha value for that imageView to make it appear like it's transparent.
I'm having problems making my app iPad compatible.
I have an implementation of a custom Tab Bar, based on the post here http://www.wiredbob.com/blog/2009/4/20/iphone-tweetie-style-navigation-framework.html
That all works fine apart from when the device is rotated. The currently selected view rotates and resizes perfectly. Every other view rotates but does not resize to fill the space. There is a large white column down the right hand side.
I've tried adding
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.view.autoresizesSubviews = YES;
to the tab controller view.
I've added similar code to the tab's views viewDidLoad methods.
I've tried to make the willRotateToInterfaceOrientation call all the subviews rotation methods but still no luck.
Any suggestions would be more than welcome at this stage. I'm hoping i'm not overlooking something obvious but i might be. I've been at it for a few hours now
Screenshot 1 -
Screenshot
Ok I Solved this problem.
What I had to do was manually call a resize on all the sub views. - i added a changeFrameSize function to each sub view (just so it made the code look a little nicer)
Oh and when adding views as sub views always use belowSubView method -
[self.view insertSubview:viewController.view belowSubview:tabBar];
-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[(ViewControllerClass *)[viewControllers objectAtIndex:0] changeFrameSize:[NSNumber numberWithFloat:self.selectedViewController.view.bounds.size.width] height:[NSNumber numberWithFloat:self.selectedViewController.view.bounds.size.height]];
[(ViewControllerClass *)[viewControllers objectAtIndex:1] changeFrameSize:[NSNumber numberWithFloat:self.selectedViewController.view.bounds.size.width] height:[NSNumber numberWithFloat:self.selectedViewController.view.bounds.size.height]];
[(ViewControllerClass *)[viewControllers objectAtIndex:2] changeFrameSize:[NSNumber numberWithFloat:self.selectedViewController.view.bounds.size.width] height:[NSNumber numberWithFloat:self.selectedViewController.view.bounds.size.height]];
}
So because the selected view controller was always rotated and resized to the correct size, once it had rotated and adjusted i simply passed the same parameters to the sub views so they would resize too.
I have an UIViewController that has two UIViews inside, whose layout (set in Interface Builder) is something like this (the magenta colored view is the UIViewController default view):
and I added the main view to a root view obtaining this effect (by not showing the darker view placing its frame at the bottom):
Now when the device rotates, what I obtain is this:
whereas I'd like to still hide the darker view.
This is the code I use to hide it when it appears (I use it in the viewDidLoad method):
- (void)hideAll:(float)time{
CGRect hiddenFrame = CGRectMake(0, 1024, self.view.frame.size.width, self.view.frame.size.height);
[self.view setFrame:hiddenFrame];
[self.view setNeedsDisplay];
}
and it appears to work, but when I call a variant of it when rotating (in willRotateToInterfaceOrientation:duration:), nothing happens:
CGRect hiddenFrame = CGRectMake(0, 748, self.view.frame.size.width, self.view.frame.size.height);
[self.view setFrame:hiddenFrame];
[self.view setNeedsDisplay];
What am I missing? have I to set some other view property in Interface Builder?
UPDATE
It seems to me that the coordinate system does not change after the device has been rotated (ie the origin set in the upper-left corner in portrait mode will become the upper-right after a clockwise rotation in landscape mode)
Check your struts and springs in IB. It maybe that when you autorotate, the strut fixing you to the top of the screen moves your frame back to the top.
Try adding your code to the didRotateToInterfaceOrientation method so it can run after rotation has occurred.
Why to you change the frame to hide it, and not just
[self.view setHidden:YES];
second thing is that you should try to set the "Autoresizing" panel to handle the orientation changes, and not by changing the frame of the view.
hope i understood you right.
shani
The problem I encountered can be faced in two ways (I hope this can save some time for someone in the future):
using an UIViewcontroller (loaded from xib) and only its view as the rotating view, that is my original attempt to solve it. In this case you have to programmatically set the frame for the view when you want to hide it, and by doing so you have to consider that the coordinate system for the controller remains untouched and does not rotate (ie. it is always originated from the same corner)
using a UIView (loaded from xib) inside an already existing UIViewcontroller, in this way the view will automatically rotate and resize and you will not have to take the proper coordinates value into account at each rotation (this is by far the simplest way)
I have an iPad app that is set to start in landscape mode.
From what I read, the UIWindow itself doesn't need to be rotated, instead it will apply a rotation transform to all of it's subviews when the device is rotated.
My application has a UINavigationController which has the app's views, and above it a custom MenuBarViewController which will show sometimes on one edge of the screen.
In my app delegate's didFinishLaunching.. I do:
[window addSubview:navigationController.view];
[window addSubview:menuBarWrapperViewController.view];
[window bringSubviewToFront:menuBarWrapperViewController.view];
The views within my navigationController seem to be fine, however the view in my MenuBarViewController are not rotated.
I've checked, and both my MenuBarViewController and my MenuBarWrapperViewController (which doesn't do anything yet) return YES to shouldAutorotate..
Does anyone have any idea why one of my UIViews subviews doesn't get the correct rotation transform?
EDIT: upon further investigation, it seems that UIWindow only applies the transform to the first added subview, so if I change the order of addSubview calls, only the first subview will be rotated.
Does anyone know why?
Perhaps you should try having one view controller be in charge of handling all rotations of all subviews being displayed.
In my iPhone app, I have a UIViewController with two subviews: a main UIView (let's call it mainView), and a secondary UIView (let's call it secondView), which is usually hidden but is sometimes shown (e.g. user settings). In my UIViewController, self.view is set to mainView. When the user switches to the subview, I call [self.view addSubview:secondView] and when the user switches back to the main UIView, I call [secondView removeFromSuperview].
There are two issues which I am dealing with at present:
When the user rotates the iPhone or iPad, the main UIView (mainView) autorotates properly and all of its UI items follow its autoresize rules which I have set up in Interface Builder. However, when the secondary UIView (secondView) is displayed, and the iPhone or iPad is rotated, the secondView & all of its UI items do not follow their autoresize rules. I have found that when I set self.view = secondView, and then rotate the device, the view rotates properly.
In the iPad specifically, when I pull up the secondView using [self.view addSubview:secondView], it is not resized to fill the full screen just as the main UIView has been resized for the iPad version. So I end up with a screen that displays the mainView UIView in the background, and the secondView UIView in the top-left corner without taking up the whole screen.
My instinct tells me that these two issues are related to one another. Has anyone else experienced these kinds of issues with secondary UIViews which they add to their UIViewControllers using addSubview:?
When using addSubview,
[secondView setFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
Not very elegant. But it worked for me:
I had a similar problem. I solved the size issue by setting the content mode of the view.
Exp:[_yourView setContentMode:UIViewContentModeScaleAspectFill];
I hope this helps...