我需要检测设备何时处于纵向,以便触发特殊动画。但我不希望我的视图自动旋转。
当设备旋转为纵向时,如何覆盖自动旋转的视图?我的应用程序只需要以横向显示它的视图,但如果我希望能够检测到纵向的旋转,我似乎也需要支持纵向。
我需要检测设备何时处于纵向,以便触发特殊动画。但我不希望我的视图自动旋转。
当设备旋转为纵向时,如何覆盖自动旋转的视图?我的应用程序只需要以横向显示它的视图,但如果我希望能够检测到纵向的旋转,我似乎也需要支持纵向。
在应用程序加载或视图加载时尝试执行以下操作:
[[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 的范围。但是,您必须有一个“未观察”才能匹配上面的“观察”代码。
如果您来这个问题是为了寻找如何检测方向变化(不一定要禁用旋转),您还应该了解viewWillTransitionToSize
iOS 8 提供的 .
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)大卫答案的 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
}
}
如果我理解正确,您的应用程序仅是横向的。您可以简单地在应用程序设置中指定它仅是横向的,因此无需担心旋转。无论 iPad 的方向如何,该应用程序都会以横向方式启动并停留在那里。
如果您不想创建设备对象,也可以使用
-(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
}
}
首先禁用除您想要的方向之外的所有内容(使其不会旋转)
然后就像大卫说的那样,只需获取设备当前方向:
或者,您可以自己使用加速度计(因为它是如何完成的)并检查重力的位置以查看它的方向。如果您采用这种方法,您可以自己使用这些值来获得不同的结果。
.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()
}
}
在 Swift 5.0 中。
DeviceOrientation vs. ScreenSize vs StatusBar.isLandscape?
如果您想检测背景中方向的变化,并且还需要检测面朝上/朝下的变化,请检查此链接In Swift, how to get the deviceorientation right after it's launch?
它涵盖了如何使用 3 种替代方法正确检测 Swift 中的方向: - viewWillTransitionToSize() - 使用观察者 - 使用状态栏
下面是一些额外的代码来避免虚假的 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;
}
}