web-dev-qa-db-ja.com

IOS 6デバイスの向きを横向きにする

10個のView Controllerを備えたアプリを提供しました。 Navigation Controllerを使用してそれらをロード/アンロードします。

1つを除くすべてがポートレートモードです。 7番目のVCが横長であるとします。ロードされたときに横向きで表示する必要があります。

IOS 6で向きをポートレートからランドスケープに強制する方法を提案してください(IOS 5でも動作するとよいでしょう)。

ここに私がそれをやっていた方法があります[〜#〜] before [〜#〜] IOS 6:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    UIViewController *c = [[[UIViewController alloc]init] autorelease];
    [self presentModalViewController:c animated:NO];
    [self dismissModalViewControllerAnimated:NO];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

モーダルVCの提示と却下は、アプリにその向きの確認を強制するため、shouldAutorotateToInterfaceOrientationが呼び出されていました。

IOS 6で試したこと:

- (BOOL)shouldAutorotate{
    return YES;
}
-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return UIInterfaceOrientationLandscapeLeft;
}

ロード時には、コントローラーはポートレートのままになります。デバイスを回転させた後、向きが変わります。ただし、コントローラーをロード時に自動的に横向きに回転させる必要があるため、ユーザーはデバイスを回転させてデータを正しく表示する必要があります。

別の問題:デバイスを回転して縦に戻すと、向きが縦になりますが、supportedInterfaceOrientationsのみUIInterfaceOrientationMaskLandscapeで指定しました。なぜ起こるのですか?

また、上記の3つのメソッドの[〜#〜] none [〜#〜]が呼び出されます。

一部の(有用な)データ:

  1. 私のplistファイルでは、3つの方向を指定しています-逆さま以外はすべて。
  2. プロジェクトはXcode 4.3 IOS 5で開始されました。xibsを含むすべてのクラスはXcode 4.5 IOS 6より前に作成され、現在は最新バージョンを使用しています。
  3. Plistファイルでは、ステータスバーは表示に設定されています。
  4. Xibファイル(横向きにするファイル)のステータスバーは「なし」で、向きは横向きに設定されています。

どんな助けも大歓迎です。ありがとう。

57
John Smith

わかりました、解決策を投稿します。

私が持っているもの:

  1. いくつかのView Controllerを備えたビューベースのアプリケーション。 (ナビゲーションベースでしたが、向きの問題のため、ビューベースにする必要がありました)。
  2. ViewLeftを除くすべてのView Controllerは縦長です。

タスク:

  1. ユーザーがデバイスをどのように持っているかに関係なく、View Controllerの1つは自動的に横向きに回転する必要があります。他のすべてのコントローラーはポートレートである必要があり、ランドスケープコントローラーを離れた後、ユーザーがデバイスをどのように持っているかに関係なく、アプリは強制的にポートレートに回転する必要があります。
  2. これは、on IOS 6.x on on IOS 5.x

行け!

更新 @IvanVučicaによって提案されたマクロを削除しました)

