iOS:サブビューの自動回転を無効にします
-
28-10-2019 - |
質問
オリエンテーションの変更をサポートするiPadアプリケーション用のネストビュー階層があります。次のように見えます。
UIViewController
UIView
- UIView
- UIImageView (disable rotation)
- UIImageView
- UIView (disable rotation)
- UIView
- UIView
...
他の人が自動回転してサイズを変更できるようにしながら、いくつかのサブビューの方向をロックしたいと思います。これを達成する方法を理解できないようです。
1つのアプローチがサブビューを手動で回転させているようです willAnimateRotationToInterfaceOrientation:
. 。 SDKが私が元に戻す回転を実行していることを考えると、それは特に魅力的ではありません。
サブビューやその他の方法の方向変更を単純に無効にして、階層を再構築する方法はありますか?
解決
オートローテーションは、ビューのuiviewcontrollerによって処理されます(shouldAutorotateToInterfaceOrientation:
)、そのため、1つのアプローチは、回転可能なビューが1つのビューコントローラーによって管理されるように階層を配置し、別のビューコントローラーによって回転不可能なビューを管理することです。これらのuiviewcontrollerのルートビューはどちらも、ウィンドウ/スーパービューに追加する必要があります。
ここでの微妙さは、同じレベルで2つのビューコントローラーのビューがある場合です(つまり、byを追加しました addSubview:
)、最初のビューコントローラーのみ(通常はウィンドウの rootViewController
) shouldAutorotateToInterfaceOrientation:
メッセージ。
私はこのアプローチを使用して、メインビューはそうではありませんが、回転するツールバーを実現しました。
Appleの技術Q&A QA1688(「なぜ私のuiviewcontrollerがデバイスで回転しないのですか?」) この問題について少し話します。
iOS 6の更新:
オートローテーションは現在使用されています UIViewController
's shouldAutorotate
と supportedInterfaceOrientations
方法。 shouldAutorotate
戻り値 YES
デフォルトでは、以外のビューコントローラーは rootViewController
ウィンドウの直接サブビューは、とにかく回転コールバックを受信しません。
iOS 6のサンプルコード:
「シングルビューアプリケーション」テンプレートを使用して新しいプロジェクトを作成し、「ストーリーボードの使用」が確認されていることを確認します。提供されたものを使用します ViewController
回転ビューコントローラーとしてのクラス(必要に応じて名前を変更してください!)、2つ目を作成します UIViewController
サブクラスが呼び出されました NonRotatingViewController
. 。このビューコントローラーは回転コールバックを受信することさえありませんが、完全性と明確さのために、次のコードをに追加します NonRotatingViewController.m
:
- (BOOL)shouldAutorotate
{
return NO;
}
の中に MainStoryboard
ファイル、新しいビューコントローラーオブジェクトをドラッグして、そのクラスをに設定します NonRotatingViewController
, 、およびストーリーボードIDを「non -rotatingVc」に設定します。そこにいる間に、回転ビューコントローラービューの背景色をClear(この展示の下に追加されます)をクリアに変更し、各ビューにラベルを追加します。の AppDelegate.m
, 、次のコードを追加します。
#import "NonRotatingViewController.h"
// ...
// ...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
NonRotatingViewController *nonRotatingVC = [mainStoryboard instantiateViewControllerWithIdentifier:@"NonRotatingVC"];
[self.window addSubview:nonRotatingVC.view];
return YES;
}
これは、非回転ビューコントローラーをインスタンス化し、そのビューをウィンドウに直接追加するだけです(この時点でウィンドウのNB rootViewController
すでにストーリーボードで設定されています)。
プロジェクトを実行します。デバイスを回転させ、1つのラベルが回転するのを見て、もう1つのラベルが静止しているのを見て驚かせます!
サンプルコードPre iOS 6:
私はこれを新しいプロジェクトで行いました - 新しいビューベースのアプリケーションでは問題ありません。 2つの新しいビューコントローラーを追加します。 RotatingViewController
と NonRotatingViewController
. 。それぞれのペン先の中には、ビューを回転させるかどうかを説明するためにラベルを追加しました。次のコードを追加します。
'RotatingViewController.m
'
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
'NonRotatingViewController.m
'
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationPortrait) { // Or whatever orientation it will be presented in.
return YES;
}
return NO;
}
'AppDelegate.m
'
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RotatingViewController *rotating = [[RotatingViewController alloc] initWithNibName:@"RotatingViewController" bundle:nil];
self.rotatingViewController = rotating;
[rotating release];
NonRotatingViewController *nonRotating = [[NonRotatingViewController alloc] initWithNibName:@"NonRotatingViewController" bundle:nil];
self.nonRotatingViewController = nonRotating;
[nonRotating release];
[self.window addSubview:self.rotatingViewController.view];
[self.window insertSubview:self.nonRotatingViewController.view belowSubview:self.rotatingViewController.view];
[self.window makeKeyAndVisible];
return YES;
}
これが役立つことを願っています。
他のヒント
これが別の方法です。このコードをviewcontroller viewdidloadに配置するだけです。
YourAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
// the view you don't want rotated (there could be a heierarchy of views here):
UIView *nonRotatingView = [[UIView alloc] initWithFrame:CGRectMake(100,0,30,500)];
nonRotatingView.backgroundColor = [UIColor purpleColor];
// make sure self.view and its children are transparent so you can see through to this view that will not be rotated behind self.view.
[delegate.window insertSubview:nonRotatingView belowSubview:self.view];
// you can't put it in the front using:
// [delegate.window insertSubview:nonRotatingView aboveSubview:self.view];
// It will show up the same as before
// you should declare nonRotatingView as a property so you can easily access it for removal, etc.
この問題を解決する私のアプローチは、 UINotification
自動回転を検出し、逆方向にビューを回転させるには。
ここで完全なコードを見つける:
https://gist.github.com/ffraenz/5945301
- (void)orientationDidChangeNotificationReceived:(NSNotification *)notification
{
// find out needed compass rotation
// (as a countermeasure to auto rotation)
float rotation = 0.0;
if (self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
rotation = M_PI;
else if (self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
rotation = M_PI / 2.0;
else if (self.interfaceOrientation == UIInterfaceOrientationLandscapeRight)
rotation = M_PI / (- 2.0);
// rotate compass without auto rotation animation
// iOS rotation animation duration is 0.3
// this excludes the compassView from the auto rotation
// (same effect as in the camera app where controls do rotate and camera viewport don't)
[UIView animateWithDuration:0.3 animations:^(void) {
self.compassView.transform = CGAffineTransformMakeRotation(rotation);
}];
}