一秸抚、UIDeviceOrientation 與 UIInterfaceOrientation的區(qū)別
UIDeviceOrientation 是機(jī)器硬件的當(dāng)前旋轉(zhuǎn)方向速和,這個(gè)枚舉只能取值,不能手動(dòng)設(shè)置剥汤,通過(guò)UIDeviceOrientationDidChangeNotification可以監(jiān)聽(tīng)其方向的改變颠放。網(wǎng)上有屌絲用以下方式進(jìn)行修改,在這里不建議這樣做
NSNumber *value = [NSNumber numberWithInt:UIDeviceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
UIDeviceOrientation枚舉值如下:
typedef NS_ENUM(NSInteger, UIDeviceOrientation) {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait, // Device oriented vertically, home button on the bottom
UIDeviceOrientationPortraitUpsideDown, // Device oriented vertically, home button on the top
UIDeviceOrientationLandscapeLeft, // Device oriented horizontally, home button on the right
UIDeviceOrientationLandscapeRight, // Device oriented horizontally, home button on the left
UIDeviceOrientationFaceUp, // Device oriented flat, face up
UIDeviceOrientationFaceDown // Device oriented flat, face down
}
UIInterfaceOrientation 是程序界面當(dāng)前旋轉(zhuǎn)方向吭敢,通過(guò)UIApplicationDidChangeStatusBarOrientationNotification可以監(jiān)聽(tīng)到即界面的布局方向發(fā)生了改變碰凶。(只有布局改變了才能收到通知)并且這個(gè)枚舉是可以手動(dòng)設(shè)置的。(可以理解為屏幕相對(duì)的home鍵方向)
UIInterfaceOrientation枚舉值如下:
// Note that UIInterfaceOrientationLandscapeLeft is equal to UIDeviceOrientationLandscapeRight (and vice versa).
// This is because rotating the device to the left requires rotating the content to the right.
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown,
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
}
二、如果你的App不支持屏幕旋轉(zhuǎn)欲低,有以下兩種方式處理
- 設(shè)置AppDelegate里的一下方法辕宏,返回值即為屏幕固定方向
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskLandscapeRight;
}
- General-Deployment Info-Device Orientation對(duì)支持的方向進(jìn)行勾選
兩種方式都可以觸發(fā)UIDeviceOrientationDidChangeNotification通知
三、如果你的App需要屏幕自適應(yīng)重力感應(yīng)進(jìn)行旋轉(zhuǎn)砾莱,并且需要針對(duì)每個(gè)VC進(jìn)行單獨(dú)控制
當(dāng)然這種情況你完全可以手動(dòng)地對(duì)每個(gè)控制器的view布局匾效,在監(jiān)聽(tīng)到UIDeviceOrientationDidChangeNotification通知后做旋轉(zhuǎn)處理。一兩個(gè)界面還好恤磷,如果控制多的話(huà)面哼,還是需要按一下方式處理
- General-Deployment Info-Device Orientation勾選所有支持的方向,代碼設(shè)置的支持旋轉(zhuǎn)方向都會(huì)在此基礎(chǔ)上
- 對(duì)項(xiàng)目中導(dǎo)航控制器的父控制器增加方法扫步,所有想說(shuō)的都在代碼里
// 是否支持屏幕旋轉(zhuǎn)
- (BOOL)shouldAutorotate
{
return self.topViewController.shouldAutorotate;
}
/**
適用于Push進(jìn)去的子類(lèi)調(diào)用
@return 屏幕支持的旋轉(zhuǎn)方向
*/
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return self.topViewController.supportedInterfaceOrientations;
}
/**
適用于modal進(jìn)去的子類(lèi)調(diào)用
@return 屏幕支持的旋轉(zhuǎn)方向
*/
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return self.topViewController.preferredInterfaceOrientationForPresentation;
}
- 在push的控制器中魔策,如果想關(guān)閉屏幕旋轉(zhuǎn),做如下操作
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
// 設(shè)置屏幕旋轉(zhuǎn)方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
// 設(shè)置是否支持屏幕旋轉(zhuǎn)
-(BOOL)shouldAutorotate
{
return NO;
}
- 如果想在另一個(gè)push的控制器再開(kāi)啟屏幕旋轉(zhuǎn)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return (toInterfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
// 設(shè)置屏幕旋轉(zhuǎn)方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
// 設(shè)置是否支持屏幕旋轉(zhuǎn)
-(BOOL)shouldAutorotate
{
return YES;
}
- 如果想在modal的控制器中河胎,關(guān)閉屏幕旋轉(zhuǎn)
// 設(shè)置屏幕是否支持旋轉(zhuǎn)
- (BOOL)shouldAutorotate
{
return NO;
}
// 設(shè)置屏幕方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
四闯袒、遇到的問(wèn)題
自己寫(xiě)了一個(gè)視頻錄制的控制器,本來(lái)是通過(guò)UIDeviceOrientationDidChangeNotification監(jiān)聽(tīng)手機(jī)旋轉(zhuǎn)方向來(lái)對(duì)視頻方向進(jìn)行調(diào)整游岳,實(shí)現(xiàn)視頻的橫豎屏錄制(視頻的方向枚舉AVCaptureVideoOrientation,有興趣的童鞋可以了解下)
typedef NS_ENUM(NSInteger, AVCaptureVideoOrientation) {
AVCaptureVideoOrientationPortrait = 1,
AVCaptureVideoOrientationPortraitUpsideDown = 2,
AVCaptureVideoOrientationLandscapeRight = 3,
AVCaptureVideoOrientationLandscapeLeft = 4,
}
但是如果系統(tǒng)禁止了屏幕旋轉(zhuǎn)功能政敢,通知就監(jiān)聽(tīng)不到旋轉(zhuǎn)了,原因是因?yàn)榇藭r(shí)系統(tǒng)會(huì)默認(rèn)你當(dāng)前的屏幕狀態(tài)一直都是你鎖屏?xí)r的狀態(tài)胚迫。
解決方法
目前大多數(shù)用戶(hù)的蘋(píng)果手機(jī)基本都有螺旋儀和加速器喷户,可以根據(jù)這個(gè)東西來(lái)判斷,這時(shí)候需要引入CoreMotion.framework這個(gè)框架访锻。
- 初始化一個(gè)螺旋儀對(duì)象
// 系統(tǒng)禁止屏幕旋轉(zhuǎn)后褪尝,可以監(jiān)聽(tīng)到屏幕方向
// 螺旋儀
@property (nonatomic, strong) CMMotionManager *motionManager;
- (void)initialMotionManager
{
if (_motionManager == nil)
{
_motionManager = [[CMMotionManager alloc] init];
}
// 提供設(shè)備運(yùn)動(dòng)數(shù)據(jù)到指定的時(shí)間間隔(輪詢(xún)間隔)
_motionManager.deviceMotionUpdateInterval = 0.3;
// 確定"是否使用任何可用的態(tài)度參考幀來(lái)決定設(shè)備的運(yùn)動(dòng)"是否可用?
if (_motionManager.deviceMotionAvailable)
{
// 啟動(dòng)設(shè)備的運(yùn)動(dòng)更新,通過(guò)給定的隊(duì)列向給定的處理程序提供數(shù)據(jù)
[_motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) {
// 調(diào)用處理函數(shù)
[self performSelectorOnMainThread:@selector(handleDeviceMotion:) withObject:motion waitUntilDone:YES];
}];
} else {
self.motionManager = nil;
}
}
- 根據(jù)重力感應(yīng)來(lái)判斷目前屏幕方向并可以做對(duì)應(yīng)處理
- (void)handleDeviceMotion:(CMDeviceMotion *)deviceMotion
{
double x = deviceMotion.gravity.x;
double y = deviceMotion.gravity.y;
// 豎屏
if (fabs(y) >= fabs(x))
{
// 這個(gè)地方注意
// if (y >= 0)
// {
// // UIDeviceOrientationPortraitUpsideDown;
// } else {
// // UIDeviceOrientationPortrait;
// }
self.recordOrientation = UIDeviceOrientationPortrait;
} else {
if (x >= 0)
{
self.recordOrientation = UIDeviceOrientationLandscapeRight;
} else {
self.recordOrientation = UIDeviceOrientationLandscapeLeft;
}
}
}
這里因?yàn)槲冶旧淼捻?xiàng)目需求期犬,只是全局記錄下了屏幕當(dāng)前方向河哑,然后KVO監(jiān)聽(tīng)recordOrientation,再對(duì)視頻錄制寫(xiě)入方向進(jìn)行處理龟虎。
- 注意一定要在控制器消失前璃谨,關(guān)閉輪詢(xún)。否則會(huì)造成內(nèi)存泄漏
// 關(guān)閉螺旋儀
[self.motionManager stopDeviceMotionUpdates];
至此鲤妥,所有我要說(shuō)的都表達(dá)完了佳吞。碼農(nóng)共勉!