iOS 獲取屏幕鎖定狀態(tài)

在開發(fā)中囊咏,有時候我們需要讓某些特定的頁面為橫屏展示毕贼,而從這個頁面離開或者進(jìn)入其他頁面時為豎屏,起初我僅僅依賴了UIViewController的屏幕旋轉(zhuǎn)方法簡單的處理况木,但是當(dāng)需求慢慢在變化時畅蹂,我發(fā)覺這并不能滿足我的需求:

比如導(dǎo)航頁需要橫屏展示健无,但是從導(dǎo)航頁上面某個按鈕跳轉(zhuǎn)的頁面需要豎屏展示,而再從這個頁面返回到導(dǎo)航頁時液斜,如果屏幕為豎屏且用戶關(guān)閉了屏幕旋轉(zhuǎn)鎖定累贤,則導(dǎo)航頁應(yīng)繼續(xù)展示橫屏。

下面筆記寫的比較亂少漆,可直接查看Demo in Github

屏幕旋轉(zhuǎn)的方案

我現(xiàn)在使用的解決方案是CMMotionManager臼膏,啟動設(shè)備的運(yùn)動更新,通過給定的隊列向給定的處理程序提供數(shù)據(jù)示损,對屏幕旋轉(zhuǎn)的監(jiān)測渗磅。

CMMotionManager可以理解為是CoreMotion Framework的中央管理器,也可以理解為運(yùn)動服務(wù)屎媳。這些服務(wù)提供了獲取加速機(jī)數(shù)據(jù)夺溢、旋轉(zhuǎn)數(shù)據(jù)和磁力數(shù)據(jù)等。

首先我在info.plist中把設(shè)備的方向只勾選了豎屏烛谊。

AppDelegate 中需要實現(xiàn)的方法

- (UIInterfaceOrientationMask)application:(UIApplication*)application supportedInterfaceOrientationsForWindow:(UIWindow*)window {
    // iPhone doesn't support upside down by default, while the iPad does.  Override to allow all orientations always, and let the root view controller decide what's allowed (the supported orientations mask gets intersected).
    
    UIViewController * presentdeVC = [self.class topViewControllerWithPresentedViewController];
    if ([presentdeVC isKindOfClass:NSClassFromString(@"NaviController")])
        return UIInterfaceOrientationMaskAllButUpsideDown;
    
    return UIInterfaceOrientationMaskPortrait;
}

監(jiān)聽設(shè)備運(yùn)動

/// 開啟屏幕旋轉(zhuǎn)的檢測
- (void)startListeningDirectionOfDevice {
    if (self.motionManager == nil) {
        self.motionManager = [[CMMotionManager alloc] init];
    }
    
    // 提供設(shè)備運(yùn)動數(shù)據(jù)到指定的時間間隔 刷新數(shù)據(jù)的評率
    self.motionManager.deviceMotionUpdateInterval = 0.3;
    
    // 判斷設(shè)備傳感器是否可用
    if (self.motionManager.deviceMotionAvailable) {
        // 啟動設(shè)備的運(yùn)動更新,通過給定的隊列向給定的處理程序提供數(shù)據(jù)嘉汰。
        [self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
            
            [self performSelectorOnMainThread:@selector(handleDeviceMotion:) withObject:motion waitUntilDone:YES];
        }];
    } else {
        [self setMotionManager:nil];
    }
}

停止監(jiān)聽設(shè)備運(yùn)動

- (void)stopListeningDirectionOfDevice {
    if (_motionManager) {
        [_motionManager stopDeviceMotionUpdates];
        _motionManager = nil;
    }
}

根據(jù)設(shè)備運(yùn)動丹禀,更新設(shè)備屏幕方向

