Android 手機一般都支持橫豎屏旋轉,系統(tǒng)也會提供一個設置,控制允不允許旋轉。這里對如何在 App 中控制界面的旋轉方向做一個小結。
界面旋轉方向的決定因素
決定一個界面顯示為橫屏/豎屏的因素有幾個:
- 系統(tǒng)的設置項,一般可以設置為只允許豎屏或可旋轉切換。
- 設備的物理傳感器感應到的設備方向。
- 不同 App 里的代碼對橫豎屏的設置。
需要注意的一點是,這三個因素沒有固定的優(yōu)先級。所以即使系統(tǒng)的設置項中設置了固定為豎屏,App 里的代碼也可以將界面設置為橫屏,當然影響的范圍僅限于 App 內部界面。
代碼中設置橫豎屏的方法
我們有2種方法設置橫豎屏:
在 AndroidManifest.xml 文件中,對 <activity> 標簽設置 android:screenOrientation 屬性,具體的值和作用見下文。
在 Java 中調用 Activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) ,具體的值和作用見下文。
如果在 xml 中設置,則在初始化界面時就已經(jīng)確定好其方向。而在如果 Java 中設置,則可以做到根據(jù)不同情況動態(tài)設置。
設置橫豎屏時傳入的值和作用
以下列出在 AndroidManifest.xml 中 <activity> 標簽的 android:screenOrientation 屬性的可能的值。如果采用 Java 方式設置,參數(shù)與之一一對應。(參考官方文檔 )
- unspecified :默認值,不做任何指定,由系統(tǒng)來決定顯示方向。這將由上一個 activity 來決定,或者當 activity 處于棧底時由用戶設置的方向來決定。
- landscape : 保持橫屏。
- portrait : 保持豎屏。
- user : 用戶當前設置的 orientation 值。
- behide : 保持和上一個 Activity 的方向一致。
- sensor : 完全根據(jù)物理傳感器的方向來決定。注意用這個值時會忽略用戶在系統(tǒng)設置中的旋轉開關狀態(tài)。(注意一般機器即使用這個值也不會支持豎屏旋轉180度)
- nosensor : 忽略物理傳感器的方向。這將導致用戶旋轉手機時不會切換橫豎屏。
- sensorLandscape : 保持橫屏,但可以根據(jù)物理傳感器來決定橫屏的方向。
- sensorPortrait : 保持豎屏,但可以根據(jù)物理傳感器來決定豎屏的方向。
- reverseLandscape : 保持橫屏,但方向與使用 landscape 時相反。
- reversePortrait : 保持豎屏,但方向與使用 portrait 時相反。
- fullSensor : 與 sensor 大致相同,區(qū)別在于這個屬性會允許4個方向都可以旋轉。
- userLandscape : 保持橫屏,但可以在用戶允許旋轉的情況下,根據(jù)物理傳感器來決定橫屏的方向。(注意與 sensorLandscape 對比)
- userPortrait : 保持豎屏,但可以在用戶允許旋轉的情況下,根據(jù)物理傳感器來決定豎屏的方向。(注意與 sensorPortrait 對比)
- fullUser : 與 user 大致相同,區(qū)別在于如果用戶允許旋轉,這個屬性允許4個方向都可以旋轉。
- locked : 屏幕方向會鎖定在當前方向,不能再旋轉。
該屬性的值有很多,但一般比較常用的幾個值也就幾個: unspecified (允許旋轉)、 landscape (固定為橫屏)、 portrait (固定為豎屏)。而且一般我們只需要在 AndroidManifest.xml 中指定好固定的值就可以了。除非你對橫豎屏切換有自己的一套邏輯,才需要在不同的邏輯下進行不同的設置。
橫豎屏切換時引起的 Activity 重新創(chuàng)建
默認情況下,橫豎屏切換會引起當前 Activity 銷毀然后重新創(chuàng)建。所以我們可以在 Activity 重新創(chuàng)建時根據(jù)當前橫豎屏狀態(tài)做一些差異化。最常見的就是根據(jù)橫豎屏采用不同的 layout xml。
在 res 目錄下建立 layout-land 和 layout-port 目錄,在不同目錄下分別放一個同名的 layout xml 文件,然后在代碼里正常使用這個 layout 文件,系統(tǒng)就會在橫豎屏切換并重新創(chuàng)建 Activity 時自動使用對應的 layout 文件。如:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
}
如果不想通過創(chuàng)建多個 layout 文件來區(qū)分橫豎屏布局,也可以用 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 屬性時,切到橫屏時會重新執(zhí)行一次生命周期,而切到豎屏時會執(zhí)行兩次。
如果設置了 android:configChanges="orientation" 屬性,則都只會執(zhí)行一次。
但是個人實驗沒有驗證出這個說法。保險起見,可以加上 android:configChanges="orientation" 屬性,確保生命周期只調用一次。
阻止橫豎屏切換時 Activity 重啟
雖然我們可以用上面的方法對橫豎屏做不同的布局,但是橫豎屏切換導致的 Activity 重新創(chuàng)建還會引起用戶當前狀態(tài)、數(shù)據(jù)的丟失。例如 EditText 中輸入到一半的文字在 Activity 重新創(chuàng)建后會丟失。所以如果有辦法能在旋轉屏幕時不重新創(chuàng)建 Activity,應該是更好的一種選擇。
我們可以在 AndroidManifest.xml 中為相應的 <activity> 設置 android:configChanges 屬性,讓它不在橫豎屏切換時引起 Activity 的重新創(chuàng)建。
Android 3.2(API Level 13)以前的 SDK 可以使用如下配置
android:configChanges="orientation|keyboardHidden"
而 Android 3.2 以后的 SDK 則需要設置為
android:configChanges="keyboardHidden|orientation|screenSize"
這樣一來,橫豎屏切換時 Activity 將不會重新創(chuàng)建。
橫豎屏切換時的回調
一旦我們按照上述方法設置了 android:configChanges 屬性,那么橫豎屏切換時 Activity 將不會重新創(chuàng)建,那么當屏幕旋轉時,我們在代碼上怎么感知呢?可以通過 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){
// 針對豎屏做一些處理
}
}
判斷當前屏幕方向
有了上面的橫豎屏切換的回調,我們就可以及時感知到屏幕的狀態(tài)變化。但因為豎屏、橫屏都有兩個不同的方向,所以 Android 系統(tǒng)又提供了方法給我們獲取當前屏幕精確的旋轉方向。
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 (保持豎屏)。
- 觸發(fā)橫豎屏切換時,如果希望 Activity 銷毀并重新創(chuàng)建,則可以設置 Activity 的 android:configChanges="orientation" 。
- 觸發(fā)橫豎屏切換時,如果不希望 Activity 銷毀并重新創(chuàng)建,可以設置 Activity 的 android:configChanges="keyboardHidden|orientation|screenSize" 。此后橫豎屏切換時,可以在 Activity.onConfigurationChanged 或 View.onConfigurationChanged 方法中處理切換后的事情。
- 在任何時候可以用 getResources().getConfiguration().orientation 獲取屏幕的橫豎屏狀態(tài)。
- 在任何時候可以用 activity.getWindowManager().getDefaultDisplay().getRotation() 獲取屏幕的旋轉角度。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持html5模板網(wǎng)。