今天項(xiàng)目中遇到一個(gè)問題,因?yàn)槲覀兊捻?xiàng)目有幾個(gè)視頻播放的界面裙犹,所以避不開與全屏/半屏按鈕伙判、鎖屏/解屏按鈕象对、方向傳感橫豎屏自動(dòng)變化打交道,我就被分到了這些任務(wù)宴抚。
先上一下大致的界面:
一般來說勒魔,涉及到能播放視頻的界面都大同小異(優(yōu)酷、愛奇藝等)菇曲,拋開彈幕冠绢、攝像頭、倍速羊娃、截屏唐全、截Gif等功能不談,幾乎都會(huì)有全屏/半屏播放蕊玷、鎖屏/解屏邮利、方向傳感這三個(gè)東西,而這三個(gè)東西都會(huì)牽涉到橫豎屏問題垃帅。
一開始的時(shí)候延届,我認(rèn)為很好做,也沒多想贸诚,覺得思路就是這樣:
⑴.全屏/半屏按鈕點(diǎn)擊邏輯:
監(jiān)測(cè)點(diǎn)擊全屏/半屏按鈕時(shí)方庭,用戶屏幕所處的橫豎位置,然后根據(jù)橫豎屏酱固,反向設(shè)置鎖定死用戶的屏幕:
/**
* 橫豎屏切換
*/
private void changeScreenOrientation() {
//獲取用戶當(dāng)前屏幕的橫豎位置
int currentOrientation = getResources().getConfiguration().orientation;
//判斷并設(shè)置用戶點(diǎn)擊全屏/半屏按鈕的顯示邏輯
if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
//如果屏幕當(dāng)前是橫屏顯示械念,則設(shè)置屏幕鎖死為豎屏顯示
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
//如果屏幕當(dāng)前是豎屏顯示,則設(shè)置屏幕鎖死為橫屏顯示
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
⑵.鎖屏按鈕點(diǎn)擊邏輯:
當(dāng)點(diǎn)擊鎖屏按鈕時(shí)运悲,設(shè)置手機(jī)忽略方向傳感龄减;當(dāng)點(diǎn)擊解屏按鈕時(shí),設(shè)置手機(jī)恢復(fù)方向傳感班眯。
/**
* 鎖定/解鎖屏幕點(diǎn)擊事件
*/
private void lockScreen(){
if(mLockBtn.isChecked()){
//鎖定屏幕
//忽略物理方向傳感器希停,這樣就不會(huì)隨著用戶旋轉(zhuǎn)設(shè)備而橫豎屏切換了
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
} else {
//解鎖屏幕
//由設(shè)備的物理方向傳感器決定烁巫,如果用戶旋轉(zhuǎn)設(shè)備,這屏幕就會(huì)橫豎屏切換
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
}
⑶.方向傳感橫豎屏自動(dòng)變化邏輯
直接把這個(gè)界面在清單文件下設(shè)計(jì)一下即可:
<!-- 測(cè)試橫豎屏視頻播放界面 -->
<activity
android:name=".modules.course.VodActivity"
android:configChanges="orientation|screenSize|layoutDirection"
android:screenOrientation="unspecified" />
但是誰知道里面的坑很深宠能,全然不是這么回事亚隙,寫完之后測(cè)試就找上門了,說:我沒鎖死屏幕违崇,點(diǎn)擊全屏播放了阿弃,為啥我又豎著拿手機(jī)屏幕不自動(dòng)切換回來了?
我擦亦歉,當(dāng)然不能自動(dòng)切換回來了恤浪,點(diǎn)擊全屏播放,我鎖死為手機(jī)橫屏了肴楷!
當(dāng)時(shí)覺得產(chǎn)品這個(gè)需求很不合理水由,又要全屏按鈕控制橫豎屏,又要小鎖按鈕控制橫豎屏赛蔫,還有手機(jī)方向感應(yīng)控制橫豎屏砂客,一旦我在代碼中強(qiáng)制設(shè)置屏幕的橫豎變化,不論是設(shè)置為ActivityInfo的哪個(gè)控制橫豎屏的值:
SCREEN_ORIENTATION_LANDSCAPE呵恢、
SCREEN_ORIENTATION_PORTRAIT鞠值、
SCREEN_ORIENTATION_SENSOR_LANDSCAPE、
SCREEN_ORIENTATION_SENSOR_PORTRAIT渗钉、
SCREEN_ORIENTATION_REVERSE_LANDSCAPE彤恶、
SCREEN_ORIENTATION_REVERSE_PORTRAIT、
SCREEN_ORIENTATION_USER_LANDSCAPE鳄橘、
SCREEN_ORIENTATION_USER_PORTRAIT
手機(jī)的方向感應(yīng)基本上算是都GG了声离。那點(diǎn)擊全屏/豎屏按鈕,強(qiáng)制設(shè)置了上面的值瘫怜,還怎么再讓手機(jī)方向感應(yīng)自動(dòng)變化呢术徊。
而且還有一個(gè)不合理的場(chǎng)景,如果用戶豎著拿手機(jī)鲸湃,點(diǎn)擊了界面的全屏播放赠涮,我設(shè)置界面為橫屏了,但此處如果方向傳感器還起作用的話暗挑,界面又立馬變回豎屏了笋除,那用戶覺得全屏按鈕還有啥作用呀。
:只能這么實(shí)現(xiàn)炸裆,沒法做到點(diǎn)擊全屏按鈕之后垃它,手機(jī)的方向傳感器還在繼續(xù)生效,就算繼續(xù)生效,也會(huì)立馬變回豎屏播放嗤瞎,相當(dāng)于全屏按鈕不好使。
:優(yōu)酷做出來了
:....
:愛奇藝也做出來了
:...那啥听系,我再看看吧贝奇。
下了個(gè)愛奇藝和優(yōu)酷,發(fā)現(xiàn)還真是做到了這個(gè)功能靠胜,他們的功能邏輯實(shí)現(xiàn)了方向感應(yīng)和全屏/半屏按鈕手動(dòng)設(shè)置的兼容掉瞳。對(duì)于上面的類似于功能沖突的點(diǎn),他們的做法是浪漠,如果用戶豎著拿手機(jī)陕习,點(diǎn)擊了界面的全屏播放,就會(huì)設(shè)置界面為橫屏顯示址愿,方向傳感器此時(shí)失效该镣,但是當(dāng)用戶拿著手機(jī)變化了一下位置,比如我豎著拿手機(jī)响谓,點(diǎn)擊了全屏损合,屏幕此時(shí)向左橫屏顯示,但是我拿著手機(jī)往右橫屏側(cè)過來娘纷,此時(shí)方向傳感器又起作用嫁审,把屏幕向右橫屏顯示。
好吧赖晶,用了一下午的時(shí)間在研究這個(gè)東西律适,發(fā)現(xiàn)不論怎么變換關(guān)鍵字,BD搜索到東西和這個(gè)功能沒一點(diǎn)關(guān)聯(lián)性遏插,全是在說怎么設(shè)置橫豎屏的問題捂贿,想念谷歌呀!
到后來自己摸索了一套方法涩堤,較為簡(jiǎn)單的解決了這個(gè)問題眷蜓!
首先必須得先了解一下ActivityInfo類的各個(gè)屬性值代表啥意思,不能亂用:
源碼:
@IntDef({
SCREEN_ORIENTATION_UNSET,
SCREEN_ORIENTATION_UNSPECIFIED,
SCREEN_ORIENTATION_LANDSCAPE,
SCREEN_ORIENTATION_PORTRAIT,
SCREEN_ORIENTATION_USER,
SCREEN_ORIENTATION_BEHIND,
SCREEN_ORIENTATION_SENSOR,
SCREEN_ORIENTATION_NOSENSOR,
SCREEN_ORIENTATION_SENSOR_LANDSCAPE,
SCREEN_ORIENTATION_SENSOR_PORTRAIT,
SCREEN_ORIENTATION_REVERSE_LANDSCAPE,
SCREEN_ORIENTATION_REVERSE_PORTRAIT,
SCREEN_ORIENTATION_FULL_SENSOR,
SCREEN_ORIENTATION_USER_LANDSCAPE,
SCREEN_ORIENTATION_USER_PORTRAIT,
SCREEN_ORIENTATION_FULL_USER,
SCREEN_ORIENTATION_LOCKED
})
挨個(gè)解釋一下(先找了這幾個(gè)胎围,剩下的有空搜到再一個(gè)個(gè)補(bǔ)充):
ActivityInfo屬性值 | 含義 |
---|---|
SCREEN_ORIENTATION_UNSET | |
SCREEN_ORIENTATION_UNSPECIFIED | 默認(rèn)值吁系,系統(tǒng)根據(jù)方向感應(yīng)自動(dòng)選擇屏幕方向 |
SCREEN_ORIENTATION_LANDSCAPE | 正向橫屏,顯示的寬比高長(zhǎng)(鎖死為橫屏方向白魂,不再讓方向感應(yīng)起作用) |
SCREEN_ORIENTATION_PORTRAIT | 正向豎屏汽纤,顯示的高比寬長(zhǎng)(鎖死為豎屏方向,不再讓方向感應(yīng)起作用) |
SCREEN_ORIENTATION_USER | 用戶當(dāng)前首選的方向 |
SCREEN_ORIENTATION_BEHIND | 這個(gè)有點(diǎn)奇葩福荸,它跟Activity堆棧中的下面一個(gè)Activity的方向一致 |
SCREEN_ORIENTATION_SENSOR | 由設(shè)備的方向傳感器決定蕴坪,如果用戶旋轉(zhuǎn)設(shè)備,這屏幕就會(huì)橫豎屏切換(這里要注意了:這個(gè)屬性有些強(qiáng)悍。大家知道安卓手機(jī)上都有一個(gè)“屏幕旋轉(zhuǎn)”按鈕背传,有的也叫“鎖定屏幕”隨便什么名字不管了呆瞻,這個(gè)設(shè)置里面的開關(guān)和Activity有密切關(guān)系。關(guān)閉它之后Activity界面就不能響應(yīng)方向傳感器了径玖,打開它才會(huì)恢復(fù)正常痴脾,挺合理的一個(gè)功能,讓決定權(quán)放在用戶手中梳星≡蘩担可一旦你設(shè)置了這個(gè)屬性,無論用戶怎么設(shè)置自己的手機(jī)上的“屏幕旋轉(zhuǎn)”按鈕冤灾,打開也好前域,關(guān)閉也好,Activity界面都會(huì)響應(yīng)方向傳感器的韵吨,會(huì)隨著用戶手持手機(jī)的方向自動(dòng)變化匿垄,這就讓用戶有點(diǎn)奇怪。) |
SCREEN_ORIENTATION_NOSENSOR | 忽略物理方向傳感器归粉,這樣就不會(huì)隨著用戶旋轉(zhuǎn)設(shè)備而橫豎屏切換了(這里有個(gè)坑:如果用戶橫屏拿著手機(jī)進(jìn)行播放年堆,界面也是橫屏的,一旦設(shè)置了這個(gè)屬性之后盏浇,手機(jī)界面會(huì)先變換到豎屏变丧,然后才會(huì)鎖死方向傳感器) |
SCREEN_ORIENTATION_SENSOR_LANDSCAPE | 橫屏,和上面它“爸爸”SENSOR一樣強(qiáng)悍绢掰,無視用戶手機(jī)設(shè)置的“屏幕旋轉(zhuǎn)”按鈕開關(guān)痒蓬,直接根據(jù)方向傳感器來切換正反向橫屏,但是不會(huì)切換到豎屏 |
SCREEN_ORIENTATION_SENSOR_PORTRAIT | 豎屏滴劲,和上面它“爸爸”SENSOR一樣強(qiáng)悍攻晒,無視用戶手機(jī)設(shè)置的“屏幕旋轉(zhuǎn)”按鈕開關(guān),直接根據(jù)方向傳感器來切換正反向豎屏班挖,不會(huì)切換到橫屏 |
SCREEN_ORIENTATION_REVERSE_LANDSCAPE | 反向橫屏鲁捏,橫屏分正向橫屏(靠左手方向橫屏)和反向橫屏(靠右手方向橫屏) |
SCREEN_ORIENTATION_REVERSE_PORTRAIT | 反向豎屏,就是和正常豎著拿手機(jī)相反萧芙,豎著掉了個(gè)個(gè) |
SCREEN_ORIENTATION_FULL_SENSOR | |
SCREEN_ORIENTATION_USER_LANDSCAPE | |
SCREEN_ORIENTATION_USER_PORTRAIT | |
SCREEN_ORIENTATION_FULL_USER | |
SCREEN_ORIENTATION_LOCKED | 鎖死用戶當(dāng)前屏幕给梅,方向傳感器不生效(這里也有一個(gè)坑,低版本不生效双揪,如vivo4.1动羽,你如果使用這個(gè)屬性來鎖定屏幕,它會(huì)直接變回到豎屏再鎖死) |
⑴首先先來分析全屏/半屏按鈕渔期,可以這么做:
還是順著之前的思路來走:
/**
* 橫豎屏切換
*/
private void changeScreenOrientation() {
//獲取用戶當(dāng)前屏幕的橫豎位置
int currentOrientation = getResources().getConfiguration().orientation;
//判斷并設(shè)置用戶點(diǎn)擊全屏/半屏按鈕的顯示邏輯
if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
//如果屏幕當(dāng)前是橫屏顯示运吓,則設(shè)置屏幕鎖死為豎屏顯示
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
//如果屏幕當(dāng)前是豎屏顯示渴邦,則設(shè)置屏幕鎖死為橫屏顯示
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
設(shè)置完之后呢,發(fā)現(xiàn)手機(jī)的方向感應(yīng)器失效了拘哨。那全屏半屏問題是解決了谋梭,
但是,最重要的事情也來了倦青,我們需要在一個(gè)正確的“點(diǎn)”上恢復(fù)手機(jī)的方向感應(yīng)器章蚣!
⑵怎么來找這個(gè)點(diǎn)呢?
我們來想姨夹,按照優(yōu)酷的那個(gè)實(shí)現(xiàn)方法,豎屏拿著手機(jī)矾策,點(diǎn)擊全屏按鈕之后磷账,切換到橫屏,此時(shí)如果用戶不移動(dòng)手機(jī)或者移動(dòng)的幅度不大贾虽,屏幕還是橫屏逃糟,一旦動(dòng)作過大(比如我把手機(jī)橫過來了),此時(shí)你會(huì)發(fā)現(xiàn)蓬豁,方向感應(yīng)器又好使了绰咽!
就這么來實(shí)現(xiàn)它!
在這里介紹一個(gè)監(jiān)聽器OrientationEventListener地粪,可以用它來監(jiān)聽用戶的手機(jī)位置變化情況:
OrientationEventListener orientationListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {
@Override
public void onOrientationChanged(int orientation) {
if(orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
//手機(jī)平放時(shí)取募,檢測(cè)不到有效的角度
return;
}
/**
* 只檢測(cè)是否有四個(gè)角度的改變
*/
if(orientation > 350 || orientation< 10) {
//0度,用戶豎直拿著手機(jī)
} else if(orientation > 80 && orientation < 100) {
//90度蟆技,用戶右側(cè)(正向)橫屏拿著手機(jī)
} else if(orientation > 170 && orientation < 190) {
//180度玩敏,用戶反向豎直拿著手機(jī)
} else if(orientation > 260 && orientation < 280) {
//270度,用戶左側(cè)(反向)橫屏拿著手機(jī)
}
}
};
對(duì)應(yīng)的具體方位圖:
有了這個(gè)監(jiān)聽器砰粹,就變得很簡(jiǎn)單了。
我們可以這樣造挽,在onOrientationChanged(int orientation)實(shí)時(shí)記錄用戶的位置碱璃,看是否與記錄的用戶手機(jī)上一次手機(jī)所處的位置發(fā)生了改變,如果改變了饭入,則用戶手機(jī)發(fā)生了很大的位置偏移厘贼,就需要恢復(fù)用戶手機(jī)的方向傳感器。
@Override
public void onOrientationChanged(int orientation) {
//判null
if(mActivity == null || mActivity.isFinishing()){
return;
}
//記錄用戶手機(jī)上一次放置的位置
int mLastOrientation = mOrientation;
if(orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
//手機(jī)平放時(shí)圣拄,檢測(cè)不到有效的角度
//重置為原始位置 -1
mOrientation = -1;
return;
}
/**
* 只檢測(cè)是否有四個(gè)角度的改變
*/
if(orientation > 350 || orientation< 10) {
//0度嘴秸,用戶豎直拿著手機(jī)
mOrientation = 0;
} else if(orientation > 80 && orientation < 100) {
//90度,用戶右側(cè)橫屏拿著手機(jī)
mOrientation = 90;
} else if(orientation > 170 && orientation < 190) {
//180度,用戶反向豎直拿著手機(jī)
mOrientation = 180;
} else if(orientation > 260 && orientation < 280) {
//270度岳掐,用戶左側(cè)橫屏拿著手機(jī)
mOrientation = 270;
}
//如果用戶鎖定了屏幕凭疮,不再開啟代碼自動(dòng)旋轉(zhuǎn)了,直接return
if(mIsLock){
return;
}
//如果用戶關(guān)閉了手機(jī)的屏幕旋轉(zhuǎn)功能串述,不再開啟代碼自動(dòng)旋轉(zhuǎn)了执解,直接return
try {
/**
* 1 手機(jī)已開啟屏幕旋轉(zhuǎn)功能
* 0 手機(jī)未開啟屏幕旋轉(zhuǎn)功能
*/
if(Settings.System.getInt(getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 0){
return;
}
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
//當(dāng)檢測(cè)到用戶手機(jī)位置距離上一次記錄的手機(jī)位置發(fā)生了改變,開啟屏幕自動(dòng)旋轉(zhuǎn)
if(mLastOrientation != mOrientation){
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
}
大頭搞定纲酗,剩下的就簡(jiǎn)單了衰腌,完善其他小邏輯。
⑶手機(jī)本身的方向傳感器
這個(gè)簡(jiǎn)單觅赊,可以直接在AndroidManifest.xml中設(shè)置SCREEN_ORIENTATION_UNSPECIFIED屬性就可以了右蕊,剩下的,交給OrientationEventListener和小鎖的邏輯重新對(duì)其賦值即可
<activity
android:name=".modules.course.DemoActivity"
android:configChanges="orientation|screenSize|layoutDirection"
android:screenOrientation="unspecified" />
⑷小鎖的邏輯
檢測(cè)下小鎖的開關(guān)是否打開吮螺,如果打開饶囚,就放開手機(jī)方向感應(yīng)器(前提是用戶打開了自己手機(jī)上的自動(dòng)旋轉(zhuǎn));如果關(guān)閉鸠补,就是鎖死手機(jī)方向感應(yīng)器:
/**
* 鎖定/解鎖屏幕點(diǎn)擊事件
*/
private void lockScreen(){
if(mLockBtn.isChecked()){
//鎖定屏幕
//獲取用戶當(dāng)前屏幕的橫豎位置
int currentOrientation = getResources().getConfiguration().orientation;
//判斷并設(shè)置用戶點(diǎn)擊鎖定屏幕按鈕的顯示邏輯
if(currentOrientation == Configuration.ORIENTATION_LANDSCAPE){
//如果屏幕當(dāng)前是橫屏顯示萝风,則設(shè)置屏幕鎖死為橫屏顯示
if(mMyOrientationDetector.getDisplayRotation() == 90){
//正向橫屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if(mMyOrientationDetector.getDisplayRotation() == 270){
//反向橫屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
}
} else if(currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
//如果屏幕當(dāng)前是豎屏顯示,則設(shè)置屏幕鎖死為豎屏顯示
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
} else {
//解鎖屏幕
try {
/**
* 1 手機(jī)已開啟屏幕旋轉(zhuǎn)功能
* 0 手機(jī)未開啟屏幕旋轉(zhuǎn)功能
*/
if(Settings.System.getInt(getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 1){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
}
}
其中紫岩,getDisplayRotation() 是一個(gè)檢測(cè)手機(jī)正反向橫豎屏的方法:
/**
* 獲取當(dāng)前屏幕旋轉(zhuǎn)角度
*
* @return
*
* 0 - 表示是豎屏 90 - 表示是左橫屏(正向) 180 - 表示是反向豎屏 270表示是右橫屏(反向)
*/
public int getDisplayRotation() {
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
switch (rotation) {
case Surface.ROTATION_0:
return 0;
case Surface.ROTATION_90:
return 90;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_270:
return 270;
}
return 0;
}
這里在贅述一點(diǎn)规惰,當(dāng)時(shí)我想的是:
①鎖定屏幕,直接設(shè)置SCREEN_ORIENTATION_NOSENSOR泉蝌,不再這么麻煩的先去判斷屏幕正反向橫豎屏卿拴,再去分別鎖死,但是這里面具體實(shí)現(xiàn)起來發(fā)現(xiàn)了個(gè)坑梨与,如果用戶橫屏拿著手機(jī)進(jìn)行播放堕花,界面也是橫屏的,一旦設(shè)置了這個(gè)屬性之后粥鞋,手機(jī)界面會(huì)先變換到豎屏缘挽,然后才會(huì)鎖死方向傳感器。
②鎖定屏幕呻粹,直接設(shè)置SCREEN_ORIENTATION_LOCKED壕曼,不再這么麻煩的先去判斷屏幕正反向橫豎屏,再去分別鎖死等浊,但是這里面也發(fā)現(xiàn)了個(gè)坑腮郊,這個(gè)屬性在低版本手機(jī)上不生效,它也會(huì)直接變回到豎屏再鎖死
③鎖定屏幕筹燕,判斷橫豎屏再進(jìn)行鎖死:
if(mLockBtn.isChecked()){
//鎖定屏幕
//獲取用戶當(dāng)前屏幕的橫豎位置
int currentOrientation = getResources().getConfiguration().orientation;
//判斷并設(shè)置用戶點(diǎn)擊鎖定屏幕按鈕的顯示邏輯
if(currentOrientation == Configuration.ORIENTATION_LANDSCAPE){
//如果屏幕當(dāng)前是橫屏顯示轧飞,則設(shè)置屏幕鎖死為橫屏顯示
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if(currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
//如果屏幕當(dāng)前是豎屏顯示衅鹿,則設(shè)置屏幕鎖死為豎屏顯示
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
但是這樣的話,也有一個(gè)bug:
我在上面介紹各個(gè)屬性的時(shí)候过咬,說過橫屏分為正向橫屏和反向橫屏大渤,豎屏同理。
此時(shí)如果用戶是反向橫屏拿著手機(jī)的掸绞,代碼這么寫的話泵三,直接設(shè)置SCREEN_ORIENTATION_LANDSCAPE,手機(jī)屏幕會(huì)直接翻轉(zhuǎn)到正向橫屏再鎖死衔掸,讓用戶感到奇怪烫幕。
以上就是我做鎖定屏幕的時(shí)候,經(jīng)歷的種種探索敞映,感覺好麻煩较曼,但是做出來還是挺開心的。
OK驱显,到了這里,就把三個(gè)邏輯融合到一起了瞳抓。最后再優(yōu)化優(yōu)化邏輯(大體思路就是上面的這些東西)埃疫、封裝成一個(gè)工具類:
/**
* 自定義工具類
*
* 實(shí)時(shí)的檢測(cè)用戶屏幕的位置改變,做到 重力感應(yīng) 與 全屏/半屏按鈕 邏輯的互容
*/
public class CLOrientationDetector extends OrientationEventListener {
/**
* 橫豎屏BaseActivity
*/
private BaseActivity mActivity;
/**
* 用戶是否鎖定屏幕
*/
private boolean mIsLock = false;
/**
* 實(shí)時(shí)記錄用戶手機(jī)屏幕的位置
*/
private int mOrientation = -1;
/**
* 構(gòu)造方法
* @param activity
*/
public CLOrientationDetector(BaseActivity activity) {
super(activity);
mActivity = activity;
}
/**
* 設(shè)置用戶屏幕是否被鎖定
* @param isLock
*/
public void setIsLock(boolean isLock){
mIsLock = isLock;
}
@Override
public void onOrientationChanged(int orientation) {
//判null
if(mActivity == null || mActivity.isFinishing()){
return;
}
//記錄用戶手機(jī)上一次放置的位置
int mLastOrientation = mOrientation;
if(orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
//手機(jī)平放時(shí)孩哑,檢測(cè)不到有效的角度
//重置為原始位置 -1
mOrientation = -1;
return;
}
/**
* 只檢測(cè)是否有四個(gè)角度的改變
*/
if(orientation > 350 || orientation< 10) {
//0度栓霜,用戶豎直拿著手機(jī)
mOrientation = 0;
} else if(orientation > 80 && orientation < 100) {
//90度,用戶右側(cè)橫屏拿著手機(jī)
mOrientation = 90;
} else if(orientation > 170 && orientation < 190) {
//180度横蜒,用戶反向豎直拿著手機(jī)
mOrientation = 180;
} else if(orientation > 260 && orientation < 280) {
//270度胳蛮,用戶左側(cè)橫屏拿著手機(jī)
mOrientation = 270;
}
//如果用戶鎖定了屏幕,不再開啟代碼自動(dòng)旋轉(zhuǎn)了丛晌,直接return
if(mIsLock){
return;
}
//如果用戶關(guān)閉了手機(jī)的屏幕旋轉(zhuǎn)功能仅炊,不再開啟代碼自動(dòng)旋轉(zhuǎn)了,直接return
try {
/**
* 1 手機(jī)已開啟屏幕旋轉(zhuǎn)功能
* 0 手機(jī)未開啟屏幕旋轉(zhuǎn)功能
*/
if(Settings.System.getInt(mActivity.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 0){
return;
}
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
//當(dāng)檢測(cè)到用戶手機(jī)位置距離上一次記錄的手機(jī)位置發(fā)生了改變澎蛛,開啟屏幕自動(dòng)旋轉(zhuǎn)
if(mLastOrientation != mOrientation){
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
}
/**
* 獲取當(dāng)前屏幕旋轉(zhuǎn)角度
*
* @return
*
* 0 - 表示是豎屏 90 - 表示是左橫屏(正向) 180 - 表示是反向豎屏 270表示是右橫屏(反向)
*/
public int getDisplayRotation() {
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
switch (rotation) {
case Surface.ROTATION_0:
return 0;
case Surface.ROTATION_90:
return 90;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_270:
return 270;
}
return 0;
}
}
這篇文章說的比較簡(jiǎn)單抚垄,主要想表明的就是這個(gè)思路,思路有了谋逻,就上手代碼就容易了呆馁。小伙伴們?nèi)绻懈玫乃悸返脑挘瑲g迎指正毁兆。