95

特定のビューでデバイスの回転をサポートしたいアプリがありますが、ランドスケープモードでは特に意味をなさないアプリがあるため、ビューを交換すると、回転を強制的にポートレートに設定したいと思います。

UIDevice には文書化されていないプロパティ セッターがありますが、これはトリックを実行しますが、明らかにコンパイラの警告を生成し、SDK の将来のリビジョンで消える可能性があります。

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];

オリエンテーションを強制する文書化された方法はありますか?

更新:すでに実装しているため、 shouldAutorotateToInterfaceOrientation を探していないため、例を提供すると思いました。

アプリでビュー 1 では横向きと縦向きをサポートし、ビュー 2 では縦向きのみをサポートするようにします。すべてのビューに対して shouldAutorotateToInterfaceOrientation を既に実装していますが、ユーザーがビュー 1 で横向きモードになってからビュー 2 に切り替えた場合、強制的に電話を回転させて縦向きに戻します。

4

17 に答える 17

101

これはかなり後になってからの話ですが、ナビゲーション コントローラーを使用していない人や、文書化されていないメソッドを使用したくない人がいる場合に備えて:

UIViewController *c = [[UIViewController alloc]init];
[self presentModalViewController:c animated:NO];
[self dismissModalViewControllerAnimated:NO];
[c release];

通常のビュー コントローラーを表示して閉じるだけで十分です。

明らかに、shouldAutorotateToInterfaceOrientation のオーバーライドで方向を確認または拒否する必要があります。しかし、これにより shouldAutorotate... がシステムによって再度呼び出されます。

于 2011-02-06T18:56:02.303 に答える
16

縦向きから横向きに強制的に回転させたい場合は、ここにコードがあります。ビューの中心を調整する必要があることに注意してください。私のビューが正しい場所に配置されていないことに気付きました。そうでなければ、それは完全に機能しました。ヒントをありがとう。

if(UIInterfaceOrientationIsLandscape(self.interfaceOrientation)){

        [UIView beginAnimations:@"View Flip" context:nil];
        [UIView setAnimationDuration:0.5f];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

        self.view.transform = CGAffineTransformIdentity;
        self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
        self.view.bounds = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f);
        self.view.center = CGPointMake(160.0f, 240.0f);

        [UIView commitAnimations];
}
于 2009-04-27T12:32:27.920 に答える
7

プログラムで iPhone を必要な向きに強制する簡単な方法があります - kdbdallasJoshによって既に提供された 2 つの回答を使用します。

//will rotate status bar
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];


//will re-rotate view according to statusbar
UIViewController *c = [[UIViewController alloc]init];
[self presentModalViewController:c animated:NO];
[self dismissModalViewControllerAnimated:NO];
[c release];

魅力のように機能します:)

編集:

iOS 6 の場合、この関数を追加する必要があります: (モーダルビューコントローラーで動作します)

- (NSUInteger)supportedInterfaceOrientations
{
    return (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight);
}
于 2012-05-09T12:00:43.897 に答える
7

UIViewController画面にUINavigationControllerが横向きに表示されるという問題がありました。ただし、フローで次のビュー コントローラーがプッシュされると、デバイスを縦向きに戻す必要がありました。

私が気づいたのはshouldAutorotateToInterfaceOrientation:、新しいView Controllerがスタックにプッシュされたときにメソッドが呼び出されるのではなく、View Controllerがスタックからポップされたときに呼び出されることです

これを利用して、アプリの 1 つで次のコード スニペットを使用しています。

- (void)selectHostingAtIndex:(int)hostingIndex {

    self.transitioning = YES;

    UIViewController *garbageController = [[[UIViewController alloc] init] autorelease];
    [self.navigationController pushViewController:garbageController animated:NO];
    [self.navigationController popViewControllerAnimated:NO];

    BBHostingController *hostingController = [[BBHostingController alloc] init];
    hostingController.hosting = [self.hostings objectAtIndex:hostingIndex];
    [self.navigationController pushViewController:hostingController animated:YES];
    [hostingController release];

    self.transitioning = NO;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    if (self.transitioning)
        return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
    else
        return YES;
}

基本的に、空のビュー コントローラーを作成し、それをスタックにプッシュし、すぐにポップすることで、インターフェイスを縦位置に戻すことができます。コントローラーがポップされたら、最初に押すつもりだったコントローラーを押すだけです。視覚的には見栄えがよく、空の任意のビュー コントローラーがユーザーに表示されることはありません。

于 2010-08-19T21:24:54.933 に答える
7

私はこれに対する良い解決策を探して掘り下げてきました。トリックを実行するこのブログ投稿を見つけました。キーから最も外側のビューを削除しUIWindowて再度追加すると、システムはビューコントローラーからメソッドを再クエリしshouldAutorotateToInterfaceOrientation:、正しい向きが適用されるように強制します。それを参照してください:iPhoneがuiviewを強制的に再配置する

于 2010-10-27T15:54:37.480 に答える
6

