Android 橫豎屏切換

Android開發中,大多APP可能根據實際情況直接將APP的界面方向設死了,或豎屏或橫屏。但是,我們還是會遇到橫豎屏切換的功能需求,不管是通過物理重力感應觸發,還是用戶手動觸發。所以,我們有必要去弄清楚Android中橫豎屏切換到底做了什么。

Follow me ......

一、android:screenOrientation & android:configChanges

  • android:screenOrientation
    是用來設置 activity在設備上的顯示方向的,只能是下面的唯一值:
描述
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 以上,鎖死當前屏幕的方向

如果你上傳應用到 Google Play,需要注意以下提示:
Note: When you declare one of the landscape or portrait values, it is considered a hard requirement for the orientation in which the activity runs. As such, the value you declare enables filtering by services such as Google Play so your application is available only to devices that support the orientation required by your activities. For example, if you declare either"landscape", "reverseLandscape", or "sensorLandscape", then your application will be available only to devices that support landscape orientation. However, you should also explicitly declare that your application requires either portrait or landscape orientation with the <uses-feature>
element. For example, <uses-feature android:name="android.hardware.screen.portrait"/>. This is purely a filtering behavior provided by Google Play (and other services that support it) and the platform itself does not control whether your app can be installed when a device supports only certain orientations.

  • android:configChanges
    用來設置 activity配置改變(不僅僅是屏幕方向,還有語言、地區等等)的集合。當一個配置改變在運行中發生時,activity默認情況下會先銷毀然后重新創建。但是,如果通過這個屬性聲明了某個配置后,將可以避免上面的情況,而是依然運行,并回調 onConfigurationChanged() 方法。該屬性可以設置多個值:
描述
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生命周期的影響

通過打印Activity各個生命周期的執行情況,我們根據以下幾種情況來分析:

1. 不配置 configChanges

2. 配置 android:configChanges="orientation"

3. 配置android:configChanges="orientation|keyboardHidden"

  • 豎屏切橫屏
11-02 20:17:44.898 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onPause
11-02 20:17:45.008 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onSaveInstanceState
11-02 20:17:45.008 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onStop
11-02 20:17:45.018 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onDestroy
11-02 20:17:45.038 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onCreate - orientation
11-02 20:17:45.088 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onStart
11-02 20:17:45.088 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onRestoreInstanceState
11-02 20:17:45.088 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onResume
  • 橫屏切豎屏:
11-02 20:19:00.268 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onPause
11-02 20:19:00.268 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onSaveInstanceState
11-02 20:19:00.268 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onStop
11-02 20:19:00.268 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onDestroy
11-02 20:19:00.318 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onCreate - orientation
11-02 20:19:00.338 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onStart
11-02 20:19:00.338 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onRestoreInstanceState
11-02 20:19:00.338 13324-13324/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onResume

從上面的 3種方式配置 打印的 Log (三種方式 Log是一樣的,故合并顯示),我們可以總結如下:

不設置Activity的android:configChanges時,或 設置Activity的android:configChanges="orientation"時,或設置Activity的android:configChanges="orientation|keyboardHidden"時,切屏會重新調用各個生命周期,切橫屏時會執行一次,切豎屏時會執行一次方法。

而我們經常在其他地方看到的結論如下:

1、不設置Activity的android:configChanges時,切屏會重新調用各個生命周期,切橫屏時會執行一次,切豎屏時會執行兩次
2、設置Activity的android:configChanges="orientation"時,切屏還是會重新調用各個生命周期,切橫、豎屏時只會執行一次
3、設置Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會重新調用各個生命周期,只會執行onConfigurationChanged方法

4. 所以是什么原因導致我們的結論不一樣呢?

需要說明的是:** 我的測試環境是 targetSdkVersion 24,測試模擬器是 系統API 5.0!**

查看官方文檔,發現有如下提示:

注意:從 Android 3.2(API 級別 13)開始,當設備在縱向和橫向之間切換時,“屏幕尺寸”也會發生變化。因此,在開發針對 API 級別 13 或更高版本系統的應用時,若要避免由于設備方向改變而導致運行時重啟(正如 minSdkVersion
targetSdkVersion
屬性中所聲明),則除了"orientation"值以外,您還必須添加 "screenSize"值。即,您必須聲明 android:configChanges="orientation|screenSize"。但是,如果您的應用是面向 API 級別 12 或更低版本的系統,則 Activity 始終會自行處理此配置變更(即便是在 Android 3.2 或更高版本的設備上運行,此配置變更也不會重啟 Activity)。

