Problems with rotation in landscape and portrait view - iphone

In my application I have 2 views, portraitView and landScapeView. And also my application consists of many views...
When I launch the application both landscape and portrait view is getting displayed side by side.
When I launch the application in landscapeview the portraitview is getting displayed..later after rotating and coming back the view is getting proper.
The code I am using is given below...so please suggest me what all changes should be done to overcome above problem as mentioned..
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
NSLog(#"LANDSCAPE>>");
portraitView.hidden = YES;
landscapeView.hidden = NO;
UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"bg-ic_landscape.jpg"]];
self.view.backgroundColor = background;
}
else if (interfaceOrientation == UIInterfaceOrientationLandscapeRight){
NSLog(#"LANDSCAPE<<");
portraitView.hidden = YES;
landscapeView.hidden = NO;
UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"bg-ic_landscape.jpg"]];
self.view.backgroundColor = background;
self.view.hidden = NO;
}
else{
portraitView.hidden = NO;
landscapeView.hidden = YES;
NSLog(#"Portrait");
UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"bg-ic.jpg"]];
self.view.backgroundColor = background;
background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"bg-ic2.jpg"]];
self.view.backgroundColor = background;
}
return YES;

It sounds like your portraitView and landscapeView are both visible on initial launch of the app. The code above is only executed when the orientation changes during runtime. If you do insist on using separate views for portrait and landscape then you'll need to detect orientation at launch as well and show / hide the views appropriately.

The fact that the system calls shouldAutorotateToInterfaceOrientation: doesn't mean that it will do so there and then. You want to be using willRotateToInterfaceOrientation and didRotateFromInterfaceOrientation, and use autosizing as much as possible. You can also subclass the layout update callback to re-arrange your view. Having two view and showing/hiding them for landscape/portrait is not recommended.

Related

adding subView to the UINavigationBar and removing it

I am trying to create a custom look of my UINavigationBar. When the user puts the app in landscape, the navigationBar should be covered with an Image. When rotated back to portrait I want the View(Image) removed. Everything works fine with the code below except removing it. I can remove the View if I put the code in the same if-statement, but nothing happens if I put it in the else if-statement. Have I missed something ? / Regards
- (void) adjustViewsForOrientation:(UIInterfaceOrientation) orientation {
UIView *v = [[UIView alloc]init];
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
v.frame = CGRectMake(0,0,480,44);
v.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"navbar25g.png"]];
[self.view addSubview:v];
//[v removeFromSuperview]; <----- works if I put it here
NSLog(#"LANDSCAPE");//load the landscape view
}
else if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
[v removeFromSuperview]; <----- Not working
NSLog(#"PORTRAIT"); //load the portrait view
}
}
the reason that you cannot remove it is every time you go into the method you create a new instance of the UIView *v.
Create an instance variable then assign the view to that. Once it is assigned you can then remove or add as needed.
If you do not want to use an instance variable then you can give the view a tag i.e.
UIView *v = nil;
v = [self.view viewForTag:1000];
if (!v) {
v = [[UIView alloc] init];
v.tag = 1000;
v.frame = CGRectMake(0, 0, 480, 44);
v.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"navbar25g.png"]];
}
Now you can do your adding and removing for it.
Have you tried UIAppearance?
[[UINavigationBar appearance] setBackgroundImage:nil barMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setBackgroundImage:image barMetrics:UIBarMetricsLandscapePhone];

Custom SectionHeaderView in landscape persisting in portrait view after rotation