これは、後のiPhone3.1.2SDKでは問題ではなくなりました。これで、スタックにプッシュバックされるビューの要求された方向を尊重するように見えます。つまり、古いiPhone OSバージョンを検出し、最新リリースより前の場合にのみsetOrientationを適用する必要があることを意味します。

Appleの静的分析が、古いSDKの制限を回避していることを理解するかどうかは明らかではありません。私は個人的にAppleから次のアップデートでメソッド呼び出しを削除するように言われたので、古いデバイスをハックして承認プロセスを通過できるかどうかはまだわかりません。

于 2009-12-05T00:03:27.007 に答える
5

ジョシュの答えは私にとってはうまくいきます。

ただし、「方向が変更されました。UI を更新してください」という通知を投稿することを好みます。この通知がView Controllerによって受信されると、 が呼び出さshouldAutorotateToInterfaceOrientation:れ、必要な向きに戻ることYESで任意の向きを設定できます。

[[NSNotificationCenter defaultCenter] postNotificationName:UIDeviceOrientationDidChangeNotification object:nil];

唯一の問題は、これによりアニメーションなしで再方向付けが強制されることです。スムーズな遷移を実現するには、この行をbeginAnimations:との間で折り返す必要があります。commitAnimations

それが役立つことを願っています。

于 2011-06-13T15:20:23.500 に答える
3

FWIW、これが手動で方向を設定する私の実装です(アプリのルートビューコントローラーに移動するために、ナッチ):

-(void)rotateInterfaceToOrientation:(UIDeviceOrientation)orientation{

    CGRect bounds = [[ UIScreen mainScreen ] bounds ];
    CGAffineTransform t;
    CGFloat r = 0;
    switch ( orientation ) {
        case UIDeviceOrientationLandscapeRight:
            r = -(M_PI / 2);
            break;
        case UIDeviceOrientationLandscapeLeft:
            r  = M_PI / 2;
            break;
    }
    if( r != 0 ){
        CGSize sz = bounds.size;
        bounds.size.width = sz.height;
        bounds.size.height = sz.width;
    }
    t = CGAffineTransformMakeRotation( r );

    UIApplication *application = [ UIApplication sharedApplication ];

    [ UIView beginAnimations:@"InterfaceOrientation" context: nil ];
    [ UIView setAnimationDuration: [ application statusBarOrientationAnimationDuration ] ];
    self.view.transform = t;
    self.view.bounds = bounds;
    [ UIView commitAnimations ];

    [ application setStatusBarOrientation: orientation animated: YES ];     
}

次の方法と組み合わせるUINavigationControllerDelegate(を使用していると仮定UINavigationController):

-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    // rotate interface, if we need to
    UIDeviceOrientation orientation = [[ UIDevice currentDevice ] orientation ];
    BOOL bViewControllerDoesSupportCurrentOrientation = [ viewController shouldAutorotateToInterfaceOrientation: orientation ];
    if( !bViewControllerDoesSupportCurrentOrientation ){
        [ self rotateInterfaceToOrientation: UIDeviceOrientationPortrait ];
    }
}

UIViewControllerこれにより、着信が現在のデバイスの向きをサポートしているかどうかに応じてルートビューを回転させることができます。最後に、rotateInterfaceToOrientation標準のiOS機能を模倣するために、実際のデバイスの向きの変更に接続する必要があります。このイベントハンドラーを同じルートビューコントローラーに追加します。

-(void)onUIDeviceOrientationDidChangeNotification:(NSNotification*)notification{
    UIViewController *tvc = self.rootNavigationController.topViewController;
    UIDeviceOrientation orientation = [[ UIDevice currentDevice ] orientation ];
    // only switch if we need to (seem to get multiple notifications on device)
    if( orientation != [[ UIApplication sharedApplication ] statusBarOrientation ] ){
        if( [ tvc shouldAutorotateToInterfaceOrientation: orientation ] ){
            [ self rotateInterfaceToOrientation: orientation ];
        }
    }
}

最後に、次のように通知に登録しますUIDeviceOrientationDidChangeNotificationinitloadview

[[ NSNotificationCenter defaultCenter ] addObserver: self
                                           selector: @selector(onUIDeviceOrientationDidChangeNotification:)
                                               name: UIDeviceOrientationDidChangeNotification
                                             object: nil ];
[[ UIDevice currentDevice ] beginGeneratingDeviceOrientationNotifications ];
于 2010-12-07T07:11:16.763 に答える
2

これは私にとってはうまくいきます(Henry Cookeに感謝します):

私の目的は、横向きの変更のみを処理することでした。

初期化方法:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(orientationChanged:)
                                             name:UIDeviceOrientationDidChangeNotification
                                           object:nil];

