[英]How Do I detect the orientation of the device on iOS?
我有一個關於如何在 iOS 上檢測設備方向的問題。 我不需要接收更改通知,只需接收當前方向本身。 這似乎是一個相當簡單的問題,但我一直無法解決它。 以下是我到目前為止所做的:
UIDevice *myDevice = [UIDevice currentDevice] ;
[myDevice beginGeneratingDeviceOrientationNotifications];
UIDeviceOrientation deviceOrientation = myDevice.orientation;
BOOL isCurrentlyLandscapeView = UIDeviceOrientationIsLandscape(deviceOrientation);
[myDevice endGeneratingDeviceOrientationNotifications];
在我看來,這應該有效。 我使設備能夠接收設備方向通知,然后詢問它所處的方向,但它不起作用,我不知道為什么。
真的很老的線程,但沒有真正的解決方案。
我遇到了同樣的問題,但發現獲取 UIDeviceOrientation 並不總是一致的,所以改用這個:
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if(orientation == 0) //Default orientation
//UI is in Default (Portrait) -- this is really a just a failsafe.
else if(orientation == UIInterfaceOrientationPortrait)
//Do something if the orientation is in Portrait
else if(orientation == UIInterfaceOrientationLandscapeLeft)
// Do something if Left
else if(orientation == UIInterfaceOrientationLandscapeRight)
//Do something if right
如果 UIViewController:
if (UIDeviceOrientationIsLandscape(self.interfaceOrientation))
{
//
}
如果 UIView:
if (UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation))
{
//
}
UIDevice.h:
#define UIDeviceOrientationIsPortrait(orientation) ((orientation) == UIDeviceOrientationPortrait || (orientation) == UIDeviceOrientationPortraitUpsideDown)
#define UIDeviceOrientationIsLandscape(orientation) ((orientation) == UIDeviceOrientationLandscapeLeft || (orientation) == UIDeviceOrientationLandscapeRight)
更新:
將此代碼添加到 xxx-Prefix.pch 然后你可以在任何地方使用它:
// check device orientation
#define dDeviceOrientation [[UIDevice currentDevice] orientation]
#define isPortrait UIDeviceOrientationIsPortrait(dDeviceOrientation)
#define isLandscape UIDeviceOrientationIsLandscape(dDeviceOrientation)
#define isFaceUp dDeviceOrientation == UIDeviceOrientationFaceUp ? YES : NO
#define isFaceDown dDeviceOrientation == UIDeviceOrientationFaceDown ? YES : NO
用法:
if (isLandscape) { NSLog(@"Landscape"); }
對於您首先要尋找的內容,如果方向改變,您必須獲得通知! 你可以在 viewDidLoad 中設置這個東西
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(OrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
並且每當您的設備的方向改變OrientationDidChange調用時,您可以根據方向做任何您想做的事情
-(void)OrientationDidChange:(NSNotification*)notification
{
UIDeviceOrientation Orientation=[[UIDevice currentDevice]orientation];
if(Orientation==UIDeviceOrientationLandscapeLeft || Orientation==UIDeviceOrientationLandscapeRight)
{
}
else if(Orientation==UIDeviceOrientationPortrait)
{
}
}
如果您想直接從加速度計獲取設備方向,請使用[[UIDevice currentDevice] orientation]
。 但是,如果您需要應用程序的當前方向(界面方向),請使用[[UIApplication sharedApplication] statusBarOrientation]
。
UIViewController
有一個interfaceOrientation
屬性,您可以訪問它來找出視圖控制器的當前方向。
至於你的例子,那應該有效。 當你說它不起作用時,你是什么意思? 與您的預期相比,它給了您什么結果?
在 Swift 3.0 中
獲取設備方向。
/* return current device orientation.
This will return UIDeviceOrientationUnknown unless device orientation notifications are being generated.
*/
UIDevice.current.orientation
從您的應用程序獲取設備方向
UIApplication.shared.statusBarOrientation
對"UIDeviceOrientation"不滿意,因為當 UIViewcontroller 方向固定為特定方向時,您不會獲得與設備方向相關的信息,因此正確的做法是使用"UIInterfaceOrientation" 。
您可以使用"self.interfaceOrientation"從 UIViewController 獲取方向,但是當您分解我們的代碼時,您可能需要在視圖控制器之外進行此類測試(自定義視圖、類別...),因此您仍然可以使用rootviewController訪問控制器之外的任何位置的信息:
if (UIInterfaceOrientationIsLandscape(view.window.rootViewController.interfaceOrientation)) {
}
無論是否啟用方向鎖定,都有一種方法可以通過使用來自 CoreMotion 的數據來實現這一點。 這是代碼:
#import <CoreMotion/CoreMotion.h>
CMMotionManager *cm=[[CMMotionManager alloc] init];
cm.deviceMotionUpdateInterval=0.2f;
[cm startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMDeviceMotion *data, NSError *error) {
if(fabs(data.gravity.x)>fabs(data.gravity.y)){
NSLog(@"LANSCAPE");
if(data.gravity.x>=0){
NSLog(@"LEFT");
}
else{
NSLog(@"RIGHT");
}
}
else{
NSLog(@"PORTRAIT");
if(data.gravity.y>=0){
NSLog(@"DOWN");
}
else{
NSLog(@"UP");
}
}
}];
這里有一些 Swift 變量可以讓檢測更容易:
let LANDSCAPE_RIGHT: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight
let LANDSCAPE_LEFT: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft
let LANDSCAPE: Bool = LANDSCAPE_LEFT || LANDSCAPE_RIGHT
let PORTRAIT_NORMAL: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.Portrait
let PORTRAIT_REVERSE: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.PortraitUpsideDown
let PORTRAIT: Bool = PORTRAIT_REVERSE || PORTRAIT_NORMAL
您是否已解鎖設備方向的硬件鎖? 我的 iPad 1 邊緣有一個。
我目前的做法是:
+ (BOOL)isPortrait {
let window = UIApplication.sharedApplication.delegate.window;
if(window.rootViewController) {
let orientation =
window.rootViewController.interfaceOrientation;
return UIInterfaceOrientationIsPortrait(orientation);
} else {
let orientation =
UIApplication.sharedApplication.statusBarOrientation;
return UIInterfaceOrientationIsPortrait(orientation);
}
}
如果由於某種原因沒有 rootViewController 還沒有安全到 statusBarOrientation ...
以及 swift 中最好的可靠方法:
public extension UIScreen {
public class var isPortrait: Bool {
UIApplication.shared.delegate?.window??.rootViewController?.interfaceOrientation.isPortrait ??
UIApplication.shared.statusBarOrientation.isPortrait
}
public class var isLandscape: Bool { !isPortrait }
}
這是我使用 Combine 的解決方案,它很容易與 SwiftUI 或常規 Swift Object 一起使用。 對於這種真正的全局對象,單例對象(靜態實例)比“環境”更好。
// Singleton object to keep the interface orientation (and any other global state)
class SceneContext: ObservableObject {
@Published var interfaceOrientation = UIInterfaceOrientation.portrait
static let shared = SceneContext()
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
...
func windowScene(_ windowScene: UIWindowScene, didUpdate previousCoordinateSpace: UICoordinateSpace, interfaceOrientation previousInterfaceOrientation: UIInterfaceOrientation, traitCollection previousTraitCollection: UITraitCollection) {
SceneContext.shared.interfaceOrientation = windowScene.interfaceOrientation
}
}
// if you want to execute some code whenever the orientation changes in SwiftUI
someView {
....
}
.onReceive(SceneContext.shared.$interfaceOrientation) { (orientation) in
// do something with the new orientation
}
// if you want to execute some code whenever the orientation changes in a regular Swift object
let pub = SceneContext.shared.$interfaceOrientation.sink(receiveValue: { (orientation) in
// do something with the new orientation
...
})
使用此功能。
func deviceOrientation() -> String! {
let device = UIDevice.current
if device.isGeneratingDeviceOrientationNotifications {
device.beginGeneratingDeviceOrientationNotifications()
var deviceOrientation: String
let deviceOrientationRaw = device.orientation.rawValue
switch deviceOrientationRaw {
case 1:
deviceOrientation = "Portrait"
case 2:
deviceOrientation = "Upside Down"
case 3:
deviceOrientation = "Landscape Right"
case 4:
deviceOrientation = "Landscape Left"
case 5:
deviceOrientation = "Camera Facing Down"
case 6:
deviceOrientation = "Camera Facing Up"
default:
deviceOrientation = "Unknown"
}
return deviceOrientation
} else {
return nil
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.