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阅读 141,232评论 1 296
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 60,610评论 1 254
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 93,049评论 0 210
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 40,691评论 0 171
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 48,375评论 1 250
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 38,571评论 1 169
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 30,262评论 2 266
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,036评论 0 163
  • 想象着我的养父在大火中拼命挣扎,窒息,最后皮肤化为焦炭。我心中就已经是抑制不住地欢快,这就叫做以其人之道,还治其人...
    爱写小说的胖达阅读 28,781评论 6 225
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 32,394评论 0 211
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,154评论 2 212
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 30,470评论 1 222
  • 白月光回国,霸总把我这个替身辞退。还一脸阴沉的警告我。[不要出现在思思面前, 不然我有一百种方法让你生不如死。]我...
    爱写小说的胖达阅读 24,151评论 0 31
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,023评论 2 210
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 31,376评论 3 201
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,579评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 25,926评论 0 163
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 33,342评论 2 227
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 33,466评论 2 229

推荐阅读更多精彩内容