講解之前需要說明的是
設置屏幕的方向
簡介
| 值 | 描述 |
|---|---|
| unspecified | 默認值。系統自動選擇屏幕方向 |
| behind | 跟activity堆棧中的下面一個activity的方向一致 |
| landscape | 橫屏方向,顯示的寬比高長 |
| portrait | 豎屏方向,顯示的高比寬長 |
| sensor | 由設備的物理方向傳感器決定,如果用戶旋轉設備,這屏幕就會橫豎屏切換 |
| nosensor | 忽略物理方向傳感器,這樣就不會隨著用戶旋轉設備而橫豎屏切換了("unspecified"設置除外) |
| user | 用戶當前首選的方向 |
| reverseLandscape | API 9 以上,反向橫屏 |
| reversePortrait | API 9 以上,反向豎屏 |
| sensorLandscape | API 9 以上,橫屏,但是可以根據 物理方向傳感器來切換正反向橫屏 |
| sensorPortrait | API 9 以上,豎屏,但是可以根據 物理方向傳感器來切換正反向豎屏 |
| fullSensor | API 9 以上,上下左右四個方向,由物理方向傳感器決定 |
| locked | API 18 以上,鎖死當前屏幕的方向 |
第一種
我們可以在AndroidManifest 清單文件里面制定Activity的方向
<activity android:name=".view.main.MainActivity" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter></activity>
這樣橫豎屏切換的時候不會重新創建Activity
第二種
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Android:android:configChanges
如果我們不配置configuration ,當 configuration 發生變化的時候,activity會自動處理它。反之,如果我們配置了相應的 configuration,當新的 configuration 發生變化的時候,會回調 Activity 的 onConfigurationChanged() 方法。
下面我們一起來看一下幾個常用的值得介紹,其他不常用的hi請自行查閱文檔。官網地址:
| 值 | 描述 |
|---|---|
| keyboardHidden | 鍵盤的可訪問性發生變化――例如:用戶發現了硬件鍵盤。 |
| orientation | 屏幕方向發生變化――用戶旋轉了屏幕。注意:如果應用程序的目標API級別是13或更高(通過屬性minSdkVersion和屬性targetSdkVersion聲明),你也需要聲明配置項screenSize,因為這將在設備選擇肖像和屏幕方向時發生改變。 |
| screenLayout | 屏幕布局發生變化――這個會導致顯示不同的Activity。屏幕方向發生變化――用戶旋轉了屏幕。注意:如果應用程序的目標API級別是13或更高(通過屬性minSdkVersion和屬性targetSdkVersion聲明),你也需要聲明配置項screenSize,因為這將在設備選擇肖像和屏幕方向時發生改變。 |
| screenSize | 當前可用屏幕大小發生變化。這代表一個當前可用大小的變化,和當前的比率相關,因此當用戶選擇不同的畫面和圖像,會發生變化。然而,如果你的程序目標API級別是12或更低,你的Activity總是會自己處理這個配置變化(這個變化不會引起Activity的重啟,甚至在Android 3.2或更新的設備上)。在API級別13里加入的。 |
android:configChanges 常用配置
在Android 3.2以后,如果我們進行下列的配置 ,這樣的話橫豎屏不會重新創建Activity,但是會調用 onConfigurationChanged()方法
<activity android:name=".view.main.MainActivity" android:configChanges="keyboardHidden|orientation|screenSize" > <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter></activity>在api 3.2 以前,我們只需這樣配置即可,android:configChanges="keyboardHidden|orientation"。<activity android:name=".view.main.MainActivity" android:configChanges="keyboardHidden|orientation" > <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter></activity>
小結
當我們進行了上述的配置,
因此我們通??梢赃M行相應的處理
public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { // 加入橫屏要處理的代碼 } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { // 加入豎屏要處理的代碼 } }如果我們同時設置了 android:configChanges="keyboardHidden|orientation|screenSize" 和 android:screenOrientation="portrait",那又會是怎樣的呢?
如果我們打開系統的自動旋轉屏幕,旋轉屏幕,系統不會發生變化,也不會調用 Activity 的 onConfigurationChanged 方法。
當我們手動調用 setRequestedOrientation() 方法去改變屏幕的方向的時候,還是會調用 onConfigurationChanged 方法的
擴展
設置全屏模式
// 去掉ActionBarrequestWindowFeature(Window.FEATURE_NO_TITLE); // 設置全屏getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
在實際項目中,我們通常會固定我們應用的屏幕方向,只對一些特定的需要切換屏幕的Activity做處理,那我們如何統一設置屏幕的方向呢?
第一種方法,復制張貼,在AndroidManifest清單文件里面的每一個Activity標簽增加如下標簽。
<activity android:name=".MainActivity" android:screenOrientation="portrait" ></activity>
第二種方法,剛開始我直接在 AppTheme 里面 設置 android:screenOrientation,但是沒有效果,剛開始我也很納悶,后面查閱了官網文檔,描述如下,才解決了疑問.
Specify the orientation an activity should be run in. If not specified, it will run in the current preferred orientation of the screen. This attribute is supported by the <activity> element.
<!-- Base application theme. --><style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="android:screenOrientation">portrait</item></style>
即這種方法不可取
第三種方法,在BaseActivity里面動態設置
public class BaseActivity extends AppCompatActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); }}同時列出這三種方法,最主要的目的不是為了告訴大家有這幾種方法可以統一設置屏幕的方向,最重要的是告訴大家一種思想吧。通常在xml 文件可以設置的,在java 代碼也可以設置。
利用系統的加載機制自動幫我們加載相應的布局
如果大家在資源目錄res 中添加了 layout-land(橫向布局文件夾) 和 layout-port (豎想布局文件夾),重啟Activity模式的橫豎屏切換,
可能有人會有這樣的疑問,當我們設置了Activity的方向為豎屏或者橫屏的時候,旋轉屏幕并不會重新調用Activity的各個生命周期,那我們要怎樣檢測呢?
其實很簡單,那就是利用我們的傳感器,然后根據旋轉的方向做相應的處理
//注冊重力感應器 屏幕旋轉mSm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);mSensor = mSm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);mSm.registerListener(mOrientationSensorListener, mSensor, SensorManager.SENSOR_DELAY_UI);
public class OrientationSensorListener implements SensorEventListener { private static final int _DATA_X = 0; private static final int _DATA_Y = 1; private static final int _DATA_Z = 2; public static final int ORIENTATION_UNKNOWN = -1; private boolean sensor_flag = true; public static final String TAG = "xujun"; int mLastAngle=-1; AngleChangleListener mAngleChangleListener; public OrientationSensorListener(AngleChangleListener angleChangleListener){ mAngleChangleListener=angleChangleListener; } @Override public void onAccuracyChanged(Sensor arg0, int arg1) { // TODO Auto-generated method stub } @Override public void onSensorChanged(SensorEvent event) { float[] values = event.values; int orientation = ORIENTATION_UNKNOWN; float X = -values[_DATA_X]; float Y = -values[_DATA_Y]; float Z = -values[_DATA_Z]; /** * 這一段據說是 android源碼里面拿出來的計算 屏幕旋轉的 不懂 先留著 萬一以后懂了呢 */ float magnitude = X * X + Y * Y; // Don't trust the angle if the magnitude is small compared to the y value if (magnitude * 4 >= Z * Z) { //屏幕旋轉時 float OneEightyOverPi = 57.29577957855f; float angle = (float) Math.atan2(-Y, X) * OneEightyOverPi; orientation = 90 - (int) Math.round(angle); // normalize to 0 - 359 range while (orientation >= 360) { orientation -= 360; } while (orientation < 0) { orientation += 360; } } if (orientation > 225 && orientation < 315) { //橫屏 sensor_flag = false; } else if ((orientation > 315 && orientation < 360) || (orientation > 0 && orientation < 45)) { //豎屏 sensor_flag = true; }// Log.i(TAG, "onSensorChanged: orientation=" + orientation+" mLastAngle="+mLastAngle); if(mLastAngle!=orientation && mAngleChangleListener!=null){ mAngleChangleListener.onChange(orientation); mLastAngle=orientation; } }}設備旋轉時保存Activity的交互狀態

大家先看一下Activity的生命周期,我們知道如果我們不配置Activity的方向或者Activity的 android:configchang 屬性的時候,每次旋轉屏幕,Activity都會重新被創建出來。那我們要如何保存我們當前的狀態呢。
其實我們可以考慮在 onPause() 或者在 onStop() 里面保存我們相應的數據,再在onCreate() 方法里面判斷 savedInstanceState 是否有緩存我們的數據即可。 至于選擇在onPause() 還是 onStop() 保存數據,得看具體的需求分析。 onPause() 在界面失去焦點的時候會回調, onStop() 方法在界面完全不可見的時候會回調。
private static final String KEY_INDEX = "index";private int mCurrentIndex = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) { if (savedInstanceState != null) { mCurrentIndex = savedInstanceState.getInt(KEY_INDEX, 0); }}@Overrideprotected void onPause(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(KEY_INDEX, mCurrentIndex);}Demo 下載地址:ScreenDemo_jb51.rar
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。
新聞熱點
疑難解答