我們現在測試第四種配置方式。

5. 配置 android:configChanges="orientation|keyboardHidden|screenSize"

  • 豎屏切橫屏
11-02 20:44:06.568 7792-7792/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onConfigurationChanged
  • 橫屏切豎屏
11-02 20:44:52.918 7792-7792/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onConfigurationChanged

結論: 從 API 13開始,配置 android:configChanges="orientation|keyboardHidden|screenSize",才不會銷毀 activity,且只調用 onConfigurationChanged方法。

6. 橫豎屏切換小結

  • (一)、Android 3.2 (API 級別 13)以前
    1、不設置Activity的android:configChanges時,切屏會重新調用各個生命周期,切橫屏時會執行一次,切豎屏時會執行兩次。
    2、設置Activity的android:configChanges="orientation"時,切屏還是會重新調用各個生命周期,切橫、豎屏時只會執行一次。
    3、設置Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會重新調用各個生命周期,只會執行onConfigurationChanged方法。

注意: 不設置Activity的android:configChanges時,切換豎屏activity的各個生命周期執行兩次,有人說是 在API 2.x下,我未測試,大家可以考證下。

  • (二)、從 Android 3.2 (API級別 13)開始
    1、不設置Activity的android:configChanges,或設置Activity的android:configChanges="orientation",或設置Activity的android:configChanges="orientation|keyboardHidden",切屏會重新調用各個生命周期,切橫屏時會執行一次,切豎屏時會執行一次。
    2、配置 android:configChanges="orientation|keyboardHidden|screenSize",才不會銷毀 activity,且只調用 onConfigurationChanged方法。

三、代碼中動態切換橫豎屏

在代碼中切換屏幕的方向主要調用 setRequestedOrientation(int requestedOrientation) 方法,此方法的作用等同于在 AndroidManifest.xml設置Activity 的android:screenOrientation,所以,其可傳遞的參數如 android:screenOrientation表格中一樣。

示例代碼:

findViewById(R.id.btn_click).setOnClickListener(new View.OnClickListener() {  
  @Override 
   public void onClick(View view) {   
     Log.d(TAG,"被點擊了");  
      //判斷當前屏幕方向  
      if(getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {     
       //切換豎屏   
         MainActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);   
      }else{   
         //切換橫屏     
         MainActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);  
      } 
   }
});

非重啟Activity模式:即設置了android:configChanges="orientation|keyboardHidden|screenSize",Log輸出(橫豎屏切換一樣)

11-03 10:38:33.998 20317-20317/com.ys.yoosir.screenconfigchange D/MainActivity: 被點擊了
11-03 10:38:34.108 20317-20317/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onConfigurationChanged

重啟Activity模式:即沒有設置android:configChanges="orientation|keyboardHidden|screenSize",Log輸出(橫豎屏切換一樣)

11-03 10:59:23.268 7724-7724/com.ys.yoosir.screenconfigchange D/MainActivity: 被點擊了
11-03 10:59:23.368 7724-7724/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onPause
11-03 10:59:23.368 7724-7724/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onSaveInstanceState
11-03 10:59:23.368 7724-7724/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onStop
11-03 10:59:23.368 7724-7724/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onDestroy
11-03 10:59:23.428 7724-7724/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onCreate - orientation
11-03 10:59:23.458 7724-7724/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onStart
11-03 10:59:23.458 7724-7724/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onRestoreInstanceState
11-03 10:59:23.458 7724-7724/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onResume

注意: 通過 setRequestedOrientation(int requestedOrientation) 修改了屏幕方向后,就類似于設置了android:screenOrientation,效果是一樣的,比如:調用setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT),無論屏幕怎么旋轉,都不會切換屏幕方向。如果要恢復為響應橫豎屏隨物理方向傳感器設備變換,那么就需要手動調用類似setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);代碼進行恢復。

四、橫豎屏切換我們需要做的事

  • 重啟Activity模式
    在重啟Activity模式下,橫豎屏切換的時候會導致數據丟失,我們可以通過如下代碼來保正數據不丟失:
 @Overrideprotected
 void onSaveInstanceState(Bundle outState) { 
   Log.d(TAG," -- onSaveInstanceState"); 
   Log.d(TAG," -- onSaveInstanceState save: name = yoosir,age = 24,handsome = ture"); 
   outState.putString("name","yoosir"); 
   outState.putInt("age",24); 
   outState.putBoolean("handsome",true); 
   super.onSaveInstanceState(outState);
}
....
 @Overrideprotected
 void onRestoreInstanceState(Bundle savedInstanceState) { 
   super.onRestoreInstanceState(savedInstanceState); 
   Log.d(TAG," -- onRestoreInstanceState"); 
   if(savedInstanceState != null) { 
       String name = savedInstanceState.getString("name"); 
       int age = savedInstanceState.getInt("age"); 
       boolean isHandsome = savedInstanceState.getBoolean("handsome"); 
       Log.d(TAG, " -- onRestoreInstanceState get: name = " + name + ",age = " + age + ",handsome = " + isHandsome); 
   }}

