Activity在屏幕顯示的方向切換
android:screenOrientation和android:configChanges
Activity的內容在屏幕上的顯示方向,有時會旋轉。
activity內容方向的設定與轉換,以及相關的生命周期處理,是與Manifest中activity標簽下的下面兩個屬性相關的:
即android:screenOrientation和android:configChanges
(鏈接中有所有屬性的說明:http://developer.android.com/guide/topics/manifest/activity-element.html#screen)
Android的屏幕方向狀態是下列的值之一:
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
ActivityInfo.SCREEN_ORIENTATION_USER
ActivityInfo.SCREEN_ORIENTATION_BEHIND
ActivityInfo.SCREEN_ORIENTATION_SENSOR
ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
方向屬性設置
我們可以利用android:screenOrientation屬性強制鎖定屏幕的方向。
也可以把方向設定為隨着傳感器而變化。
下面是這個屬性可以設定的值。
在程序中也可以調用setRequestedOrientation方法進行屏幕方向的動態設置,具體請參見文后參考資料的第二個鏈接。
方向轉換與生命周期
當在manifest中把android:screenOrientation的屬性設為sensor時:
<activity android:name=".HelloOrientationActivity" android:label="@string/title_activity_hello_orientation" android:screenOrientation="sensor" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
運行程序可以發現Activity的顯示內容的確會隨着手機的姿態進行橫豎屏的切換。
但是觀察生命周期的相關函數調用Log,發現在進行橫豎屏切換的時候整個activity會調用onPause()、onStop()、onDestroy()然后重新調用onCreate()、onResume()。
並且此時覆寫onConfigurationChanged()是不會被調用的。
查看android:configChanges部分的文檔可以發現,默認情況下activity是會關閉並且重啟的,但是通過這個屬性可以阻止activity的重啟行為,讓activity保持運行,並且activity的onConfigurationChanged()將會被調用。
(默認情況下這個方法是不會被調用的)。
但是官方不建議用這個屬性來處理,建議看看 Handling Runtime Changes 。
這個屬性設置的各種值就是要阻止activity重啟的各種情況。
比如設置為:
<activity android:name=".HelloOrientationActivity" android:configChanges="orientation|keyboardHidden" android:label="@string/title_activity_hello_orientation" android:screenOrientation="sensor" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
這樣在屏幕旋轉並切換橫豎屏的時候,發現activity並沒有被重建,而是調用了onConfigurationChanged()方法。
補充一下:
當android:targetSdkVersion大於等於13時, 要想onConfigurationChanged()方法被調用,mainfest中需要這樣寫:
<activity android:name="com.example.helloorientation.MainActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:label="@string/app_name" android:screenOrientation="sensor" > ......
測試程序
附上測試程序代碼:

package com.example.helloactivityorientation; import android.app.Activity; import android.content.res.Configuration; import android.os.Bundle; import android.util.Log; import android.widget.TextView; public class HelloOrientationActivity extends Activity { private static final String LOG_TAG = "Hello Orientation"; @Override public void onCreate(Bundle savedInstanceState) { Log.i(LOG_TAG, "onCreate"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_hello_orientation); } @Override protected void onResume() { Log.i(LOG_TAG, "onResume"); super.onResume(); } @Override protected void onPause() { Log.i(LOG_TAG, "onPause"); super.onPause(); } @Override protected void onStop() { Log.i(LOG_TAG, "onStop"); super.onStop(); } @Override protected void onDestroy() { Log.i(LOG_TAG, "onDestroy"); super.onDestroy(); } @Override public void onConfigurationChanged(Configuration newConfig) { Log.i(LOG_TAG, "onConfigurationChanged"); super.onConfigurationChanged(newConfig); } }

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.helloactivityorientation" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".HelloOrientationActivity" android:configChanges="orientation|keyboardHidden" android:label="@string/title_activity_hello_orientation" android:screenOrientation="sensor" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
布局代碼略,能看出正反向就行,TextView里寫個HelloWorld就可以了。
參考資料
官方文檔中activity標簽下的元素說明:
http://developer.android.com/guide/topics/manifest/activity-element.html
一個英文的關於屏幕方向的文章:
http://techblogon.com/android-screen-orientation-change-rotation-example/