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 element. For example, . 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"

  • 竖屏切横屏
1
2
3
4
5
6
7
8
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
  • 横屏切竖屏:
1
2
3
4
5
6
7
8
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"

  • 竖屏切横屏
1
11-02 20:44:06.568 7792-7792/com.ys.yoosir.screenconfigchange D/MainActivity:  -- onConfigurationChanged
  • 横屏切竖屏
1
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表格中一样。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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输出(横竖屏切换一样)

1
2
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输出(横竖屏切换一样)

1
2
3
4
5
6
7
8
9
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模式下,横竖屏切换的时候会导致数据丢失,我们可以通过如下代码来保正数据不丢失:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 @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 输出:

1
2
3
4
5
6
7
8
9
10
11
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。

  • 非重启Activity模式
    非重启Activity模式下横竖屏切换,我们的Activity 不会销毁重建,数据也不会丢失。但是,如果我们想根据不同的屏幕方向来展示不同UI或做不同的事,应该怎么做呢?直接上代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@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 输出:

1
2
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() 中添加如下代码:

1
2
3
4
5
6
7
8
9
10
//是否已经 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
1
2
3
4
5
6
7
8
9
10
11
12
13
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 中获取之前保存的数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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 方法。
1
2
3
4
5
6
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

六、其他小技巧

如果我们应用是手机和平板都可用的,且手机的只能是竖屏不可切换,平板的只能是横屏不可切换。首先,我们要区分设备是手机还是平板,然后设置屏幕方向。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 判断是否平板设备
* @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横竖屏切换小结

附图两张:

小小总结

通过一步一步代码验证,我们终于明白了横竖屏切换时发生了什么,又可以愉快的写代码了,啦啦啦…,I AM CODER!
若有错误的地方,欢迎大家指正和评论,谢谢!:-)

坚持原创技术分享,您的支持将鼓励我继续创作!