我写了一个简单的视图控制器,它显示了一个模态弹出对话框。因为它创建了一个覆盖整个屏幕的新窗口,所以我添加了一个UIDeviceOrientationDidChangeNotification
观察器,用于指出如何使用CGAffineTransformMakeRotation()
旋转视图。它似乎有效。
主要是。缺点是我可以摆弄方向,让它最终横向或颠倒。查看this 18s video演示此问题。在调试中,似乎有时通知不会触发,或者至少不会调用正在侦听它的回调方法。
但是,我必须遗漏一些东西,因为如果再看一下视频,你会注意到它背后的视图 正确旋转。那个由-willAnimateRotationToInterfaceOrientation:duration:
管理。如何正确地调用iOS控制器方法(可能由UIViewController中的UIDeviceOrientationDidChangeNotification
观察者管理)但我自己的代码不是?
答案 0 :(得分:12)
我在Kobo中使用了UIApplicationWillChangeStatusBarOrientationNotification
,这似乎可以解决问题。它更加可靠,因为您希望匹配UI的选择方向,而不一定是设备恰好在哪里。换句话说,您可以让Apple决定何时应该重新定位窗口。
以下是iPad上Kobo应用程序的弹出对话框代码中的几个片段(UIAlertView在iPad上看起来很有点,所以Richard Penner写了一个更好的片段)。在更新的iOS版本出现一些故障并且不得不在不同情况下显示这些对话框(所有方向都是IIRC)之后,我不得不将其调整为直接位于UIWindow内部,这意味着要复制所有的方向转换逻辑。
此代码来自UIViewController,其视图直接删除到当前窗口。
- (void) presentDialogWindow
{
// register for orientation change notification
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(orientationWillChange:)
name: UIApplicationWillChangeStatusBarOrientationNotification
object: nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(orientationDidChange:)
name: UIApplicationDidChangeStatusBarOrientationNotification
object: nil];
}
- (void) orientationWillChange: (NSNotification *) note
{
UIInterfaceOrientation current = [[UIApplication sharedApplication] statusBarOrientation];
UIInterfaceOrientation orientation = [[[note userInfo] objectForKey: UIApplicationStatusBarOrientationUserInfoKey] integerValue];
if ( [self shouldAutorotateToInterfaceOrientation: orientation] == NO )
return;
if ( current == orientation )
return;
// direction and angle
CGFloat angle = 0.0;
switch ( current )
{
case UIInterfaceOrientationPortrait:
{
switch ( orientation )
{
case UIInterfaceOrientationPortraitUpsideDown:
angle = (CGFloat)M_PI; // 180.0*M_PI/180.0 == M_PI
break;
case UIInterfaceOrientationLandscapeLeft:
angle = (CGFloat)(M_PI*-90.0)/180.0;
break;
case UIInterfaceOrientationLandscapeRight:
angle = (CGFloat)(M_PI*90.0)/180.0;
break;
default:
return;
}
break;
}
case UIInterfaceOrientationPortraitUpsideDown:
{
switch ( orientation )
{
case UIInterfaceOrientationPortrait:
angle = (CGFloat)M_PI; // 180.0*M_PI/180.0 == M_PI
break;
case UIInterfaceOrientationLandscapeLeft:
angle = (CGFloat)(M_PI*90.0)/180.0;
break;
case UIInterfaceOrientationLandscapeRight:
angle = (CGFloat)(M_PI*-90.0)/180.0;
break;
default:
return;
}
break;
}
case UIInterfaceOrientationLandscapeLeft:
{
switch ( orientation )
{
case UIInterfaceOrientationLandscapeRight:
angle = (CGFloat)M_PI; // 180.0*M_PI/180.0 == M_PI
break;
case UIInterfaceOrientationPortraitUpsideDown:
angle = (CGFloat)(M_PI*-90.0)/180.0;
break;
case UIInterfaceOrientationPortrait:
angle = (CGFloat)(M_PI*90.0)/180.0;
break;
default:
return;
}
break;
}
case UIInterfaceOrientationLandscapeRight:
{
switch ( orientation )
{
case UIInterfaceOrientationLandscapeLeft:
angle = (CGFloat)M_PI; // 180.0*M_PI/180.0 == M_PI
break;
case UIInterfaceOrientationPortrait:
angle = (CGFloat)(M_PI*-90.0)/180.0;
break;
case UIInterfaceOrientationPortraitUpsideDown:
angle = (CGFloat)(M_PI*90.0)/180.0;
break;
default:
return;
}
break;
}
}
CGAffineTransform rotation = CGAffineTransformMakeRotation( angle );
[UIView beginAnimations: @"" context: NULL];
[UIView setAnimationDuration: 0.4];
self.view.transform = CGAffineTransformConcat(self.view.transform, rotation);
[UIView commitAnimations];
}
- (void) orientationDidChange: (NSNotification *) note
{
UIInterfaceOrientation orientation = [[[note userInfo] objectForKey: UIApplicationStatusBarOrientationUserInfoKey] integerValue];
if ( [self shouldAutorotateToInterfaceOrientation: [[UIApplication sharedApplication] statusBarOrientation]] == NO )
return;
self.view.frame = [[UIScreen mainScreen] applicationFrame];
[self didRotateFromInterfaceOrientation: orientation];
}
我们通过加载此视图控制器,将其视图添加到窗口,然后调用-presentModalDialog来使用它,如下所示:
UIView *window = [[UIApplication sharedApplication] keyWindow];
[window addSubview: theController.view];
[theController presentDialogWindow];
我将很快创建一个简单的UIViewController子类来实现fiddly位,并将它发布在我的github帐户上。当我这样做时,我会编辑这个&链接到它。
答案 1 :(得分:0)
UIDeviceOrientation有一些值未映射到UIInterfaceOrientation:
UIDeviceOrientationUnknown,
UIDeviceOrientationFaceUp, // Device oriented flat, face up
UIDeviceOrientationFaceDown // Device oriented flat, face down
通知回调是否可能会被触发,但这些情况不会被处理?
如果视图控制器可以访问该窗口 - 它可以手动将didRotate回调转发到窗口。
答案 2 :(得分:0)
我通过取消UIDeviceOrientationDidChangeNotification
的使用来解决这个问题。我所做的是创建UIViewController
的子类,并将自定义视图设置为其视图。然后它只是实现-willAnimateRotationToInterfaceOrientation:duration:
来进行旋转。这对我来说实际上是不那么挑剔的代码。但是,它确实感觉像是一个黑客,只是为了在UIViewController
的克隆中利用自转来创建一个任意的presentModalViewController
。似乎UIDeviceOrientationDidChangeNotification
应该正常工作。我希望有一种方法可以让它表现出来,但我还没有找到它。 : - (