すべてのPORTRAIT View Controllerで、次のような自動回転メソッドをオーバーライドします:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
-(BOOL)shouldAutorotate {
    return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

2つのアプローチを見ることができます。1つはIOS 5で、もう1つはIOS 6。

いくつかの追加と変更を加えたLANDSCAPE View Controllerでも同じです

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
    [image_signature setImage:[self resizeImage:image_signature.image]];
    return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
-(BOOL)shouldAutorotate {
    return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
    [image_signature setImage:[self resizeImage:image_signature.image]];
    return UIInterfaceOrientationMaskLandscapeLeft;
}

[〜#〜] attention [〜#〜]:で自動回転を強制するにはIOS 5これを追加する必要があります。

- (void)viewDidLoad{
    [super viewDidLoad];
    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
        [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];    
}

同様に、LANDSCAPEコントローラーを離れた後、どのコントローラーをロードしても、IOS 5の自動回転を強制する必要がありますが、PORTRAITに移動するときにUIDeviceOrientationPortraitを使用しますコントローラ:

- (void)viewDidLoad{
        [super viewDidLoad];
        if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
            [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO];    
    }

これで最後のことです(少し奇妙です)-IOSに応じて、コントローラーから別のコントローラーに切り替える方法を変更する必要があります

NSObjectクラスを「Schalter」(ドイツ語の「Switch」)にします。

Schalter.hで次のように言います:

#import <Foundation/Foundation.h>

@interface Schalter : NSObject
+ (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease;
@end

Schalter.mで:

#import "Schalter.h"
#import "AppDelegate.h"

@implementation Schalter
+ (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease{

    //adjust the frame of the new controller
    CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
    CGRect windowFrame = [[UIScreen mainScreen] bounds];
    CGRect firstViewFrame = CGRectMake(statusBarFrame.Origin.x, statusBarFrame.size.height, windowFrame.size.width, windowFrame.size.height - statusBarFrame.size.height);
    VControllerToLoad.view.frame = firstViewFrame;

    //check version and go
    if (IOS_OLDER_THAN_6)
        [((AppDelegate*)[UIApplication sharedApplication].delegate).window addSubview:VControllerToLoad.view];
    else
        [((AppDelegate*)[UIApplication sharedApplication].delegate).window setRootViewController:VControllerToLoad];

    //kill the previous view controller
    [VControllerToRelease.view removeFromSuperview];
}
@end

今、これがSchalterの使用方法です(WarehouseコントローラーからProductsコントローラーに移動するとします):

#import "Warehouse.h"
#import "Products.h"

@implementation Warehouse
Products *instance_to_products;

- (void)goToProducts{
    instance_to_products = [[Products alloc] init];
    [Schalter loadController:instance_to_products andRelease:self];
}

bla-bla-bla your methods

@end

もちろん、instance_to_productsオブジェクト:

- (void)dealloc{
     [instance_to_products release];
     [super dealloc];
}

まあ、これです。ためらわないで、投票してください、私は気にしません。これは、評判ではなく解決策を探している人のためです。乾杯!サヴァマザレ。

43
John Smith

これは動作するはずです。iOS6以前のバージョンと似ていますが、UINavigationControllerがあります。

UIViewController *portraitViewController = [[UIViewController alloc] init];
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:portraitViewController];
[self.navigationController presentModalViewController:nc animated:NO];
[self.navigationController dismissModalViewControllerAnimated:NO];

次のUIViewControllerをプッシュする前にこれを呼び出しています。現在のUIViewControllerがLandscapeにある場合でも、次にプッシュされたUIViewControllerを強制的にPo​​rtraitモードで表示します(PortraitからLandscapeでも機能するはずです)。 iOS 4 + 5 + 6で動作します。

34
Chunkylover53

最善の解決策は、公式のAppleドキュメントに固執することだと思います。したがって、私は次の方法を使用し、すべてがiOS 5および6で非常にうまく機能しています。VCでは、次の方法をオーバーライドします:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}

IOS 6のメソッド、最初のメソッドはサポートされている方向マスクを返します(名前が示すとおり)

-(NSUInteger)supportedInterfaceOrientations{

    return UIInterfaceOrientationMaskPortrait;
}

2番目のメッセージは、VCが表示されるときに優先インターフェイスの方向であるVCを示します。

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

必要な向きに合わせてポートレートを変更してください;)このソリューションはスムーズに機能しています。マクロやその他のものを作成するというアイデアは、このシンプルなソリューションを回避するのが嫌です。このヘルプを願っています...

14
Skodik.o

私は同じ問題を抱えていました。アプリケーションでは27ビューで、そのうち26ビューがポートレートで、1ビューのみがすべての向きでした(イメージビューアー:))。すべてのクラスにマクロを追加し、ナビゲーションを置き換えることは、私が満足できる解決策ではありませんでした...

そのため、アプリ内でUINavigationControllerの仕組みを維持し、他のコードでこれを置き換えたくありませんでした。

何をすべきか:

@ 1メソッドdidFinishLaunchingWithOptionsのアプリケーションデリゲート

if ([[UIDevice currentDevice].systemVersion floatValue] < 6.0)
{
    // how the view was configured before IOS6
    [self.window addSubview: navigationController.view];
    [self.window makeKeyAndVisible];
}
else
{
    // this is the code that will start the interface to rotate once again
    [self.window setRootViewController: self.navigationController];
}

@ 2 navigationControllerは自動回転に対してYESで応答するだけなので、いくつかの制限を追加する必要があります。UINavicationController-> YourNavigationControllerを拡張し、Interface Builderでリンクします。

@ 3 Navigation Controllerの「迷惑な新しいメソッド」をオーバーライドします。

このクラスはこのアプリケーション専用であるため、コントローラーに対して責任を負い、代わりに応答することができます。

