HI I am developing an iOS Universal application for both orientation Portrait and Landscape
I am using following code for adjusting my UI according to orientation change
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(deviceOrientationDidChange:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
- (void)deviceOrientationDidChange:(NSNotification *)notification
{
[self changeTheOrientation];
}
- (void)changeTheOrientation
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
if ( UIDeviceOrientationIsPortrait(orientation))
{
//For Portrait set frame size
lblBookInfo.frame = CGRectMake (0, 20, 718, 50);
btnClose.frame = CGRectMake (718, 20, 50, 50);
}
else if (UIDeviceOrientationIsLandscape(orientation))
{
//For Landscape set frame size
lblBookInfo.frame = CGRectMake (0, 20, 974, 50);
btnClose.frame = CGRectMake (974, 20, 50, 50);
}
}
else
{
if (UIDeviceOrientationIsPortrait(orientation))
{
//For Portrait set frame size
lblBookInfo.frame = CGRectMake (0, 20, 290, 30);
btnClose.frame = CGRectMake (290, 20, 30, 30);
}
else if (UIDeviceOrientationIsLandscape(orientation))
{
//For Landscape set frame size
if ( [[UIScreen mainScreen] bounds].size.height==568 ) {
} else {
}
}
}
}
The basic code structure which I am using for handling different UI frame with change in orientation is above.
But the problem which i am facing is that the UIDeviceOrientationDidChangeNotification is not fired every time , I think it gets missed for some times , I have checked this by setting proper breakpoints , this problem makes look my Ui really bad as sometimes UI do not change accordingly to the frame.
This approach works properly for some initial UI changes but get failed after some (10-20)orientation changes.
Is it the correct approach which I am using or is there any better approach to handle different orientations in iOS
I am developing app for (iOS 6 and iOS 7).
Use the following code to detect orientation in the callback for the UIDeviceOrientationDidChangeNotification -
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
Then to detect if it is landscape or portairt you can -
if (UIDeviceOrientationIsLandscape(deviceOrientation) {
//do landscape related view changes
} else if (UIDeviceOrientationIsPortrait(deviceOrientation) {
//do portrait related view changes
}
I have seen this line being added before registering for orientation change notifications. Usually in awakeFromNib method -
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
Then register for notifications -
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(deviceOrientationDidChange:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
Related
I have an iOS app. It works great.
Except when the user has a hotspot on or is in a call but the call app is minimised
The extended height of the status bar pushes my ui down, making part of it disappear,
at the bottom.
I want this extended bar to overlay the top of the screen and not push the ui downwards.
How do I achieve that ?
The Simplest Solution is to make sure that your view's springs-and-struts or Autolayout properties allow for compression or expansion of the view , If you have some complex UI then you can implement UIApplicationWillChangeStatusBarFrameNotification observer.
You can handle the UIApplicationWillChangeStatusBarFrameNotification and UIApplicationDidChangeStatusBarOrientationNotification notifications which will tell you the new size of the status bar.
If you are intent on using a transform on your view to handle resizing, you can implement -viewWillLayoutSubviews in your view controllers (probably in a common base class) to set a transform on the root view of the view controller.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(statusFrameChanged:)
name:UIApplicationWillChangeStatusBarFrameNotification
object:nil];
}
-(void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationWillChangeStatusBarFrameNotification
object:nil];
}
- (void)statusFrameChanged:(NSNotification*)note
{
CGRect statusBarFrame = [note.userInfo[UIApplicationStatusBarFrameUserInfoKey] CGRectValue];
CGFloat statusHeight = statusBarFrame.size.height;
UIScreen *screen = [UIScreen mainScreen];
CGRect viewRect = screen.bounds;
viewRect.size.height -= statusHeight;
viewRect.origin.y = statusHeight;
self.view.frame = viewRect;
[self.view setNeedsLayout];
}
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
CGRect baseFrame = self.view.frame;
// 548.0 is the full height of the view. Update as necessary.
CGFloat scale = self.view.frame.size.height / 548.0;
[self.view setTransform:CGAffineTransformMakeScale(1.0, scale)];
self.view.frame = baseFrame;
}
I used use "Vertical space - Bottom layout Guide - Button". This way, a button I have on the bottom of the screen stays in the same place when there is an in call bar and if a different screen size is used (3.5inch or 4icnh).
I have an iOS app. It works great.
Except when the user has a hotspot on or is in a call but the call app is minimised
The extended height of the status bar pushes my ui down, making part of it disappear,
at the bottom.
I want this extended bar to overlay the top of the screen and not push the ui downwards.
How do I achieve that ?
The Simplest Solution is to make sure that your view's springs-and-struts or Autolayout properties allow for compression or expansion of the view , If you have some complex UI then you can implement UIApplicationWillChangeStatusBarFrameNotification observer.
You can handle the UIApplicationWillChangeStatusBarFrameNotification and UIApplicationDidChangeStatusBarOrientationNotification notifications which will tell you the new size of the status bar.
If you are intent on using a transform on your view to handle resizing, you can implement -viewWillLayoutSubviews in your view controllers (probably in a common base class) to set a transform on the root view of the view controller.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(statusFrameChanged:)
name:UIApplicationWillChangeStatusBarFrameNotification
object:nil];
}
-(void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationWillChangeStatusBarFrameNotification
object:nil];
}
- (void)statusFrameChanged:(NSNotification*)note
{
CGRect statusBarFrame = [note.userInfo[UIApplicationStatusBarFrameUserInfoKey] CGRectValue];
CGFloat statusHeight = statusBarFrame.size.height;
UIScreen *screen = [UIScreen mainScreen];
CGRect viewRect = screen.bounds;
viewRect.size.height -= statusHeight;
viewRect.origin.y = statusHeight;
self.view.frame = viewRect;
[self.view setNeedsLayout];
}
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
CGRect baseFrame = self.view.frame;
// 548.0 is the full height of the view. Update as necessary.
CGFloat scale = self.view.frame.size.height / 548.0;
[self.view setTransform:CGAffineTransformMakeScale(1.0, scale)];
self.view.frame = baseFrame;
}
I used use "Vertical space - Bottom layout Guide - Button". This way, a button I have on the bottom of the screen stays in the same place when there is an in call bar and if a different screen size is used (3.5inch or 4icnh).
I have a UITextView that in portrait sizes 500px width.
I add it by code as subview but i can't be able in viewdidapper to get the correct size if the app is opened in landscape mode.
After the device rotation it works right. If opened landscape no.
How can i calculate the correct dimension of this textview when opening landscape?
Thank you
Add a notifier in the viewWillAppear function
-(void)viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
The orientation change notifies this function
- (void)orientationChanged:(NSNotification *)notification{
[self adjustViewsForOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
}
and you calculate the size of your textView
- (void) adjustViewsForOrientation:(UIInterfaceOrientation) orientation {
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
//calculate the portrait textView size
}
else if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
//calculate the landscape textView size
}}
i hope this help
Here is the problem I've been struggling with:
I'm creating a view programatically using loadView.
Once it's loaded it looks just great in Portrait view. However, I want to handle rotation of the device. Therefore I use willAnimateRotationToInterfaceOrientation method.
Within this method I call a function that adjust all the elements. What that function does is just goes through all my views and sets new CGRect to each of them. It works just fine on portrait orientations (up and upside-down), but once I change orientation to horizontal, it crops.
Two questions:
What is the most likely reason for such behavior?
How would you suggest handling device rotation without creating a separate view for horisontal / vertical orientations?
I think you are missing the key part. When you are setting the frame at portrait view at view did load, view got the frame but when it change to the landscape it change but again from there i think you are not setting the frame for portrait view. use notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
-(void) orientationChanged:(NSNotification *)notification
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
UIDeviceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if((orientation == UIDeviceOrientationPortrait) || (orientation == UIDeviceOrientationPortraitUpsideDown)) {
// set frame here
}else if ((orientation == UIDeviceOrientationLandscapeLeft) || (orientation == UIDeviceOrientationLandscapeRight)){
// set frame here too
}
}];
}
I am building a template app. I am having some issues with the device rotation/orientation. I have the following in my appDelegate didFinishLaunching:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
and in my VC viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
...
//add the title bar
titleBar = [[OAI_TitleBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 1024.0, 50.0)];
titleBar.titleBarTitle = #"OAI Template";
titleBar.hasAccount = YES;
titleBar.hasReset = YES;
titleBar.hasHome = YES;
[titleBar buildTitleBar];
[self.view addSubview:titleBar];
This is my deviceOrientationDidChange method:
//rotate the vc view
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
[self.view setFrame:CGRectMake(0.0, 0.0, 1024.0, 768.0)];
} else if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)) {
[self.view setFrame:CGRectMake(0.0, 0.0, 768.0, 1024.0)];
}
//call the rotation management methods of various classes
[titleBar adjustForRotation:orientation];
}
This works fine when I rotate the device, the views adjust as expected. But when the app launches, the x,y coordinates are wrong - when I log the frame when launching in portrait orientation, the VC view's frame is {{0, 20}, {768, 1004}}, when launching in landscape mode it is {{20, 0}, {748, 1024}}
The titlebar frame is {{20, 0}, {748, 1024}} for landscape and portrait (which is as I coded it).
However, what I am seeing in the simulator and on my device is drastically different. What you should see is a black bar (50 pixels or so in height) at the top with a logo on the left, followed by some buttons and then the app title aligned right. As you can see from the images below, when the app launches in either orientation it's opening x/y coords are no where near 0/20. Any help would be appreciated.
What it looks like to me is that when the app launches in landscape it is being displayed as portrait and when it launches as portrait, though the display is right, it is off by about 20.0f or so. Any help would be appreciated.
Solved it, I
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight;
}
in my viewController, made sure the correct orientations were in my plist and it loads fine.