I have a bit of a strange situation. I have a photo app that automatically sets the app orientation based upon the dimensions of the image loaded. I use the following code.
- (BOOL)prefersStatusBarHidden {
return YES;
}
- (BOOL) shouldAutorotate {
return NO;
}
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return NO;
}
- (IBAction)setRotation {
if(imageOriginal.size.height > imageOriginal.size.width){
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}else {
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
}
The problem is that lets say I load a portrait image into the app the UIImagePicker is in portrait mode. I now select a Landscape image and select the UIImagePicker again, instead of the picker now being in landscape mode it jumps back to portrait and looks pretty ugly.
Is there a better way to set the device orientation based upon the image or fix the problem above?
Found the solution needed to change the following code to make sure the UIImagePicker was in context.
- (IBAction)loadImage:(id)sender {
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
-- > imagePicker.modalPresentationStyle = UIModalPresentationCurrentContext;
//imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentViewController:imagePicker animated:NO completion:nil];
}
Related
I want to set device orientation to landscape mode programmatically to particular viewcontroller, its working well if I use with UIAlertController, with YES/NO option, but if I directly write the same code on button click. its not working.
working code with UIAlertController,
UIAlertController * alert=[UIAlertController
alertControllerWithTitle:APP_NAME message:#"Please Select Video Orientation."preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* yesButton = [UIAlertAction
actionWithTitle:#"Landscape Mode"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
[self.navigationController pushViewController:mySecondViewController animated:NO];
}];
UIAlertAction* noButton = [UIAlertAction
actionWithTitle:#"Portrait Mode"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
[self.navigationController pushViewController:mySecondViewController animated:NO];
}];
[alert addAction:yesButton];
[alert addAction:noButton];
[self presentViewController:alert animated:YES completion:nil];
The above code is working well, but i want to force next controller in landscape mode without asking with Alert, so directly write the code on button click like this,
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
[self.navigationController pushViewController:mySecondViewController animated:NO];
but this same code is not working well. it will open the mySecondViewController in portrait first and manually we have to tilt phone once then it will move into landscape.
I tried lot of option but no luck. Testing on iPhone5 and iPhone6 with iOS 10.1
Update: adding mySecondViewController code,
This is second view controller code,
-(void)viewWillAppear:(BOOL)animated{
self.navigationController.navigationBar.hidden = NO;
}
- (void)viewDidAppear:(BOOL)animated {
// [super viewDidAppear:animated];
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft|UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
-(BOOL)shouldAutorotate
{
return YES;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeLeft | UIInterfaceOrientationLandscapeRight;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}
Try this for force the view to launch in landscape mode in swift :
Use this code in viewWillAppear
let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(Int(value), forKey: "orientation")
and
override func shouldAutorotate() -> Bool {
return true
}
This is code for set orientation, but if you want for specific VC try this code in that VC class
[[UIDevice currentDevice] setValue:
[NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
forKey:#"orientation"];
It is an superclass file name Apporientationviewcontroller.h/m. And i am calling this super class in all other subclasses. So that if "isPortraitModeONN" is "ON"
then all the screen should work only in portrait mode. if user try to changes the device to landscape it should not rotate. it should be always in portrait mode if switch is "ON".. In my case while laughing the app it is in portrait mode. but if i rotate the screen it is changing towards landscape. but it should not change its orientation until turning OFF the switch in settings..
if(isPortraitModeONN)
{
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];
}
else
{
if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft){
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
}
else if([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight)
{
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft];
}
else{
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
}
}
This code works for me somewhat..
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator: (id<UIViewControllerTransitionCoordinator>)coordinator
{
///if isPortraitMode On then force the orientation to portrait if it's other than Portrait
///else force the orientation to landscape
if (isPortraitModeONN)
{
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
// do whatever
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (UIInterfaceOrientationIsLandscape(orientation)) {
///App is rotating to landscape, force it to portrait
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
}];
}
else{
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
// do whatever
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (UIInterfaceOrientationIsPortrait(orientation)) {
///App is rotating to portrait, force it to landscape
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
}];
}
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}
You can do like this-
Add - #property () BOOL isPortraitModeONN; in AppDelegate.h class.
Now code this in AppDelegate.m -
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.isPortraitModeONN=YES;
return YES;
}
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if(self.isPortraitModeONN)
return UIInterfaceOrientationMaskPortrait;
else
return UIInterfaceOrientationMaskLandscape;
}
Now Add IBAction of UIButton for changing orientation in Apporientationviewcontroller.m--
- (IBAction)changeOrientation:(id)sender {
if (allowedToRotate) {
allowedToRotate=NO;
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.isPortraitModeONN = NO;
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}else{
allowedToRotate=YES;
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.isPortraitModeONN = YES;
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
}
define in Apporientationviewcontroller.m BOOL allowedToRotate; default value is YES;
Goto Target -> Deployment info -> set device Orientation to portrait only
As par your question if you want to do this by tapping on button
Please try this code i am not sure about this it works on your project but it works for my dummy project
please try it
[[UIDevice currentDevice] setValue:
[NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
forKey:#"orientation"];
change the device orientation for both buttons
You code should be like this,
AppDelegate.h
#property () BOOL restrictRotation;
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window;
AppDelegate.m
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if(self.restrictRotation)
return UIInterfaceOrientationMaskLandscape; //you can change upsidedown etc
else
return UIInterfaceOrientationMaskPortrait; // you can change landscape right or left only
//this should be your initial app orientation because by default value of bool is false
}
SettingsViewController (from where you want to change whole app orientations)
-(void) restrictRotation:(BOOL) restriction
{
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.restrictRotation = restriction;
[appDelegate application:[UIApplication sharedApplication] supportedInterfaceOrientationsForWindow:self.view.window];
}
don't forget to import appdelegate.h ;)
And finally from your switch for changing orientation,
[self restrictRotation:YES]; // or NO
You can manipulate supportedInterfaceOrientationsForWindow as per requirement like you can set property as int instead of bool and can set multiple orientation for different int value.
hope this will help :)
I am trying to work on iOS app , one viewController portrait , one viewController using GoogleMap landscape orientation as follows :
When it comes to the implementation and testing, it shows :
I am not sure how it could be when running on iPhone 6 iOS 8.3 . it seems that setting device orientation and interface orientation are different parameters have to be set. I have
AppDelegate.m
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
ViewControllerA.m
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
ViewControllerB.m
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
isPresented = YES;
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
[[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeRight];
}
viewDidLoad ...
GMSMarker *marker = [[GMSMarker alloc] init];
NSLog(#"assadsd arrived map");
if(latitide!=0.00&&longitude!=0.00) {
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(latitide, longitude);
marker.position = CLLocationCoordinate2DMake(position.latitude, position.longitude);
camera = [GMSCameraPosition cameraWithLatitude:latitide longitude:longitude zoom:12];
}else{
camera = [GMSCameraPosition cameraWithLatitude:22.2855200 longitude:114.1576900 zoom:12];
marker.position = CLLocationCoordinate2DMake(22.2855200, 114.1576900);
}
self.myMapView = [GMSMapView mapWithFrame:self.view.bounds camera:camera];
Could you please tell me the know-how to work as the first picture does ? It seems that iOS 8.3 has some orientation bug that has to re-=assign the correct view width and height but I am not sure how exactly it could work.
If you are using NavigationController then create navigationController subclass and override the shouldAutorotate method.
My app is a portrait only. I need to present a UIViewController in Landscape mode(Reason for that is I am using Core-Plot sdk for drawing graphs on that viewcontroller, so it needs to be in landscape mode).
I tried the following methods and it work fine. But the issue is, when I dismiss the landscape viewcontroller, app cannot force to portrait mode.
http://www.sebastianborggrewe.de/only-make-one-single-view-controller-rotate/
http://b2cloud.com.au/tutorial/forcing-uiviewcontroller-orientation/
How can I force the app to become portrait only mode after dismiss the landscape viewcontroller?
This is How I presenting the landscape view controller and dismissing it.
LineChartViewController *obj = [[LineChartViewController alloc]initWithNibName:#"LineChartViewController" bundle:nil];
[self.navigationController presentViewController:obj animated:YES completion:nil];
- (IBAction)btnDonePressed:(id)sender{
[self dismissViewControllerAnimated:NO completion:nil];
}
XIB of the LineChartViewController is in landscape mode.
In simple words, My app is portrait only, and I wanted to show CorePlot hostView in landscape mode.
Actually I could solve the issue by rotating the CorePlot hostView. The solution isn't the perfect for the the question described, but I'd like to put my solution here, since it solved my problem
self.hostView = [(CPTGraphHostingView *) [CPTGraphHostingView alloc] initWithFrame:self.viewGraphBack.bounds];
self.hostView.allowPinchScaling = YES;
[self.viewGraphBack addSubview:self.hostView];
CGAffineTransform transform =
CGAffineTransformMakeRotation(DegreesToRadians(90));
viewGraphBack.transform = transform;
viewGraphBack.frame = CGRectMake(-285, 0, 568, 320);
[self.view addSubview:viewGraphBack];
This kind of workaround works for me (temporary pushing fake model view controller), called after other view controller which introduces new orientation is demised:
- (void)doAWorkaroudnOnUnwantedRotation {
// check if is workaround nesesery:
if (UIInterfaceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
double delayInSeconds = 0.7;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
UIViewController *fake = [[[UIViewController alloc] init] autorelease];
UIViewController *rootController = [UIApplication sharedApplication].keyWindow.rootViewController;
[rootController presentModalViewController: fake animated: NO];
[fake dismissModalViewControllerAnimated: NO];
});
}
}
If Parent viewcontroller in UIInterfaceOrientationPortrait mode & current viewcontroller should be in UIInterfaceOrientationLandscapeLeft or UIInterfaceOrientationLandscapeRight in that case you may use device orientation changing delegate & a few codes in viewdidload
In ViewDidLoad
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
& implement shouldAutorotateToInterfaceOrientation delegate in ViewController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) return YES;
return NO;
}
Like this. Assure that landscape mode must be checked in from target settings.
Write this category in your project
#import "UINavigationController+ZCNavigationController.h"
#implementation UINavigationController (ZCNavigationController)
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
#end
And in your viewcontroller where you need Landscape
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
I've got a header/brand image which changes between iPad and iPhone, but will not change the picture when changing from portrait to landscape, which is really important that it does.
I have this HeaderView Class, which is called by tableViewControllers like this:
self.tableView.tableHeaderView = [[HeaderView alloc] initWithText:#""];
which holds a UIImageView:
#interface HeaderView : UIImageView{
}
- (id)initWithText:(NSString*)text;
- (void)setText:(NSString*)text;
#end
For the M file, we find where I'm not getting the result I want:
#import "HeaderView.h"
#define IDIOM UI_USER_INTERFACE_IDIOM()
#define IPAD UIUserInterfaceIdiomPad
#interface HeaderView()
{
UILabel*label;
}
#end
#implementation HeaderView
- (id)initWithText:(NSString*)text
{
UIImage* img = [UIImage imageNamed:#"WashU.png"];
UIImage* iPhonePortrait = [UIImage imageNamed:#"WashU2.png"];
UIImage* image = [[UIImage alloc] init];
UIInterfaceOrientation interfaceOrientation = [UIApplication sharedApplication].statusBarOrientation;
//different header image for different devices...
if(IDIOM==IPAD){
image = img;
}
else{
if(UIInterfaceOrientationIsPortrait(interfaceOrientation)){
image = iPhonePortrait;
}
else if(UIInterfaceOrientationIsLandscape(interfaceOrientation))
{
iPhonePortrait = nil;
image = img;
}
}
[headerImageView setImage:image];
if (self = [super initWithImage:image]){
}
return self;
}
I also have added these methods:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
-(BOOL)shouldAutorotate {
return YES;
}
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
I'm sure its a classic sort of question, but I'm reasonably stumped. Also, if I remove
[headerImageView setImage:image];
, and
[self addSubview:headerImageView];
, the image still shows up, which means that
if (self = [super initWithImage:image])
is doing all the display work.
didRotateFromInterfaceOrientation is sent to your view controller after rotation, you can implement that to change your image.
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
...change your image here
}
As your code, you do not need allocate (UIImage*)image property, because you will assign (UIImage*)img or (UIImage*)iPhonePortrait. And should assign image to headerImageView.image.
[headerImageView setImage:image];
You are not actually assigning the image to the imageView. Add:
headerImageView.image = image;
somewhere after 'image' has been set (based on iPad vs iPhone and Portrait vs Landscape).