Android 橫豎屏處理的知識小結
Android 手機一般都支援橫豎屏旋轉,系統也會提供一個設定,控制允不允許旋轉。這裡對如何在 App 中控制介面的旋轉方向做一個小結。
介面旋轉方向的決定因素
決定一個介面顯示為橫屏/豎屏的因素有幾個:
- 系統的設定項,一般可以設定為只允許豎屏或可旋轉切換。
- 裝置的物理感測器感應到的裝置方向。
- 不同 App 裡的程式碼對橫豎屏的設定。
需要注意的一點是,這三個因素沒有固定的優先順序。所以即使系統的設定項中設定了固定為豎屏,App 裡的程式碼也可以將介面設定為橫屏,當然影響的範圍僅限於 App 內部介面。
程式碼中設定橫豎屏的方法
我們有2種方法設定橫豎屏:
- 在
AndroidManifest.xml
檔案中,對<activity>
標籤設定android:screenOrientation
屬性,具體的值和作用見下文。 - 在 Java 中呼叫
Activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
,具體的值和作用見下文。
如果在 xml 中設定,則在初始化介面時就已經確定好其方向。而在如果 Java 中設定,則可以做到根據不同情況動態設定。
設定橫豎屏時傳入的值和作用
以下列出在 AndroidManifest.xml
中 <activity>
標籤的 android:screenOrientation
屬性的可能的值。如果採用 Java 方式設定,引數與之一一對應。(參考 官方文件)
-
unspecified
:預設值,不做任何指定,由系統來決定顯示方向。這將由上一個 activity 來決定,或者當 activity 處於棧底時由使用者設定的方向來決定。 -
landscape
: 保持橫屏。 -
portrait
: 保持豎屏。 -
user
: 使用者當前設定的 orientation 值。 -
behide
: 保持和上一個 Activity 的方向一致。 -
sensor
: 完全根據物理感測器的方向來決定。注意用這個值時會忽略使用者在系統設定中的旋轉開關狀態。(注意一般機器即使用這個值也不會支援豎屏旋轉180度) -
nosensor
: 忽略物理感測器的方向。這將導致使用者旋轉手機時不會切換橫豎屏。 -
sensorLandscape
: 保持橫屏,但可以根據物理感測器來決定橫屏的方向。 -
sensorPortrait
: 保持豎屏,但可以根據物理感測器來決定豎屏的方向。 -
reverseLandscape
: 保持橫屏,但方向與使用landscape
時相反。 -
reversePortrait
: 保持豎屏,但方向與使用portrait
時相反。 -
fullSensor
: 與sensor
大致相同,區別在於這個屬性會允許4個方向都可以旋轉。 -
userLandscape
: 保持橫屏,但可以在使用者允許旋轉的情況下,根據物理感測器來決定橫屏的方向。(注意與sensorLandscape
對比) -
userPortrait
: 保持豎屏,但可以在使用者允許旋轉的情況下,根據物理感測器來決定豎屏的方向。(注意與sensorPortrait
對比) -
fullUser
: 與user
大致相同,區別在於如果使用者允許旋轉,這個屬性允許4個方向都可以旋轉。 -
locked
: 螢幕方向會鎖定在當前方向,不能再旋轉。
該屬性的值有很多,但一般比較常用的幾個值也就幾個:unspecified
(允許旋轉)、landscape
(固定為橫屏)、portrait
(固定為豎屏)。而且一般我們只需要在 AndroidManifest.xml
中指定好固定的值就可以了。除非你對橫豎屏切換有自己的一套邏輯,才需要在不同的邏輯下進行不同的設定。
橫豎屏切換時引起的 Activity 重新建立
預設情況下,橫豎屏切換會引起當前 Activity 銷燬然後重新建立。所以我們可以在 Activity 重新建立時根據當前橫豎屏狀態做一些差異化。最常見的就是根據橫豎屏採用不同的 layout xml。
-
在
res
目錄下建立layout-land
和layout-port
目錄,在不同目錄下分別放一個同名的 layout xml 檔案,然後在程式碼里正常使用這個 layout 檔案,系統就會在橫豎屏切換並重新建立 Activity 時自動使用對應的 layout 檔案。如:@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_layout); }
-
如果不想通過建立多個 layout 檔案來區分橫豎屏佈局,也可以用 Java 程式碼來做一些差異化,只要使用以下判斷即可獲取當前橫豎屏的資訊。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_layout); // 獲取橫豎屏資訊 int orientation = getResources().getConfiguration().orientation; if (orientation == Configuration.ORIENTATION_LANDSCAPE) { // 針對橫屏做一些處理 } else if (orientation == Configuration.ORIENTATION_PORTRAIT) { // 針對豎屏做一些處理 } }
有一個點需要注意,關於 Activity 的生命週期被重新呼叫,有的資料說:
當不設定 Activity 的
android:configChanges
屬性時,切到橫屏時會重新執行一次生命週期,而切到豎屏時會執行兩次。
如果設定了android:configChanges="orientation"
屬性,則都只會執行一次。
但是個人實驗沒有驗證出這個說法。保險起見,可以加上 android:configChanges="orientation"
屬性,確保生命週期只呼叫一次。
阻止橫豎屏切換時 Activity 重啟
雖然我們可以用上面的方法對橫豎屏做不同的佈局,但是橫豎屏切換導致的 Activity 重新建立還會引起使用者當前狀態、資料的丟失。例如 EditText
中輸入到一半的文字在 Activity 重新建立後會丟失。所以如果有辦法能在旋轉螢幕時不重新建立 Activity,應該是更好的一種選擇。
我們可以在 AndroidManifest.xml
中為相應的 <activity>
設定android:configChanges
屬性,讓它不在橫豎屏切換時引起 Activity 的重新建立。
Android 3.2(API Level 13)以前的 SDK 可以使用如下配置android:configChanges="orientation|keyboardHidden"
而 Android 3.2 以後的 SDK 則需要設定為android:configChanges="keyboardHidden|orientation|screenSize"
這樣一來,橫豎屏切換時 Activity 將不會重新建立。
橫豎屏切換時的回撥
一旦我們按照上述方法設定了 android:configChanges
屬性,那麼橫豎屏切換時 Activity 將不會重新建立,那麼當螢幕旋轉時,我們在程式碼上怎麼感知呢?可以通過 Override Activity
和 View
的 onConfigurationChanged
方法。
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// 針對橫屏做一些處理
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
// 針對豎屏做一些處理
}
}
判斷當前螢幕方向
有了上面的橫豎屏切換的回撥,我們就可以及時感知到螢幕的狀態變化。但因為豎屏、橫屏都有兩個不同的方向,所以 Android 系統又提供了方法給我們獲取當前螢幕精確的旋轉方向。
Display display = activity.getWindowManager().getDefaultDisplay();
int rotation = display.getRotation();
//
// rotation 的值表示了當前螢幕的旋轉角度,可能的值有:
// Surface.ROTATION_0、Surface.ROTATION_90、
// Surface.ROTATION_180、Surface.ROTATION_270。
//
這樣我們就可以判斷當前螢幕的方向了。
舉個例子,以下方法獲取當前螢幕的旋轉方向,然後將旋轉方向鎖定,使使用者不能再旋轉。
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);
}
}
總結
-
android:screenOrientation
屬性可以控制 Activity 的方向,常用的值有unspecified
(預設,可旋轉)、landscape
(保持橫屏)、portrait
(保持豎屏)。 - 觸發橫豎屏切換時,如果希望 Activity 銷燬並重新建立,則可以設定 Activity 的
android:configChanges="orientation"
。 - 觸發橫豎屏切換時,如果不希望 Activity 銷燬並重新建立,可以設定 Activity 的
android:configChanges="keyboardHidden|orientation|screenSize"
。此後橫豎屏切換時,可以在Activity.onConfigurationChanged
或View.onConfigurationChanged
方法中處理切換後的事情。 - 在任何時候可以用
getResources().getConfiguration().orientation
獲取螢幕的橫豎屏狀態。 - 在任何時候可以用
activity.getWindowManager().getDefaultDisplay().getRotation()
獲取螢幕的旋轉角度。
相關文章
- 程式碼處理 iOS 的橫豎屏旋轉iOS
- Android橫豎屏切換Android
- activity橫屏豎屏
- iOS橫豎屏iOS
- iOS 橫豎屏旋轉總結iOS
- 檢測橫屏豎屏程式碼
- iOS 橫豎屏切換iOS
- App中橫豎屏的設定APP
- Android 拍攝(橫 豎屏)視訊的懶人之路Android
- Android 拍攝(橫 \ 豎屏)視訊的懶人之路Android
- 匹配橫屏或者豎屏css程式碼例項CSS
- android-Fragment橫豎屏翻轉對重新載入的要求AndroidFragment
- 你還在問android橫豎屏切換的生命週期?Android
- Android在橫豎屏切換時到底發生了什麼?Android
- Activity橫豎屏切換生命週期
- js監聽手機橫豎屏事件JS事件
- 橫屏和豎屏切換介面不重新整理
- Android系統橫豎屏切換時候Activity的生命週期Android
- 短視訊開發app,Android 強制應用全域性橫屏或豎屏APPAndroid
- 投屏成功後,手機橫屏切豎屏小窗畫面向右偏移
- [iOS]終極橫豎屏切換解決方案iOS
- unity 動態修改當前橫豎屏狀態Unity
- android轉屏,切換螢幕,橫豎屏(onConfigurationChanged)會重新 OnCreate 的解決方案Android
- 直播電商平臺開發,橫豎屏切換的方法
- dialog橫豎屏切換時消失的解決方法
- 關於處理死鎖的一點小知識
- 橫豎屏切換中的介面設計與體驗提升
- 直播系統搭建,判斷螢幕橫豎屏狀態
- 關於iPad應用強制橫豎屏問題iPad
- 純CSS(media queries)實現移動端橫豎屏提示CSS
- Flex知識小結Flex
- 小知識總結
- 線上直播系統原始碼,強制應用全域性橫屏或豎屏原始碼
- 前端須知的 Cookie 知識小結前端Cookie
- Android處理圖片OOM的若干方法小結AndroidOOM
- Android小知識庫Android
- 前端 H5 橫屏 獨特處理方案詳解前端H5
- perl橫豎轉換