橫豎屏切換Log 輸出:

11-03 12:03:31.678 3663-3663/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onPause
11-03 12:03:31.678 3663-3663/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onSaveInstanceState
11-03 12:03:31.678 3663-3663/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onSaveInstanceState save: name = yoosir,age = 24,handsome = ture
11-03 12:03:31.688 3663-3663/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onStop
11-03 12:03:31.688 3663-3663/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onDestroy
11-03 12:03:31.758 3663-3663/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onCreate - orientation
11-03 12:03:31.758 3663-3663/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onCreate get: name = yoosir,age = 24,handsome = true
11-03 12:03:31.788 3663-3663/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onStart
11-03 12:03:31.788 3663-3663/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onRestoreInstanceState
11-03 12:03:31.788 3663-3663/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onRestoreInstanceState get: name = yoosir,age = 24,handsome = true
11-03 12:03:31.788 3663-3663/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onResume

如上,大家可以看到在 onCreate() 中也是可以拿到我們之前保存的數據的。

補充一點: 如果大家在資源目錄res 中添加了 layout-land(橫向布局文件夾) 和 layout-port (豎想布局文件夾),重啟Activity模式的橫豎屏切換,系統會自動幫我們顯示正確方向的布局UI。

Paste_Image.png

  • 非重啟Activity模式
    非重啟Activity模式下橫豎屏切換,我們的Activity 不會銷毀重建,數據也不會丟失。但是,如果我們想根據不同的屏幕方向來展示不同UI或做不同的事,應該怎么做呢?直接上代碼:
@Overridepublic void onConfigurationChanged(Configuration newConfig) { 
   super.onConfigurationChanged(newConfig); 
   Log.d(TAG," -- onConfigurationChanged"); 
   if(newConfig.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){ 
       //切換到豎屏  
      //修改布局文件  
      setContentView(R.layout.activity_main);  
      //findViewById ....   
     //TODO something  
      Log.d(TAG," -- onConfigurationChanged  可以在豎屏方向 to do something"); 
   }else{  
      //切換到橫屏  
      //修改布局文件  
      setContentView(R.layout.activity_main);  
      //findViewById ....  
      //TODO something  
      Log.d(TAG," -- onConfigurationChanged  可以在橫屏方向 to do something"); 
   }
}

橫豎屏切換Log 輸出:

11-03 14:56:50.465 28612-28612/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onConfigurationChanged
11-03 14:56:50.495 28612-28612/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onConfigurationChanged  可以在橫屏方向 to do something

大家可以看到,在非重啟Activity模式下,橫豎屏切換修改UI布局文件時,其實挺麻煩的(我是這樣的看法,^_~),需要重新初始化一遍UI。不過,不需要我們手動保存數據倒是挺方便的。

五、橫豎屏切換對Fragment的影響

打印 Activity 和 Fragment 各個生命周期,并在Activity 的 onCreate() 中添加如下代碼:

//是否已經 add 了 Fragment
if(getSupportFragmentManager().findFragmentByTag("child") == null) {
    Log.d(TAG, " -- onCreate has no child ");
    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
    blankFragment = BlankFragment.newInstance("one", "two");
    fragmentTransaction.add(R.id.root_view, blankFragment, "child");
    fragmentTransaction.commit();
}else{
    Log.d(TAG, " -- onCreate has child ");
}
  • 重建Activity模式
    Log: 帶有 BlankFragment 即為 Fragment 的打印,其他則為 Activity 的打印
    進入Activity的Log: 我們可以關注下第 2 行log——-- onCreate has no child
11-03 17:56:19.465 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onCreate - orientation
11-03 17:56:19.525 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onCreate has no child 
11-03 17:56:19.545 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- newInstance 
11-03 17:56:19.545 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onAttach 
11-03 17:56:19.545 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onCreate 
11-03 17:56:19.545 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onCreateView 
11-03 17:56:19.585 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onActivityCreated 
11-03 17:56:19.585 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onStart 
11-03 17:56:19.585 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onStart
11-03 17:56:19.585 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onResume
11-03 17:56:19.585 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onResume 
11-03 17:57:02.285 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity: -- one btn click 
11-03 17:57:05.705 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity: -- two btn click 

