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()
獲取螢幕的旋轉角度。
相關文章
- Android 拍攝(橫 豎屏)視訊的懶人之路Android
- Android開發之平板和橫豎屏適配-RecyclerViewAndroidView
- 短視訊開發app,Android 強制應用全域性橫屏或豎屏APPAndroid
- js監聽手機橫豎屏事件JS事件
- Activity橫豎屏切換生命週期
- Swift橫豎屏切換、自動旋轉螢幕、手動旋轉螢幕、鎖定當前螢幕禁止轉屏、橫豎屏頁面跳轉過度、橫豎屏UI適配SwiftUI
- 40 橫豎屏切換略縮圖不能定位
- [iOS]終極橫豎屏切換解決方案iOS
- unity 動態修改當前橫豎屏狀態Unity
- 投屏成功後,手機橫屏切豎屏小窗畫面向右偏移
- 直播電商平臺開發,橫豎屏切換的方法
- uniapp 小程式橫屏的方式APP
- Android技能樹 — 樹基礎知識小結(一)Android
- 直播系統搭建,判斷螢幕橫豎屏狀態
- Android音訊處理知識(一)MediaRecorder錄製音訊Android音訊
- 汽車之家原影片怎樣一鍵採集,批次橫屏改豎屏?
- 前端須知的 Cookie 知識小結前端Cookie
- Flex知識小結Flex
- 前端 H5 橫屏 獨特處理方案詳解前端H5
- T113啟動G2D旋轉豎屏當作橫屏使用
- 線上直播系統原始碼,強制應用全域性橫屏或豎屏原始碼
- Infrastructure 知識: dnf對module的處理ASTStruct
- 處理器基礎知識
- 總結的小知識點(一)
- makefile 知識點小結
- 【JAVA】- 知識點小結Java
- Vue重要知識小結Vue
- promise知識點小結Promise
- Android華為凹口屏適配小結Android
- 是豎屏簡易操作還是橫屏精細玩法?休閒手遊的近期走向觀察
- Android小知識-Java多執行緒的基礎知識瞭解下AndroidJava執行緒
- node知識點小結(一)
- 想要將多個橫版格式的視訊調整成豎版有什麼快速的處理方式嗎?
- 短視訊app開發,視訊、直播畫面跟隨手機橫屏、豎屏移動APP
- Android小知識-定時任務ScheduledThreadPoolExecutorAndroidthread
- Linux檔案管理知識:文字處理Linux
- 線性表的理論知識總結
- 有關Es6知識的小結