I'm using a custom sectionheader class with a tableview, and getting some unexpected behavior after rotation. Here's the use case:
Tap on cell in UITableView
View pushed onto stack.
Rotate the view to landscape.
Rotate back to portrait.
Pop the view.
On the iPhone 3G only, a landscape-sized section header now appears stuck somewhere down the middle of the view (in addition to the portrait-sized section header, which appears, as it should, at the top of the tableview). The extraneous header scrolls with the UITableView cells, and switching away from and back to the view (the UITableView is nested within a UITabBarController) doesn't fix the problem.
I can't reproduce this problem on the iPhone 4, or in the Simulator. It seems that, for some reason, a landscape oriented sectionheaderview is being added to the uitableview after popping the second level view, but why would this be? Note that the same problem is reproduced when the default (and not a custom) header is used. I've also checked whether it's a problem with device orientation being returned incorrectly, and that does not appear to be the case.
Here's the init code for the custom SectionHeaderView class, if it's helpful:
-(id)initWithFrame:(CGRect)frame title:(NSString*)title delegate:(id <SectionHeaderViewDelegate>)aDelegate {
self = [super initWithFrame:frame];
if (self != nil) {
float lineHeight = 0.5f;
// check line sizing for retina/non-retina
if (![Utilities hasRetina])
{
lineHeight = 1.0f;
}
// Set up the tap gesture recognizer.
delegate = aDelegate;
// Create and configure the title label.
CGRect titleLabelFrame = self.bounds;
titleLabelFrame.origin.y -= 12.5;
titleLabel = [[UILabel alloc] initWithFrame:titleLabelFrame];
titleLabel.text = title;
titleLabel.textAlignment = UITextAlignmentCenter;
titleLabel.font = [UIFont fontWithName:#"Georgia" size:15.0];
titleLabel.textColor = [UIColor whiteColor];
titleLabel.backgroundColor = [UIColor clearColor];
[self addSubview:titleLabel];
// add thin white line to top of section header
UIView *topBorder = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.bounds.size.width, lineHeight)];
[topBorder setBackgroundColor:[UIColor whiteColor]];
[self addSubview:topBorder];
[topBorder release];
// Set the colors for the gradient layer.
static NSMutableArray *colors = nil;
if (colors == nil) {
colors = [[NSMutableArray alloc] initWithCapacity:3];
UIColor *color = nil;
color = [UIColor colorWithRed:57.0/255.0 green:56.0/255.0 blue:105.0/255.0 alpha:1.0];
[colors addObject:(id)[color CGColor]];
color = [UIColor colorWithRed:54.0/255.0 green:53.0/255.0 blue:95.0/255.0 alpha:1.0];
[colors addObject:(id)[color CGColor]];
color = [UIColor colorWithRed:57.0/255.0 green:56.0/255.0 blue:105.0/255.0 alpha:1.0];
[colors addObject:(id)[color CGColor]];
}
[(CAGradientLayer *)self.layer setColors:colors];
[(CAGradientLayer *)self.layer setLocations:[NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:0.48], [NSNumber numberWithFloat:1.0], nil]];
}
return self;
}
Why would an additional landscape version of the custom SectionHeaderView be added in the portrait view, only on the iPhone 3G?
Thanks in advance for any help.
Still no clue what's causing this problem, but I eventually solved it by adding a check in viewWillAppear to make sure the old header was removed.

UITableView background color does not change

In a model UIViewController I have the following implementation of loadView (everything is created programmatically):
- (void)loadView {
// Add Basic View
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 540, 620)];
myView.backgroundColor = [UIColor clearColor];
self.view = myView;
[myView release];
// Add NavigationBar
// Add a BG image
// Add Table
UITableView *tbView = [[UITableView alloc] initWithFrame:CGRectMake(30, 80, 480, 250) style:UITableViewStyleGrouped];
tbView.dataSource = self;
tbView.delegate = self;
tbView.scrollEnabled = NO;
tbView.backgroundColor = [UIColor clearColor];
[tbView reloadData];
[self.view addSubview:tbView];
[tbView release];
// some more code
}
As you can see I set backgroundColor to clearColor, yet when I compile and run the code I always see a gray background behind the table:
I don't understand what I am doing wrong (sounds stupid, I know), I used to have the very same code and it worked perfectly fine. I am compiling with iOS SDK 4.2.1
You also need to set your UITableView's backgroundView property to nil on recent (since 3.2) versions of iOS.
As such, adding...
tbView.backgroundView = nil;
...should sort your problems.
That said, if you want to maintain compatibilty with pre-3.2 devices, you should check for the existence of this via the instancesRespondToSelector method before calling it.
Make sure you have the following 3 options set:
tbView.opaque = NO;
tbView.backgroundColor = [UIColor clearColor];
tbView.backgroundView = nil;
try
tbView.backgroundView = nil;
I tried to change from storyboard.
It works fine in
tbView.backgroundColor = .white

How do I rotate custom splash screen on iOS?

