1. 程式人生 > 程式設計 >Android螢幕旋轉之橫屏豎屏切換的實現

Android螢幕旋轉之橫屏豎屏切換的實現

剛實現了App內手機橫/豎放置時,螢幕橫/豎屏的切換。記錄一下中間需要的關鍵資訊和實現過程。

開門見山的說,實現螢幕自動/手動旋轉的方式有兩種:

一種是在工程的程式碼中定義,這種方式在橫豎屏切換時執行的操作是:銷燬當前Activity–根據新的螢幕尺寸重建Activity。如果不進行資料儲存的操作,在切換的過程中Activity中的資料會丟失。

另一種是在工程的AndroidManifest.xml中定義,這種定義的方式在某些情況下可以實現“不銷燬需要橫豎屏的Activity”,因為這種方式不會銷燬Activity後重建Activity,因此Activity的資料不會丟失。

接下來分別介紹這兩種實現方式:

方式一:程式碼中定義

在需要橫屏的Activity中的onCreate方法內新增如下語句,並且要求該語句位於onCreate方法內setContentView(**)語句之前。

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);

上條語句中,常數SCREEN_ORIENTATION_FULL_SENSOR是決定螢幕如何旋轉的引數。總結所有的引數對應的功能:

引數 功能
SCREEN_ORIENTATION_BEHIND 繼承Activity堆疊中當前Activity下面的那個Activity的方向
SCREEN_ORIENTATION_FULL_SENSOR 由重力感測器決定0/90/180/270°
SCREEN_ORIENTATION_FULL_USER
SCREEN_ORIENTATION_LANDSCAPE 始終橫屏
SCREEN_ORIENTATION_PORTRAIT 始終豎屏
SCREEN_ORIENTATION_LOCKED 鎖定螢幕方向
SCREEN_ORIENTATION_NOSENSOR 關閉重力感測器對橫/豎屏的影響
SCREEN_ORIENTATION_REVERSE_LANDSCAPE 另一個方向的橫屏
SCREEN_ORIENTATION_REVERSE_PORTRAIT 另一個方向的豎屏(倒拿手機)
SCREEN_ORIENTATION_SENSOR 重力感測器影響螢幕的方向0/90/270°
SCREEN_ORIENTATION_SENSOR_LANDSCAPE 始終橫屏,由重力感測器決定是哪個方向的橫屏
SCREEN_ORIENTATION_SENSOR_PORTRAIT 始終豎屏,由重力感測器決定是哪個方向的豎屏
SCREEN_ORIENTATION_UNSPECIFIED 不指定方向,使用預設方向
SCREEN_ORIENTATION_USER 由使用者和重力感測器共同決定,詳見文字末端
SCREEN_ORIENTATION_USER_LANDSCAPE 使用者和重力感測器共同決定是哪個方向的橫屏
SCREEN_ORIENTATION_USER_PORTRAIT 使用者和重力感測器共同決定是哪個方向的豎屏
UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW 當螢幕較窄時導航欄有一部分會顯示在底部

由於該方式下橫/豎屏切換時,對應的Activity的資料會丟失,可以在對應的Activity中重寫如下兩個方法,來保證資料不丟失:

@Override
protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  //橫豎屏切換前呼叫,儲存使用者想要儲存的資料,以下是樣例
  outState.putString("name","yoosir"); 
  outState.putInt("age",24); 
  outState.putBoolean("handsome",true);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
  super.onRestoreInstanceState(savedInstanceState);
  // 螢幕切換完畢後呼叫使用者儲存的資料,以下為樣例:
  if(savedInstanceState != null) { 
    int age = savedInstanceState.getInt("age"); 
    String name = savedInstanceState.getString("name"); 
    boolean isHandsome = savedInstanceState.getBoolean("handsome");
  }
}

方式二:在AndroidManifest.xml中定義

在AndroidManifest.xml中對應的Activity屬性定義中配置android:configChanges和screenOrientation。參考的文章中在android:configChanges的配置說的很清楚,我直接把結論貼出來:

