Android 橫豎屏處理的知識(shí)小結(jié)
Android 手機(jī)一般都支持橫豎屏旋轉(zhuǎn),系統(tǒng)也會(huì)提供一個(gè)設(shè)置,控制允不允許旋轉(zhuǎn)。這里對(duì)如何在 App 中控制界面的旋轉(zhuǎn)方向做一個(gè)小結(jié)。
界面旋轉(zhuǎn)方向的決定因素
決定一個(gè)界面顯示為橫屏/豎屏的因素有幾個(gè):
- 系統(tǒng)的設(shè)置項(xiàng),一般可以設(shè)置為只允許豎屏或可旋轉(zhuǎn)切換。
- 設(shè)備的物理傳感器感應(yīng)到的設(shè)備方向。
- 不同 App 里的代碼對(duì)橫豎屏的設(shè)置。
需要注意的一點(diǎn)是,這三個(gè)因素沒(méi)有固定的優(yōu)先級(jí)。所以即使系統(tǒng)的設(shè)置項(xiàng)中設(shè)置了固定為豎屏,App 里的代碼也可以將界面設(shè)置為橫屏,當(dāng)然影響的范圍僅限于 App 內(nèi)部界面。
代碼中設(shè)置橫豎屏的方法
我們有2種方法設(shè)置橫豎屏:
在 AndroidManifest.xml 文件中,對(duì) <activity> 標(biāo)簽設(shè)置 android:screenOrientation 屬性,具體的值和作用見(jiàn)下文。
在 Java 中調(diào)用 Activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) ,具體的值和作用見(jiàn)下文。
如果在 xml 中設(shè)置,則在初始化界面時(shí)就已經(jīng)確定好其方向。而在如果 Java 中設(shè)置,則可以做到根據(jù)不同情況動(dòng)態(tài)設(shè)置。
設(shè)置橫豎屏?xí)r傳入的值和作用
以下列出在 AndroidManifest.xml 中 <activity> 標(biāo)簽的 android:screenOrientation 屬性的可能的值。如果采用 Java 方式設(shè)置,參數(shù)與之一一對(duì)應(yīng)。(參考官方文檔 )
- unspecified :默認(rèn)值,不做任何指定,由系統(tǒng)來(lái)決定顯示方向。這將由上一個(gè) activity 來(lái)決定,或者當(dāng) activity 處于棧底時(shí)由用戶設(shè)置的方向來(lái)決定。
- landscape : 保持橫屏。
- portrait : 保持豎屏。
- user : 用戶當(dāng)前設(shè)置的 orientation 值。
- behide : 保持和上一個(gè) Activity 的方向一致。
- sensor : 完全根據(jù)物理傳感器的方向來(lái)決定。注意用這個(gè)值時(shí)會(huì)忽略用戶在系統(tǒng)設(shè)置中的旋轉(zhuǎn)開(kāi)關(guān)狀態(tài)。(注意一般機(jī)器即使用這個(gè)值也不會(huì)支持豎屏旋轉(zhuǎn)180度)
- nosensor : 忽略物理傳感器的方向。這將導(dǎo)致用戶旋轉(zhuǎn)手機(jī)時(shí)不會(huì)切換橫豎屏。
- sensorLandscape : 保持橫屏,但可以根據(jù)物理傳感器來(lái)決定橫屏的方向。
- sensorPortrait : 保持豎屏,但可以根據(jù)物理傳感器來(lái)決定豎屏的方向。
- reverseLandscape : 保持橫屏,但方向與使用 landscape 時(shí)相反。
- reversePortrait : 保持豎屏,但方向與使用 portrait 時(shí)相反。
- fullSensor : 與 sensor 大致相同,區(qū)別在于這個(gè)屬性會(huì)允許4個(gè)方向都可以旋轉(zhuǎn)。
- userLandscape : 保持橫屏,但可以在用戶允許旋轉(zhuǎn)的情況下,根據(jù)物理傳感器來(lái)決定橫屏的方向。(注意與 sensorLandscape 對(duì)比)
- userPortrait : 保持豎屏,但可以在用戶允許旋轉(zhuǎn)的情況下,根據(jù)物理傳感器來(lái)決定豎屏的方向。(注意與 sensorPortrait 對(duì)比)
- fullUser : 與 user 大致相同,區(qū)別在于如果用戶允許旋轉(zhuǎn),這個(gè)屬性允許4個(gè)方向都可以旋轉(zhuǎn)。
- locked : 屏幕方向會(huì)鎖定在當(dāng)前方向,不能再旋轉(zhuǎn)。
該屬性的值有很多,但一般比較常用的幾個(gè)值也就幾個(gè): unspecified (允許旋轉(zhuǎn))、 landscape (固定為橫屏)、 portrait (固定為豎屏)。而且一般我們只需要在 AndroidManifest.xml 中指定好固定的值就可以了。除非你對(duì)橫豎屏切換有自己的一套邏輯,才需要在不同的邏輯下進(jìn)行不同的設(shè)置。
橫豎屏切換時(shí)引起的 Activity 重新創(chuàng)建
默認(rèn)情況下,橫豎屏切換會(huì)引起當(dāng)前 Activity 銷毀然后重新創(chuàng)建。所以我們可以在 Activity 重新創(chuàng)建時(shí)根據(jù)當(dāng)前橫豎屏狀態(tài)做一些差異化。最常見(jiàn)的就是根據(jù)橫豎屏采用不同的 layout xml。
在 res 目錄下建立 layout-land 和 layout-port 目錄,在不同目錄下分別放一個(gè)同名的 layout xml 文件,然后在代碼里正常使用這個(gè) layout 文件,系統(tǒng)就會(huì)在橫豎屏切換并重新創(chuàng)建 Activity 時(shí)自動(dòng)使用對(duì)應(yīng)的 layout 文件。如:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_layout); }
如果不想通過(guò)創(chuàng)建多個(gè) layout 文件來(lái)區(qū)分橫豎屏布局,也可以用 Java 代碼來(lái)做一些差異化,只要使用以下判斷即可獲取當(dāng)前橫豎屏的信息。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_layout); // 獲取橫豎屏信息 int orientation = getResources().getConfiguration().orientation; if (orientation == Configuration.ORIENTATION_LANDSCAPE) { // 針對(duì)橫屏做一些處理 } else if (orientation == Configuration.ORIENTATION_PORTRAIT) { // 針對(duì)豎屏做一些處理 } }
有一個(gè)點(diǎn)需要注意,關(guān)于 Activity 的生命周期被重新調(diào)用,有的資料說(shuō):
當(dāng)不設(shè)置 Activity 的 android:configChanges 屬性時(shí),切到橫屏?xí)r會(huì)重新執(zhí)行一次生命周期,而切到豎屏?xí)r會(huì)執(zhí)行兩次。
如果設(shè)置了 android:configChanges="orientation" 屬性,則都只會(huì)執(zhí)行一次。
但是個(gè)人實(shí)驗(yàn)沒(méi)有驗(yàn)證出這個(gè)說(shuō)法。保險(xiǎn)起見(jiàn),可以加上 android:configChanges="orientation" 屬性,確保生命周期只調(diào)用一次。
阻止橫豎屏切換時(shí) Activity 重啟
雖然我們可以用上面的方法對(duì)橫豎屏做不同的布局,但是橫豎屏切換導(dǎo)致的 Activity 重新創(chuàng)建還會(huì)引起用戶當(dāng)前狀態(tài)、數(shù)據(jù)的丟失。例如 EditText 中輸入到一半的文字在 Activity 重新創(chuàng)建后會(huì)丟失。所以如果有辦法能在旋轉(zhuǎn)屏幕時(shí)不重新創(chuàng)建 Activity,應(yīng)該是更好的一種選擇。
我們可以在 AndroidManifest.xml 中為相應(yīng)的 <activity> 設(shè)置 android:configChanges 屬性,讓它不在橫豎屏切換時(shí)引起 Activity 的重新創(chuàng)建。
Android 3.2(API Level 13)以前的 SDK 可以使用如下配置
android:configChanges="orientation|keyboardHidden"
而 Android 3.2 以后的 SDK 則需要設(shè)置為
android:configChanges="keyboardHidden|orientation|screenSize"
這樣一來(lái),橫豎屏切換時(shí) Activity 將不會(huì)重新創(chuàng)建。
橫豎屏切換時(shí)的回調(diào)
一旦我們按照上述方法設(shè)置了 android:configChanges 屬性,那么橫豎屏切換時(shí) Activity 將不會(huì)重新創(chuàng)建,那么當(dāng)屏幕旋轉(zhuǎn)時(shí),我們?cè)诖a上怎么感知呢?可以通過(guò) Override Activity 和 View 的 onConfigurationChanged 方法。
@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { // 針對(duì)橫屏做一些處理 } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){ // 針對(duì)豎屏做一些處理 } }
判斷當(dāng)前屏幕方向
有了上面的橫豎屏切換的回調(diào),我們就可以及時(shí)感知到屏幕的狀態(tài)變化。但因?yàn)樨Q屏、橫屏都有兩個(gè)不同的方向,所以 Android 系統(tǒng)又提供了方法給我們獲取當(dāng)前屏幕精確的旋轉(zhuǎn)方向。
Display display = activity.getWindowManager().getDefaultDisplay(); int rotation = display.getRotation(); // // rotation 的值表示了當(dāng)前屏幕的旋轉(zhuǎn)角度,可能的值有: // Surface.ROTATION_0、Surface.ROTATION_90、 // Surface.ROTATION_180、Surface.ROTATION_270。 //
這樣我們就可以判斷當(dāng)前屏幕的方向了。
舉個(gè)例子,以下方法獲取當(dāng)前屏幕的旋轉(zhuǎn)方向,然后將旋轉(zhuǎn)方向鎖定,使用戶不能再旋轉(zhuǎn)。
public static void lockScreenOrientation(Activity activity) { Display display = activity.getWindowManager().getDefaultDisplay(); switch (display.getRotation()) { case Surface.ROTATION_90: activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; case Surface.ROTATION_180: activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; case Surface.ROTATION_270: activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; default: activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } }
總結(jié)
- android:screenOrientation 屬性可以控制 Activity 的方向,常用的值有 unspecified (默認(rèn),可旋轉(zhuǎn))、 landscape (保持橫屏)、 portrait (保持豎屏)。
- 觸發(fā)橫豎屏切換時(shí),如果希望 Activity 銷毀并重新創(chuàng)建,則可以設(shè)置 Activity 的 android:configChanges="orientation" 。
- 觸發(fā)橫豎屏切換時(shí),如果不希望 Activity 銷毀并重新創(chuàng)建,可以設(shè)置 Activity 的 android:configChanges="keyboardHidden|orientation|screenSize" 。此后橫豎屏切換時(shí),可以在 Activity.onConfigurationChanged 或 View.onConfigurationChanged 方法中處理切換后的事情。
- 在任何時(shí)候可以用 getResources().getConfiguration().orientation 獲取屏幕的橫豎屏狀態(tài)。
- 在任何時(shí)候可以用 activity.getWindowManager().getDefaultDisplay().getRotation() 獲取屏幕的旋轉(zhuǎn)角度。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解Flutter桌面應(yīng)用如何進(jìn)行多分辨率適配
這篇文章主要為大家介紹了Flutter桌面應(yīng)用如何進(jìn)行多分辨率適配的方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Flutter框架解決盒約束widget和assets里加載資產(chǎn)技術(shù)
這篇文章主要為大家介紹了Flutter框架解決盒約束widget和assets里加載資產(chǎn)技術(shù)運(yùn)用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Android應(yīng)用中拍照后獲取照片路徑并上傳的實(shí)例分享
這篇文章主要介紹了Android應(yīng)用中拍照后獲取照片路徑并上傳的實(shí)例分享,文中使用MultipartEntityBuilder制作了一個(gè)簡(jiǎn)單的上傳工具,需要的朋友可以參考下2016-03-03Android應(yīng)用開(kāi)發(fā):電話監(jiān)聽(tīng)和錄音代碼示例
這篇文章主要介紹了Android應(yīng)用開(kāi)發(fā)中電話監(jiān)聽(tīng)和電話錄音的代碼實(shí)例,同時(shí)附錄了一個(gè)拍照、錄像的例子,需要的朋友可以參考下2014-04-04Android利用MPAndroidChart繪制曲線圖表的基礎(chǔ)教程
最近在項(xiàng)目中要用到曲線圖,于是在網(wǎng)上找了很多很多,有AChartengine,MPAndroidChart,helloChart等等,我還用過(guò)基于html5的jsChart來(lái)做過(guò),不過(guò)最終還是選擇了MPAndroidChart來(lái)做本文介紹了Android利用MPAndroidChart繪制曲線圖表的基礎(chǔ)教程,需要的朋友可以參考下。2018-03-03Android利用Badge組件實(shí)現(xiàn)未讀消息小紅點(diǎn)
在?App?的運(yùn)營(yíng)中,活躍度是一個(gè)重要的指標(biāo),日活/月活……為了提高活躍度,就發(fā)明了小紅點(diǎn)。這一篇,來(lái)介紹一個(gè)徽標(biāo)(Badge)組件,能夠快速搞定應(yīng)用內(nèi)的小紅點(diǎn),希望對(duì)大家有所幫助2023-01-01Android基于zxing的二維碼(網(wǎng)格)掃描 仿支付寶網(wǎng)格掃描
這篇文章主要為大家詳細(xì)介紹了Android基于zxing的二維碼網(wǎng)格掃描,仿支付寶網(wǎng)格掃描,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03Android利用Chronometer實(shí)現(xiàn)倒計(jì)時(shí)功能
這篇文章主要為大家詳細(xì)介紹了Android利用Chronometer實(shí)現(xiàn)倒計(jì)時(shí)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Android?Camera1實(shí)現(xiàn)預(yù)覽框顯示
這篇文章主要為大家詳細(xì)介紹了Android?Camera1實(shí)現(xiàn)預(yù)覽框顯示,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05Android Menu半透明效果的開(kāi)發(fā)實(shí)例
這篇文章主要介紹了Android Menu半透明效果方法的相關(guān)資料,需要的朋友可以參考下2016-09-09