-(BOOL)shouldAutorotate {

    if ([self.viewControllers firstObject] == YourObject)
    {
         return YES;
    }
    return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
     if ([self.viewControllers firstObject] == YourObject)
    {
         return UIINterfaceOrientationMaskLandscape;
    }
    return UIInterfaceOrientationMaskPortrait;
}

これがお役に立てば幸いです、

7
Vlad Cioaba

iOS 6リリースノート から:

現在、iOSコンテナ(UINavigationControllerなど)は、自動回転する必要があるかどうかを判断するために子を参照しません。

rootViewControllershouldAutoRotateメッセージをViewController階層を下ってVCに渡しますか?

3
sam-w

OP pre-ios6(モーダルVCの表示と非表示)と同じ方法を使用して、単一のView Controllerをランドスケープモード(他のすべてはポートレート)で表示しました。 ios6では、横向きVC縦向きで表示)で破損しました。

これを修正するために、landscape VCにpreferredInterfaceOrientationForPresentationメソッドを追加しました。現在、OS 5とOS 6で正常に動作しているようです。

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}

- (BOOL)shouldAutorotate
{
return NO;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{    
return UIInterfaceOrientationLandscapeLeft;
}
2
user1581123

皆さん、成功しないさまざまな解決策を試した後、次の解決策が出てきたので助けてください!.

レシピを準備しました:)。

問題: iOS 6のnavigationcontrollerを使用して、viewcontrollersの向きを変更する必要があります。

解決策:

navigation suggested

ステップ1。画像表示のように、ランドスケープおよびポートレートUInavigationControllersへのモーダルセグエをトリガーする最初のUIviewcontroler。

uIViewController1でさらに深く、Appdelegateのグローバル変数に応じて2つのセグエアクションが必要です。

-(void)viewDidAppear:(BOOL)animated{
    if([globalDelegate changeOrientation]==0){
        [self performSegueWithIdentifier:@"p" sender:self];
    }
    else{
        [self performSegueWithIdentifier:@"l" sender:self];
    }

}

また、ポートレートに戻る方法も必要です&|風景....

- (IBAction)dimis:(id)sender {
    [globalDelegate setChangeOrientation:0];
    [self dismissViewControllerAnimated:NO completion:nil];
}

ステップ2。各NavigationControllerで最初にプッシュされたUiViewControllersは...

-(NSUInteger)supportedInterfaceOrientations{
    return [self.navigationController supportedInterfaceOrientations];
}

-(BOOL)shouldAutorotate{
    return YES;
}

ステップ3。 UInavigationControllerのサブクラスでsupportedInterfaceOrientationsメソッドを上書きします。..

customNavigationControllerには.....

-(NSUInteger)supportedInterfaceOrientations{
    if([self.visibleViewController isKindOfClass:[ViewController2 class]]){

        return UIInterfaceOrientationMaskPortrait;
    }
    else{
        return UIInterfaceOrientationMaskLandscape;

    }

}

ステップ4。ストーリーボードまたはコードで、wantsFullScreenLayoutフラグをyesに設定し、ポートレートおよびランドスケープの両方のuinavigationcontrollersに設定します。

2
47tucanae

カテゴリを使用するか、サブクラス化されて希望の方向を指定するUINavigationControllerにセグエしてみてから、目的のVCにセグエします。続きを読む こちら

1
Michael Mangold

別の方法として、ブロックを使用して同じことを行うことができます。

UIViewController *viewController    = [[UIViewController alloc] init];
viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:viewController animated:NO completion:^{
    [self dismissViewControllerAnimated:NO completion:nil];
}];

また、新しいビューをプッシュする前に呼び出します。

1
Raspu

同じ問題がありました。特定のView Controllerを強制的にランドスケープに表示したい場合は、ナビゲーションスタックにプッシュする直前に実行してください。

UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation];
        if (currentOrientation == UIInterfaceOrientationPortrait ||
            currentOrientation == UIInterfaceOrientationPortraitUpsideDown)
            [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft];

        UIViewController *vc = [[UIViewController alloc] init];
        [self.navigationController pushViewController:vc animated:YES];
        [vc release];
0
Norbert Antal

UINavigationControllerをサブクラス化し、Navigation ControllerのsupportedInterfaceOrientationsを次のようにオーバーライドすることで解決しました。

- (NSUInteger)supportedInterfaceOrientations
{
     return [[self topViewController] supportedInterfaceOrientations];
}

すべてのコントローラーは、必要な方向でsupportedInterfaceOrientationsを実装しました。

0
Zeev Vax

Info.plistファイルに移動して、変更を加えます。 enter image description here