- (void)handleDeviceMotion:(CMDeviceMotion *)deviceMotion {
    if ([UIDevice bb_canRotate] == false) {
        return;
    }
    
    double x = deviceMotion.gravity.x;
    double y = deviceMotion.gravity.y;
    
    if (fabs(y) >= fabs(x)) {// 豎屏
        if (y < 0) {
            if (self.previousInterfaceOrientation == UIInterfaceOrientationPortrait) {
                return;
            }
            [self applyInterfaceOrientation:UIInterfaceOrientationPortrait];
        }
        else {
            if (self.previousInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
                return;
            }
            [self applyInterfaceOrientation:UIInterfaceOrientationPortraitUpsideDown];
        }
    }
    else { // 橫屏
        if (x < 0) {
            if (self.previousInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
                return;
            }
            [self applyInterfaceOrientation:UIInterfaceOrientationLandscapeRight];
        }
        else {
            if (self.previousInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
                return;
            }
            [self applyInterfaceOrientation:UIInterfaceOrientationLandscapeLeft];
        }
    }
}

強(qiáng)制修改屏幕方向

- (void)applyInterfaceOrientation:(UIInterfaceOrientation)orientation {
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    
    UIDevice *currentDevice = [UIDevice currentDevice];
    UIDeviceOrientation currentDeviceOrientation = currentDevice.orientation;
    /// mark:強(qiáng)制旋轉(zhuǎn)有時無效的解決方案: 強(qiáng)制前先設(shè)置為UIDeviceOrientationUnknown
    [currentDevice setValue:@(UIDeviceOrientationUnknown) forKey:@"orientation"];
    
    SEL selector = NSSelectorFromString(@"setOrientation:");
    if (![currentDevice respondsToSelector:selector]) {
        return;
    }
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
    [invocation setSelector:selector];
    [invocation setTarget:currentDevice];
    // 從2開始是因為0 1 兩個參數(shù)已經(jīng)被selector和target占用
    [invocation setArgument:&orientation atIndex:2];
    [invocation invoke];
    [currentDevice endGeneratingDeviceOrientationNotifications];
    [UIDevice setForceOrientation:currentDeviceOrientation];
}

獲取屏幕鎖定狀態(tài)

現(xiàn)在存在的問題是,屏幕旋轉(zhuǎn)開關(guān)被鎖定時,橫屏狀態(tài)下不應(yīng)該可以旋轉(zhuǎn)頁面双泪,而Apple提供的api中持搜,并沒有獲取控制中心中屏幕旋轉(zhuǎn)鎖定的開關(guān)

通過監(jiān)聽UIDeviceOrientationDidChangeNotification通知測試:

  • 當(dāng)app在前臺時,如果屏幕旋轉(zhuǎn)開關(guān)鎖定了焙矛,怎么旋轉(zhuǎn)設(shè)備都不會觸發(fā)此通知葫盼,只有在app啟動、從后臺進(jìn)入前臺或者被激活時村斟,才會觸發(fā)此通知
  • 當(dāng)屏幕旋轉(zhuǎn)開關(guān)被關(guān)閉時贫导,設(shè)備旋轉(zhuǎn)時都會觸發(fā)此通知的

解決方法:

  • 注冊UIDeviceOrientationDidChangeNotification通知
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientaionDidChange:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]];
}
  • 當(dāng)觸發(fā)監(jiān)聽的方法時,根據(jù)設(shè)備的方向確定屏幕是否可以旋轉(zhuǎn)
/// 當(dāng)用戶鎖定了屏幕旋轉(zhuǎn)開關(guān)時蟆盹,且app在前臺時孩灯,設(shè)備旋轉(zhuǎn)不會觸發(fā)此通知,當(dāng)app啟動逾滥、從后臺進(jìn)入前臺或者被激活時峰档,都會觸發(fā)此通知
+ (void)deviceOrientaionDidChange:(NSNotification *)noty {
    self.forceOrientation = [UIDevice currentDevice].orientation;
    [InterfaceOrientationUtil sharedInsatnce].previousInterfaceOrientation = [UIApplication sharedApplication].statusBarOrientation;
    
    UIDevice *device = [UIDevice currentDevice] ;
    /**
     *  取得當(dāng)前Device的方向,Device的方向類型為Integer
     *
     *  必須調(diào)用beginGeneratingDeviceOrientationNotifications方法后寨昙,此orientation屬性才有效讥巡,否則一直是0。orientation用于判斷設(shè)備的朝向舔哪,與應(yīng)用UI方向無關(guān)
     *
     *  @param device.orientation
     *
     */
    NSLog(@"%@", noty.userInfo);
    
    switch (device.orientation) {
        case UIDeviceOrientationLandscapeLeft:
        case UIDeviceOrientationLandscapeRight:
            [self setBb_canRotate:YES];//只有當(dāng)用戶把手機(jī)旋轉(zhuǎn)到橫屏的時候來去觸發(fā)判斷是否支持橫屏
            break;
        default:
            [self setBb_canRotate:NO];
            break;
    }
}

