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/