我需要检测设备是否处于竖屏模式,以便启动特殊的动画。但我不希望我的视图自动旋转。
当设备旋转到竖屏时,如何覆盖视图的自动旋转?我的应用程序只需要在横向显示视图,但似乎如果我要能够检测到旋转到竖屏的情况,也需要支持竖屏模式。
我需要检测设备是否处于竖屏模式,以便启动特殊的动画。但我不希望我的视图自动旋转。
当设备旋转到竖屏时,如何覆盖视图的自动旋转?我的应用程序只需要在横向显示视图,但似乎如果我要能够检测到旋转到竖屏的情况,也需要支持竖屏模式。
尝试在应用程序加载或视图加载时执行以下操作:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:[UIDevice currentDevice]];
接着添加以下方法:
- (void) orientationChanged:(NSNotification *)note
{
UIDevice * device = note.object;
switch(device.orientation)
{
case UIDeviceOrientationPortrait:
/* start special animation */
break;
case UIDeviceOrientationPortraitUpsideDown:
/* start special animation */
break;
default:
break;
};
}
通过上述方法,您可以在不启用视图自动旋转的情况下注册设备方向更改操作。
iOS中的所有情况下,当您添加观察者时,请同时在适当的时候将其移除(可能是视图出现/消失时,但不总是)。您只能拥有“观察/取消观察”代码对。如果您不这样做,应用程序将崩溃。选择何时观察/取消观察超出了此QA的范围。然而,您必须有一个与上面的“观察”代码匹配的“取消观察”代码。
如果您来到这个问题是为了检测方向变化(而不一定想禁用旋转),您还应该了解从iOS 8开始可用的viewWillTransitionToSize
方法。
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animateAlongsideTransition({ (UIViewControllerTransitionCoordinatorContext) -> Void in
let orient = UIApplication.sharedApplication().statusBarOrientation
switch orient {
case .Portrait:
println("Portrait")
// Do something
default:
println("Anything But Portrait")
// Do something else
}
}, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
println("rotation completed")
})
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
}
如果您不需要担心实际方向:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
// do something
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
}
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
// do whatever
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
}];
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}
如果你不需要担心实际方向(参考这个答案):
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
// Do view manipulation here.
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}
1) David的回答的Swift版本 2) 如果您仍然希望在没有方向更改时检测方向(Moe对如何在iOS上检测设备方向?的Swift版本的答案)
// Initial device orientation
let orientation: UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation
if(orientation == UIInterfaceOrientation.Unknown){
// code for Unknown
}
else if(orientation == UIInterfaceOrientation.Portrait){
// code for Portrait
}
else if(orientation == UIInterfaceOrientation.PortraitUpsideDown){
// code for Portrait
}
else if(orientation == UIInterfaceOrientation.LandscapeRight){
// code for Landscape
}
else if(orientation == UIInterfaceOrientation.LandscapeLeft){
// ode for Landscape
}
// To detect device orientation change
UIDevice.currentDevice().beginGeneratingDeviceOrientationNotifications()
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "orientationChanged:",
name: UIDeviceOrientationDidChangeNotification,
object: UIDevice.currentDevice())
方向改变函数
func orientationChanged(note: NSNotification)
{
let device: UIDevice = note.object as! UIDevice
switch(device.orientation)
{
case UIDeviceOrientation.Portrait:
// code for Portrait
break
case UIDeviceOrientation.PortraitUpsideDown:
// code for Portrait
break
case UIDeviceOrientation.LandscapeLeft:
// code for Landscape
break
case UIDeviceOrientation.LandscapeRight:
// code for Landscape
break
case UIDeviceOrientation.Unknown:
// code for Unknown
break
default:
break
}
}
-(void) seObserverForOrientationChanging
{
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:[UIDevice currentDevice]];
}
- (void) orientationChanged:(NSNotification *)note
{
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)){
//Do something in landscape
}
else {
//Do something in portrait
}
}
这里有一些额外的代码,用于避免不必要的UI重置或过渡:
- (void) orientationChanged:(NSNotification *)note
{
UIDeviceOrientation newOrientation = ((UIDevice*)note.object).orientation;
// don't do anything if device is flat...
if (UIDeviceOrientationIsFlat(newOrientation) || newOrientation == UIDeviceOrientationUnknown)
return;
// ... and only if orientation has changed
if (newOrientation != self->lastOrientation) {
// do whatever you need to do to change UI
self->lastOrientation = newOrientation;
}
}
.UIDeviceOrientationDidChange
通知在 iPhone 上即使设备没有旋转也会被多次调用。不知道原因,但如果你只需要在设备真正旋转时才需要它,那么请按照以下步骤操作。
NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged), name: .UIDeviceOrientationDidChange, object: nil)
从观察者调用的方法应该像这样:
func orientationChanged() {
if traitCollection.isIphone {
defer {
self.previousTraitCollectionForIphone = traitCollection
}
guard let previousTraitCollectionForIphone = previousTraitCollectionForIphone else {
updateView()
return
}
if previousTraitCollectionForIphone != traitCollection {
updateView()
}
} else {
updateView()
}
}
首先禁用除了您想要的方向以外的所有方向(这样它就不会旋转)
然后像David所说,只需获取设备的当前方向:
或者你可以直接使用加速度计(因为这就是它的工作原理),检查重力所在的位置,以确定其方向。如果采用这种方法,你可以自己调整数值来获得不同的结果。
在Swift 5.0中。
DeviceOrientation vs. ScreenSize vs StatusBar.isLandscape?
如果你想要在后台检测方向的变化,并且还需要检测面朝上/下的变化,请查看此链接在Swift中,如何在启动后正确获取设备方向?
它涵盖了使用3种替代方法正确在Swift中检测方向的方法: - viewWillTransitionToSize() - 使用观察者 - 使用状态栏
viewDidLayoutSubviews
,它将处理所有布局更改。(请记住,在不久的将来,用户将在设备上调整应用程序大小。)响应式布局现在是常态。 - Fattie