在監(jiān)聽設(shè)備的運(yùn)動更新的方法中欢顷,根據(jù)canRotate判斷是否可以旋轉(zhuǎn)屏幕

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市尸红,隨后出現(xiàn)的幾起案子吱涉,更是在濱河造成了極大的恐慌,老刑警劉巖外里,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怎爵,死亡現(xiàn)場離奇詭異,居然都是意外死亡盅蝗,警方通過查閱死者的電腦和手機(jī)鳖链,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來墩莫,“玉大人芙委,你說我怎么就攤上這事】袂兀” “怎么了灌侣?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長裂问。 經(jīng)常有香客問我侧啼,道長牛柒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任痊乾,我火速辦了婚禮皮壁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘哪审。我一直安慰自己蛾魄,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布湿滓。 她就那樣靜靜地躺著滴须,像睡著了一般。 火紅的嫁衣襯著肌膚如雪茉稠。 梳的紋絲不亂的頭發(fā)上描馅,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機(jī)與錄音而线,去河邊找鬼铭污。 笑死,一個胖子當(dāng)著我的面吹牛膀篮,可吹牛的內(nèi)容都是我干的嘹狞。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼誓竿,長吁一口氣:“原來是場噩夢啊……” “哼磅网!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起筷屡,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤涧偷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后毙死,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體燎潮,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年扼倘,在試婚紗的時候發(fā)現(xiàn)自己被綠了确封。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡再菊,死狀恐怖爪喘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情纠拔,我是刑警寧澤秉剑,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站稠诲,受9級特大地震影響秃症,放射性物質(zhì)發(fā)生泄漏候址。R本人自食惡果不足惜吕粹,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一种柑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧匹耕,春花似錦聚请、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至既鞠,卻和暖如春煤傍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嘱蛋。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工蚯姆, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人洒敏。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓龄恋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親凶伙。 傳聞我的和親對象是個殘疾皇子郭毕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 在開發(fā)中,有時候我們需要讓某些特定的頁面為橫屏展示函荣,而從這個頁面離開或者進(jìn)入其他頁面時為豎屏显押,起初我僅僅依賴了UI...
    MTDeveloper閱讀 5,722評論 0 2
  • 關(guān)于屏幕旋轉(zhuǎn)需要理解兩個概念設(shè)備方向(UIDeviceOrientation)和屏幕方向(UIInterfaceO...
    騎馬縱天下閱讀 8,091評論 0 13
  • 專業(yè)考題類型管理運(yùn)行工作負(fù)責(zé)人一般作業(yè)考題內(nèi)容選項A選項B選項C選項D選項E選項F正確答案 變電單選GYSZ本規(guī)程...
    小白兔去釣魚閱讀 8,993評論 0 13
  • 1.開學(xué)練習(xí)普通話 3月中下旬考試 1.暑期社會實踐計劃 1.英語四級一定要過! 考蟲5月中旬到期 2.減肥 ...
    就靜靜聽你說閱讀 173評論 0 0
  • 世上最美麗的是媽媽 最善良的是媽媽 最可愛的是媽媽 最慈祥的是媽媽 最偉大的是媽媽 媽媽傻挂,多么親切的稱呼 可我不會...
    呂玥媽咪閱讀 201評論 1 0