android:configChanges="orientation|keyboardHidden|screenSize"
  • 配置configChanges為以上配置時,切屏不會重新呼叫各個生命週期,只會執行onConfigurationChanged方法。Activity中的資料不會被銷燬。
  • 不配置configChanges或配置configChanges為非以上配置時,切屏會重新呼叫當前Activity的各個生命週期。Activity中的資料會被銷燬。

給出示例程式碼如下:

<activity android:name=".com.cdsn.SearchActivity"
  ... ...
  android:screenOrientation="sensor"
  android:configChanges="keyboardHidden|orientation|screenSize"
      />

上述程式碼中的android:screenOrientation所有可能的引數配置如下 。

描述
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 以上,鎖死當前螢幕的方向

上述程式碼中的android:configChanges所有可能的引數配置如下:

描述
mcc IMSI移動臺的國家程式碼(MCC)發生變化——一個SIM被探測到並且更新MCC
mnc IMSI移動臺的網路程式碼(MNC)發生變化——一個SIM被探測到並且更新MNC
locale 區域發生變化——使用者選擇了一個文字需要顯示的新語言
keyboard 鍵盤型別發生變化——例如:使用者插入了外接鍵盤。
keyboardHidden 鍵盤的可訪問性發生變化——例如:使用者發現了硬體鍵盤。
screenLayout 屏幕布局發生變化——這個會導致顯示不同的Activity。
orientation 螢幕方向發生變化——使用者旋轉了螢幕。注意:如果應用程式的目標API級別是13或更高(通過屬性minSdkVersion和屬性targetSdkVersion宣告),你也需要宣告配置項screenSize,因為這將在裝置選擇肖像和螢幕方向時發生改變。
screenSize 當前可用螢幕大小發生變化。這代表一個當前可用大小的變化,和當前的比率相關,因此當用戶選擇不同的畫面和影象,會發生變化。然而,如果你的程式目標API級別是12或更低,你的Activity總是會自己處理這個配置變化(這個變化不會引起Activity的重啟,甚至在Android 3.2或更新的裝置上)。在API級別13里加入的。
smallestScreenSize 物理螢幕大小的變化。不管方向的變化,僅僅在實際物理螢幕打包變化的時候,如:外接顯示器。這個配置項的變化引起在smallestWidth configuration裡的變化。然而,如果你的程式目標API級別是12或更低,你的Activity將自己處理這個變化(這個變化不會引起Activity的重啟,甚至在Android 3.2或更新的裝置上)在API級別13里加入的。
layoutDirection 佈局方向變化。例如書寫方式從左向右(LTR)轉換為從右向左(RTL)

配置了以上屬性之後,進行橫豎屏切換的Activity的資料不會丟失,如果想根據不同的螢幕方向來展示不同UI或做不同的事,需要在該Activity中重寫以下方法:

@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  // 在這裡新增螢幕切換後的操作
}

番外

我按照上述方法,根據重力感測器實現了螢幕旋轉,雖然可以做到螢幕隨重力感測器切換,但是發現:無論手機設定中“螢幕旋轉”或“方向鎖定”是開是關,App內的Activity都會隨著手機的橫豎方向切換橫豎屏。我想要實現的是當開啟“螢幕旋轉”時,App內的Activity跟隨重力感應器;當關閉“螢幕旋轉”時,App內的Activity固定為預設方向。如何做到關閉重力感測器時,App亦關閉螢幕自動旋轉?

android:screenOrientation="sensor"

改上述程式碼為以下程式碼

android:screenOrientation="user"

意即:當引數為sensor時,無論是否關閉“螢幕旋轉”設定,App內的特定Activity都會根據重力感測器改變橫豎屏。
當引數為user時,當“螢幕旋轉”開啟,則特定Activity根據根據重力感測器改變橫豎屏;當“螢幕旋轉”關閉,則特定Activity會固定位預設方向(一般為正面豎屏)。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。