橫豎屏切換的Log:

  • 1、我們關注一下 第17行 onCreate has child ,所以** Fragment 本身是沒有被 destroy,它的views 是被destroy 的**
  • 2、關注一下 第5、6、19 和 20 行,Fragment 的局部變量數據被銷毀了,我們可以在onSaveInstanceState 保存數據,雖然 Fragment 不像 Activity 擁有 onRestoreInstanceState 方法,但是我們可以在 onActivityCreated 中獲取之前保存的數據。
11-03 17:57:40.095 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onPause 
11-03 17:57:40.095 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onPause
11-03 17:57:40.095 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onSaveInstanceState
11-03 17:57:40.095 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onSaveInstanceState save: name = yoosir,age = 24,handsome = ture
11-03 17:57:40.095 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onSaveInstanceState 
11-03 17:57:40.095 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onSaveInstanceState save str
11-03 17:57:40.095 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onStop 
11-03 17:57:40.095 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onStop
11-03 17:57:40.095 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onDestroyView 
11-03 17:57:40.095 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onDestroy 
11-03 17:57:40.095 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onDetach 
11-03 17:57:40.095 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onDestroy
11-03 17:57:40.165 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onAttach 
11-03 17:57:40.165 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onCreate 
11-03 17:57:40.165 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onCreate - orientation
11-03 17:57:40.165 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onCreate get: name = yoosir,age = 24,handsome = true
11-03 17:57:40.175 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onCreate has child 
11-03 17:57:40.175 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onCreateView 
11-03 17:57:40.185 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onActivityCreated 
11-03 17:57:40.185 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onActivityCreated get 我設置了參數
11-03 17:57:40.185 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onStart 
11-03 17:57:40.185 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onStart
11-03 17:57:40.195 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onRestoreInstanceState
11-03 17:57:40.195 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onRestoreInstanceState get: name = yoosir,age = 24,handsome = true
11-03 17:57:40.195 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onResume
11-03 17:57:40.195 26990-26990/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onResume 
  • 非重建Activity模式:
    橫豎屏切換Log(進入Activity的Log 與 重建Activity模式一樣 ):橫豎屏切換時,Fragment 和 Activity 都只會調用 onConfigurationChanged 方法。
11-03 18:31:21.725 27309-27309/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onConfigurationChanged 
11-03 18:31:21.725 27309-27309/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onConfigurationChanged
11-03 18:31:21.725 27309-27309/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onConfigurationChanged  可以在橫屏方向 to do something
11-03 18:31:36.545 27309-27309/com.ys.yoosir.screenconfigchange D/Main2Activity:  BlankFragment -- onConfigurationChanged 
11-03 18:31:36.545 27309-27309/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onConfigurationChanged
11-03 18:31:36.545 27309-27309/com.ys.yoosir.screenconfigchange D/Main2Activity:  -- onConfigurationChanged  可以在豎屏方向 to do something

六、其他小技巧

如果我們應用是手機和平板都可用的,且手機的只能是豎屏不可切換,平板的只能是橫屏不可切換。首先,我們要區分設備是手機還是平板,然后設置屏幕方向。代碼如下:

/**
 * 判斷是否平板設備
 * @param context
 * @return true:平板,false:手機 
*/
private boolean isTabletDevice(Context context) {
    return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
//設置屏幕方向
private void setScreenOrientation(Context context){  
    if(!isTabletDevice(context)){  
        //手機,豎屏   
       MainActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);  
    }else{ 
         //平板,橫屏   
       MainActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);   
   }
}

參考學習的文章:

The Real Best Practices to Save/Restore Activity's and Fragment's state 《===== 重點推薦閱讀
[譯] 保存/恢復 Activity 和 Fragment 狀態的最佳實踐 《=== 上面一篇文章的譯文
如何在Android設備旋轉時暫存數據以保護當前的交互狀態?
Android橫豎屏切換小結

附圖兩張:

Activity 生命周期.png
Fragment 生命周期.png

小小總結

通過一步一步代碼驗證,我們終于明白了橫豎屏切換時發生了什么,又可以愉快的寫代碼了,啦啦啦...,I AM CODER!
若有錯誤的地方,歡迎大家指正和評論,謝謝!:-)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容