- (void)orientationChanged:(NSNotification *)notification {    
    //[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
    UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
    CGRect bounds = [[ UIScreen mainScreen ] bounds ];
    CGAffineTransform t;
    CGFloat r = 0;
    switch ( orientation ) {
        case UIDeviceOrientationLandscapeRight:
            r = 0;
            NSLog(@"Right");
            break;
        case UIDeviceOrientationLandscapeLeft:
            r  = M_PI;
            NSLog(@"Left");
            break;
        default:return;
    }

    t = CGAffineTransformMakeRotation( r );

    UIApplication *application = [ UIApplication sharedApplication ];
    [ UIView beginAnimations:@"InterfaceOrientation" context: nil ];
    [ UIView setAnimationDuration: [ application statusBarOrientationAnimationDuration ] ];
    self.view.transform = t;
    self.view.bounds = bounds;
    [ UIView commitAnimations ];

    [ application setStatusBarOrientation: orientation animated: YES ];
}
于 2011-04-18T16:26:57.163 に答える
1

特定のビューでデバイスの回転をサポートしたいアプリがありますが、横向きモードでは特に意味がないため、ビューを入れ替えるときに、回転を強制的に縦向きに設定したいと思います。

このスレッドの上記の元の投稿は現在非常に古いことを認識していますが、同様の問題がありました。ユーザーが横向きと縦向きの間で回転できる1つの画面を除いて、私のアプリのすべての画面は縦向きのみです。

これは簡単なことですが、他の投稿と同様に、前の画面に戻ったときに、現在のデバイスの向きに関係なく、アプリが自動的に縦向きに戻るようにしたかったのです。

私が実装した解決策は、横向きモードではナビゲーションバーを非表示にすることでした。つまり、ユーザーは縦向きである間だけ前の画面に戻ることができます。したがって、他のすべての画面は縦向きにすることしかできません。

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)pInterfaceOrientation {
    BOOL lHideNavBar = self.interfaceOrientation == UIInterfaceOrientationPortrait ? NO : YES;
    [self.navigationController setNavigationBarHidden:lHideNavBar animated:YES];
}

これには、横向きモードで利用できる画面スペースが増えるという点で、私のアプリにも追加の利点があります。問題の画面はPDFファイルの表示に使用されるため、これは便利です。

お役に立てれば。

于 2011-10-03T15:45:37.447 に答える
1

結局、これは非常に簡単に解決しました。私は上記のすべての提案を試しましたが、それでも不足しているので、これが私の解決策でした:

横向き(左または右)のままにする必要があるViewControllerで、向きの変更をリッスンします。

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(didRotate:)
                                             name:UIDeviceOrientationDidChangeNotification object:nil];

次に、didRotateで:

- (void) didRotate:(NSNotification *)notification
{   if (orientationa == UIDeviceOrientationPortrait) 
    {
        if (hasRotated == NO) 
        {
            NSLog(@"Rotating to portait");
            hasRotated = YES;
            [UIView beginAnimations: @"" context:nil];
            [UIView setAnimationDuration: 0];
            self.view.transform = CGAffineTransformIdentity;
            self.view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(-90));
            self.view.bounds = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f);
            self.view.frame = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f);
            [UIView commitAnimations];

    }
}
else if (UIDeviceOrientationIsLandscape( orientationa))
{
    if (hasRotated) 
    {
        NSLog(@"Rotating to lands");
        hasRotated = NO;
        [UIView beginAnimations: @"" context:nil];
        [UIView setAnimationDuration: 0];
        self.view.transform = CGAffineTransformIdentity;
        self.view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(0));
        self.view.bounds = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f);
        self.view.frame = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f);
        [UIView commitAnimations];

    }
}

view.bounds / frameが明示的にリセットされているため、自動サイズ変更を使用するスーパービュー/サブビューを覚えておいてください...

ビューランドスケープを維持するためのこの方法の唯一の注意点は、変化がないように見える方がよい場合に、発生する必要のある方向を切り替える固有のアニメーションです。

于 2012-07-05T03:55:31.040 に答える
1

iOS 6 ソリューション:

[[[self window] rootViewController] presentViewController:[[UIViewController alloc] init] animated:NO completion:^{
    [[[self window] rootViewController] dismissViewControllerAnimated:NO completion:nil];
}];

正確なコードは、アプリごとに、またそれを配置する場所によって異なります (私は AppDelegate で使用しました)。使用するものと交換[[self window] rootViewController]してください。を使用していましたUITabBarController

于 2013-01-13T00:42:41.503 に答える
0

私は解決策を見つけてフランス語で何かを書きました(しかしコードは英語です)。ここ

この方法は、コントローラーをウィンドウビューに追加することです(コントローラーは、shouldRotate ....関数の適切な実装を備えている必要があります)。

于 2010-09-10T14:26:59.163 に答える
-3

もちろん、UI に 90 度の変換を適用することもできますが、実行時にこれを行うことはできないと思います。

于 2008-10-08T20:09:48.680 に答える
-3

これは私が使用するものです。(コンパイルの警告が表示されますが、シミュレータと iPhone の両方で動作します)

[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
于 2008-10-10T06:58:18.433 に答える
-3

UIViewControllers を使用している場合は、次のメソッドがあります。

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

NO回転させたくないビューを含むビュー コントローラーに戻ります。

詳細はこちら

于 2008-10-08T15:21:14.957 に答える