Background:
My app was configured in portrait view by default, but for one scene the screen should be in landscape view only.
Question:
How to set the orientation manually with codes, in other words, users need not to rotate the device to generate an event to make the screen rotated.
PS:
I need a method like "setRequestedOrientation" in Android or I need to know how to construct a screen rotation event to send to the system.
Have you on the desired view controller tried
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
Another thing you can do is to change the orientation on the desired view controller from "Inferred" to "Landscape" in the Attributes inspector in your storyboard.
UIViewController Class Reference
Key:
Use CGAffineTransform CGAffineTransformMakeRotation(CGFloat angle) from CoreGraphics, which could make your view rotated
Sample Codes:
(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.view.transform = CGAffineTransformMakeRotation(M_PI/2);
self.view.frame = CGRectMake(0, 0, 480, 320);
}
Related
I have two different UI specs for my iOS app.
I'm facing issues in orientation change(Upsidedown not supporting) for following scenario.FYI :I'm using using self.view.frame.size.width to set width for UI and to identify orientation change i'm using UIDeviceOrientationDidChangeNotification1.Change orientation to landscape
2.change to orientation upsidedown (not settign any frame)
3.change orientation to portrait directly (setting frame for portrait mode)
On following these steps my UI frame is getting misplaced.I'm getting width as 568 for portrait mode.
Please suggest me a better way to fix this problem.
It is not good practice to change the self.view frame when rotating because its bound are handled by the UIViewController rotation logic.
You can use the willRotateToInterfaceOrientation:duration: and didRotateFromInterfaceOrientation: delegate methods for manual rotation.
you are listing to your device orientation changes and you need to allow UI rotation and listen to it with
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
//update your view's subviews
}
note that UIDeviceOrientation is different from UIInterfaceOrientation
to allow interface rotation add this to the view controller and make sure that in the project plist you are supporting the landscape and portrait in the 'Supported interface orientations' key
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
This topic has come up before (iPad modal view controller acting in portrait even though it's landscape) but I haven't found a clear answer - so I don't know if this is a duplicate or not.
In new single view project, I set the main view to landscape in xcode:
And the Property Inspector confirms this (as well as how the view is displayed in the storyboard):
And the ViewController orientation property is set to landscape:
Yet when I check the view frame in 'viewDidLoad' it reports portrait mode:
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect theRect = self.view.frame;
NSLog(#" frame %f %f %f %f", theRect.origin.x,
theRect.origin.y,
theRect.size.width,
theRect.size.height);
}
2012-08-26 16:42:45.045 Test[2320:f803] cell 0.000000 20.000000
768.000000 1004.000000
I also force landscape in shouldAutorotateToInterfaceOrientation:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
I've encountered this many times before and have had to set the frame explicitly to landscape but I have never understood why all the storyboard settings have no effect.
Am I missing something basic here?
Every application in iOS starts in portrait mode inititally, even if you specified the supported device orientations and give the right "answers" at shouldAutorotateToInterfaceOrientation:. It will always start in portrait and will the rotate to landscape if the device. The user maybe won't see it cause its so fast.
Because of this your app has to be able to rotate via shouldAutorotateToInterfaceOrientation even if your only supported orientations are landscape ones.
So to get a landscape orientation after start you should:
set the supported interface orientations in Xcodes Interface Builder
overide shouldAutorotateToInterfaceOrientation:
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)io {
return (io == UIInterfaceOrientationLandscapeRight);
}
give the interface a chance to rotate and do your view configuration afterwards
Regarding your question about the Xcode configuration of the the viewcontroller to landscape: Notice the title of the menu in the storyboard - it says: Simulated Metrics
This means that every modification you do there is just for the purpose to simulate it in the storyboard. But unless you do the necessary modifications to get to this state in the code it will have no effect.
Add below code in your view controller with swift 4.2
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .landscapeRight
}
What I tried so far is, in viewDidLoad, I called
self.bannerView.autoresizingMask=UIViewAutoresizingFlexibleWidth;
and
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)newInterfaceOrientation duration:(NSTimeInterval)duration {
if (newInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || newInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
self.bannerView.frame=CGRectMake(0.0,
0.0,
480.0,
GAD_SIZE_320x50.height);
}
// Position the UI elements for portrait mode
else {
self.bannerView.frame=CGRectMake(0.0,
0.0,
GAD_SIZE_320x50.width,
GAD_SIZE_320x50.height);
}
}
Both of these didn't work for me.
Hmm, I don't think that AdMob's creatives can stretch to fit the size of the screen when in landscape. So despite the fact that you're stretching the frame of the view to fit, the ad itself I think will stay the same size.
This means you should still see an ad come in on orientation changes, it will just look like it's the same size (make sure to make another request for an ad in the willAnimateRotationToInterfaceOrientation: method to see this).
You don't need to do any moves, but you must set correct rootViewController for adMovView.
If you use view controller model please add line in each custom view controller
adMobView.rootViewController = viewController;
where viewController - root view controller of your app.
Do not code like this
adMobView.rootViewController = self;
in custom view!
I am presenting a UIPopovercontroller using PresentPopOverFromRect: method. in Portrait Orientation. When i autorotate to Landscape UIPopoverController is not presenting at the proper position. How to position the UIPopoverController while autorotating the device.
You need to override this function:
- (void)willAnimateRotationToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
where you can change the dimension and position of the UIPopovercontroller depending of your current orientation. This function is convenient because it is called just before the screen is being redrawn and just before the user interface begins to rotate.
You should check this tutorial for an understanding of how you should handle the layout for different orientations of the IPad.
Yes, as tiguero says, in your custom UIViewController, you can override the method:
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[self.popOverViewController dismissPopoverAnimated:NO];
CGRect yourNewRect = CGRectMake(0.0, 0.0, 20, 20);
[self.popOverViewController presentPopoverFromRect:yourNewRect inView:yourView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
You can have a try!
The documentation says that if I want to support both portrait and landscape, I basically have two ways of doing that:
Set up the viewcontroller's view so that the subviews autoresize correctly and make smaller changes programmatically at runtime
If the changes are more substantial, create an alternative landscape interface and push/pop the alternative modal viewcontroller at runtime
I would like to present the info where the layout is substantially different, but logic is the same. Ideally, I would load another XIB for the same viewcontroller, but it does not seem to be an option.
Sounds like #2 is what I need to do, but my problem with that is that it sounds like it would use the standard modalviewcontroller animations that are nothing like the device rotation animation. (Of course, being the lazywebber that I am, I did not test this hypothesis.)
So, how do I load an alternative layout for landscape with the same viewcontroller but different XIB? Should I use the method #2 above and is the rotation animation natural? Or is there some other way?
I instantiate my UIView instances in -viewDidLoad: and add them as subviews to the view controller's view property:
- (void) viewDidLoad {
[super viewDidLoad];
self.myView = [[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 280.0f, 210.0f)] autorelease];
// ...
[self.view addSubview:myView];
}
I then call -viewWillAppear: to center those subviews:
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self adjustViewsForOrientation:[[UIDevice currentDevice] orientation]];
}
I also override -willRotateToInterfaceOrientation:duration:
- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)newInterfaceOrientation duration:(NSTimeInterval)duration {
[self adjustViewsForOrientation:newInterfaceOrientation];
}
The -adjustViewsForOrientation: method sets the center CGPoint of various subview objects, depending on the device's orientation:
- (void) adjustViewsForOrientation:(UIInterfaceOrientation)orientation {
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
myView.center = CGPointMake(235.0f, 42.0f);
// ...
}
else if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
myView.center = CGPointMake(160.0f, 52.0f);
// ...
}
}
When the view controller is loaded, the UIView instances are created and positioned based on the device's current orientation. If the device is subsequently rotated, the views are re-centered to new coordinates.
To make this smoother, one could probably use a keyed animation in -adjustViewsForOrientation:, so that the subviews more gracefully move from one center to the other. But the above works for me, for now.