問題:アプリのさまざまな部分で、横向きモード (ロック) と縦向きモード (ロック) の両方を使用するアプリがあります。現在、私は実用的な解決策を持っていますが、それは正しくないようで、独自の問題があります。
最適には、方向の変更を強制したいと思います。必要に応じて、ビューの変換を行うことも考えています。
アプリの基本的な流れ:
- HomeView (Portrait) (これには、いくつかのサブプッシュ ビューもあり、縦向きでそれにロックされています)。
- LandscapeView (Landscape) (横向きでもある 5 つのプッシュされたサブビューがあります)
ノート:
- HomeView には、LandscapeView へのリンクがあります
- LandscapeView は HomeView に戻ることができます
- LandscapeView サブビューの最後に、HomeView に戻ります。
さまざまなビューの向きでこれがどのように見えるかを示す基本的な画像。(線はアプリの流れを示し、画像の向きは各画面のあり方を示します)
現在、以下の実装を使用して、[setLockedToPortait:YES] (縦向きビューの場合) などにより、ビューが縦向きモードまたは横向きモードであるかどうかを呼び出し/設定します。
これは、デバイスが回転している場合に、iOS からどのインターフェイスの向きを使用するかをクエリします。
ここで、LandscapeView に移動する場合のために、通常のビューの上に一時的なビューを表示して、携帯電話を横向きに回転させるために使用するように求めます。(横表示から HomeView に戻ると、一時的な表示も表示されます)
したがって、ユーザーがデバイスを回転させると、正しい向きがトリガーされ、一時ビューが非表示になります。
ユーザーがこの時点で携帯電話を回転させて縦に戻すと、横にロックされたままになるため、別のビューの回転はトリガーされません (一時的なビューも表示されません)。
現在の実装コード::
// ---------------------- NavigationController (subclass of UINavigationController)
@interface NavigationController () {
BOOL isOrientationPortrait;
}
@end
@implementation NavigationController {
UIDeviceOrientation lastAccepted;
UIDeviceOrientation lastKnown;
}
-(void)setLockedToPortait:(BOOL)isLocked {
isOrientationPortrait = isLocked;
}
-(UIDeviceOrientation) getCurrentOrientation {
UIDeviceOrientation orientate = [[UIDevice currentDevice] orientation];
if(orientate == 0) { // needed for simulator
orientate = (UIDeviceOrientation)[UIApplication sharedApplication].statusBarOrientation;
}
return orientate;
}
// Deprecated in iOS6, still needed for iOS5 support.
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation
{
UIDeviceOrientation orientation = [self getCurrentOrientation];
[self setLastKnownOrientation:orientation];
if(isOrientationPortrait == YES) {
if([self isLastKnownPortrait] == YES) {
[self setLastAcceptedOrientation:orientation];
return YES;
} else {
return NO;
}
} else {
if([self isLastKnownLandscape] == YES) {
[self setLastAcceptedOrientation:orientation];
return YES;
} else {
return NO;
}
}
}
// iOS6/7 support
- (BOOL)shouldAutorotate
{
// find out the current device orientation
UIDeviceOrientation orientation = [self getCurrentOrientation];
[self setLastKnownOrientation:orientation];
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
if(isOrientationPortrait == YES) {
if([self isLastKnownPortrait] == YES)
{
UIDeviceOrientation orientation = [self getCurrentOrientation];
[self setLastAcceptedOrientation:orientation];
}
return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
} else {
if([self isLastKnownLandscape] == YES)
{
UIDeviceOrientation orientation = [self getCurrentOrientation];
[self setLastAcceptedOrientation:orientation];
}
return (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight );
}
}
-(void)setLastAcceptedOrientation:(UIDeviceOrientation)orient {
lastAccepted = orient;
}
-(void)setLastKnownOrientation:(UIDeviceOrientation)orient {
lastKnown = orient;
}
-(BOOL)isLastKnownPortrait {
return UIDeviceOrientationIsPortrait(lastKnown);
}
-(BOOL)isLastKnownLandscape {
return UIDeviceOrientationIsLandscape(lastKnown);
}
-(BOOL)isLastAcceptedPortrait {
return UIDeviceOrientationIsPortrait(lastAccepted);
}
-(BOOL)isLastAcceptedLandscape {
return UIDeviceOrientationIsLandscape(lastAccepted);
}
現在の問題:
- デバイスの回転は、ユーザーが縦向きから横向きモードに移行したり、その逆の場合に、ビューが読み込まれた後に常に必要です。
- ユーザーがデバイスの向きをロックしている場合、これはまったく機能しません。
- 横向きモードから戻るときに、ユーザーがすでにデバイスを縦向きに回転させている場合 (最後の横向きビューで)、縦向きビューのインターフェースは、ユーザーがデバイスを再度回転させるまで「横向き」レイアウトにロックされます (現在、私はデバイスを回転させるためにオーバーレイを表示しているだけですが、すでに回転しています... ユーザーにとって非常に迷惑です)。上記の実装で現在大きな問題が発生しています。
次のことができるようになりたいです:
- 現在のビューの方向を電話で強制的に変更します。
- ビューのプッシュ/ポップ間で強制されるビューの優先レイアウトを設定します。
ここと Apple Dev フォーラムで他の解決策をよく調べましたが、この問題をカバーしていないようです。または、2 つのビュー間の方向のバグも存在します。
助けや指針をありがとう!アドバイスは割引されません:D
-- 編集::
@leo-natanのおかげで解決策が見つかりました!!
したがって、ビューの向きを強制的に変更しようとする代わりに。新しいモーダル ビューをプッシュするだけです。これにより、変更が強制されます。回転を管理するには、上記の方向コードが必要です。
それで、HomeViewControllerに今あるもの:
LandscapeViewController * viewController = [[[LandscapeViewController ViewController alloc] init] autorelease];
UINib * nib = [UINib nibWithNibName:@"NavigationController" bundle:nil];
NavigationController *navController = [[nib instantiateWithOwner:nil options:nil] objectAtIndex:0];
[navController initWithRootViewController:viewController];
[self presentViewController:navController animated:YES completion:^{
// completion
}];
したがって、このモーダル ビューの新しいナビゲーション コントローラーを再度追加する必要があります。また、上記の「presentViewController」は、モーダル ビューをプッシュする新しい方法です。
ビュー コントローラを管理するために、次のオーバーロードされたメソッドを実装しました。
-(id)initWithRootViewController:(UIViewController *)rootViewController {
self = [super initWithRootViewController:rootViewController];
if(self){
}
return self;
}
注:上記は絵コンテを使用していません。この問題は、ストーリーボードを使用し、同じ方法でビューをモーダルに表示することで解決できる場合があります。