I have an application with 3 view controllers. They are all have shouldAutoRotateToInterfaceOrientation returning YES. The first two, my main menu and my submenu both autorotate just fine. The third viewcontroller, which programatically loads a UIImageView from a jpg file in the program's bundle, will only display in portrait.
In the viewcontroller containing the image, i have this:
NSString *imageName = [NSString stringWithFormat:#"%#-00%d.jpg",setPrefix,imageNumber];
UIImageView *pictureView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]];
pictureView.frame = CGRectMake(0, 0, 1024, 768);
[self.view addSubview:pictureView];
and again, I have shouldAutoRotateToInterfaceOrientation returning YES for all orientations.
My image shows up, but is sideways, and the 0,0,1024,768 values I used to make my rectangle start from the top right corner going down, instead of starting at the top left and going across (holding in landscape). Am I missing a parameter I need to set in order to ensure the imageview shows up in landscape instead of portrait?
I don't know for sure, but I suspect the setting of pictureView.frame may not be correct. The frame can be "weird" (technical term) when adding a subview to an autorotated view. See Automatically Sizing UIView after Adding to Window.
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 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)
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...
I am experiencing some weird behavior with my iPad app. I usually add a view to my viewController like this:
CGRect bounds = [[UIScreen mainScreen] applicationFrame];
// Add Basic View
UIView *myView = [[UIView alloc] initWithFrame:bounds];
myView.backgroundColor = [UIColor blackColor];
self.view = myView;
[myView release];
On the iPhone this always works like a charm. On my iPad app however, I add a toolbar to this self.view as a subview with the rectangle (0, 0, self.view.frame.width, 100). Sometimes this works out well and the toolbar displays right below the status bar, yet in certain conditions (eg. when the iPad is lying flat on a table and the interface orientation is portrait) my toolbar slides partly below the status bar. Yet as soon as I rotate the device everything is fine again and the toolbar is aligned properly with the status bar.
I have tried some workarounds with adding values a few points to the origin.y property of the toolbar, yet when I do this the toolbar gets an offset to the status bar after rotating the device. I am really confused by this, did anybody else ever experience this problem? If so, how did you fix it?
Thanks a lot!
I have an application where a UIToolBar is to be constantly on the bottom side of the screen. No matter the device orientation.
The toolbar must have the same screen width and always be justified to the bottom side.
If the device rotates, the toolbar has to assume the new width and continue to be justified on the bottom.
Is there a way to do that programmatically?
thanks for any help.
First off, auto-rotation can be a little tricky. For example, if you are using a UITabBarController, you will need to subclass it and add the appropriate delegate methods. You should read up on auto-rotation via the Apple docs and Google, before really diving in.
To answer your question specifically though, here is how you would need to declare the UIToolbar such that it will auto-rotate when you have the app set up to do so:
// I keep this definition in a file called constants.h since I use it a lot
#define SCREEN_FRAME [[UIScreen mainScreen] applicationFrame]
UIToolbar *tb = [[[UIToolbar alloc]init]autorelease];
// this frame will position a toolbar at the bottom of the screen
tb.frame = CGRectMake(0,
SCREEN_FRAME.size.height-tb.frame.size.height,
SCREEN_FRAME.size.width,
tb.frame.size.height);
//Setting the auto-resizing mask will make the toolbar resize when the viewController
//it resides in rotates.
tb.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Yes. Have a look at autoresizing masks.
Use a navigation controller, and make use of the toolbarItems property.