My splash screen is working, but my app works on landscape mode, and the splash screen shows in the default portrait mode.
How can I start the app so that the splash screen rotates between landscape modes like my app?
I'm using the following code:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight)
return YES;
else {
return NO; }
}
and for the splash screen
-(void)displayScreen {
UIViewController *displayViewController=[[UIViewController alloc] init];
displayViewController.view = displaySplashScreen;
[self presentModalViewController:displayViewController animated:NO];
[self performSelector:#selector(removeScreen) withObject:nil afterDelay:3.0];
}
-(void)removeScreen
{ [[self modalViewController] dismissModalViewControllerAnimated:YES];
}
But how can I put the rotate inside the display screen?
Aha. If you want to display your own splash screen, you should create a special view controller for that, which you already did. I think you can simplify the autorotation query code:
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) foo
{
return YES; // all interface orientations supported
}
Now you have to think about the splash screens for different orientations. Do you have a separate splash image for landscape and portrait? If yes, you can do something like this:
- (UIView*) startupImageWithOrientation: (UIInterfaceOrientation) io
{
UIImage *img = [UIImage imageNamed:[NSString
stringWithFormat:#"Default-%#.png", UIInterfaceOrientationName(io)]];
UIView *view = [[UIImageView alloc] initWithImage:img];
[view setFrame:[[UIScreen mainScreen] applicationFrame]];
return [view autorelease];
}
- (void) loadView
{
self.view = [self startupImageWithOrientation:self.interfaceOrientation];
}
- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) io
duration: (NSTimeInterval) duration
{
self.view = [self startupImageWithOrientation:io];
self.view.transform = CGAffineTransformFromUIOrientation(io);
}
There are two utility functions called, you can stuff these into a separate file:
NSString *UIInterfaceOrientationName(UIInterfaceOrientation io)
{
return UIInterfaceOrientationIsPortrait(io) ? #"Portrait" : #"Landscape";
}
CGAffineTransform CGAffineTransformFromUIOrientation(UIInterfaceOrientation io)
{
assert(io <= 4);
// unknown, portrait, portrait u/d, landscape L, landscape R
static float angles[] = {0, 0, M_PI, M_PI/2, -M_PI/2};
return CGAffineTransformMakeRotation(angles[io]);
}
It’s a bit messy, I’d be interested in simpler solution myself.
#zoul - loving this solution so far. however, if/when that view has any subviews - they don't show up. any ideas?
update:
fixed this issue by adding a subview to the UIView created in -startupImageWithOrientation: not self.view.
- (UIView *)startupImageWithOrientation:(UIInterfaceOrientation)io{
UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:#"Default-%#.png", UIInterfaceOrientationName(io)]];
UIView *aView = [[UIImageView alloc] initWithImage:img];
[aView setFrame:[[UIScreen mainScreen] applicationFrame]];
// define the version number label
self.versionNumberLabel_iPadSplashScreen.text = [NSString stringWithFormat:#"Version %#",
[[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"]];
[aView addSubview:self.versionNumberLabel_iPadSplashScreen];
return [aView autorelease];
}
The resolution of your defult.png can effect your apps orientation if you have locked orientations.
For example if a 1024x768 splash image is used and the initial view doesn’t support portrait viewing through orientation locks this can cause visual UI objects to appear off screen (especially when animation is involved) as the view will try and present itself in a portrait configuration even though the device may be in landscape.
Generally, 1024x768 images imply portrait while 768x1024 images imply landscape.
If this isn't enough, or your wanting to seamlessly go from the initial default image into e.g a login screen, then you can use a viewcontroller to 'continue' the splash .
Load all the normal viewControllers into the window, then put your 'splash' viewController in then in your splashController use shouldAutorotateToInterfaceOrientation method to set the right image (on an ImageViewController):
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
switch ([[UIDevice currentDevice] orientation])
{
case UIInterfaceOrientationLandscapeRight:
splashImage.image = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"Default"] ofType:#"png"]];
break;
case UIInterfaceOrientationPortrait:
splashImage.image = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"Default"] ofType:#"png"]];
break;
default:
splashImage.image = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"Default2"] ofType:#"png"]];
break;
}
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
The configuration of the images i have used may not suit you, so some experimentation might be needed.
- (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if (toInterfaceOrientation == UIInterfaceOrientationPortrait)
{
// take action here , when phone is "Portrait"
}
else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft)
{
action 4 LandscapeLeft
}
else if (toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
//PortraitUpsideDown
}
else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
//LandscapeRight
}
note that you should return YES the method shouldAutorotateToInterfaceOrientation:

How to autoresize the subviews for screen orientations in iPhone programmatically?

I have created a UIViewController class with a background color as red.
I have also created a UIView which is a subview and placed with a background image and two UIButtons on them.
The coding which i give for screen orientation is
-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
self.view =[[UIView alloc] initWithFrame:CGRectMake(0,0,320,480)];
self.view.backgroundcolor =[UIColor redColor];
UIView *subview;
subview = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,480)];
subview.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#""]];
subview.autoresizingMask = UIViewAutoResizingFlexibleWidth |UIViewAutoresizingFlexibleHeight;
Problem:
When i turn into Landscape the subview is resized with the image, but the buttons remain in the same position and i am not using any .xib file.I have created the project programmatically.Please do reply....
Override layoutSubviews for your class. You might need to explicitly call [self setNeedsLayout] from didRotateFromInterfaceOrientation