美文网首页
重识Activity-横竖屏的那些事儿

重识Activity-横竖屏的那些事儿

作者: Android_程序媛 | 来源:发表于2019-05-06 16:39 被阅读0次

重识Activity—Activity的生命周期这篇文章中有记录Activity横竖屏切换的生命周期,这篇文章主要延伸上篇的该知识点,记录关于Activity横竖屏的那些事儿。

影响横竖屏切换的因素

一般我们在玩游戏或者看视频的时候,会发现手机的界面会由竖屏切换成横屏,等到退出的时候又会由横屏切换成竖屏,那么影响横竖屏切换的因素有哪些呢?

  • 在手机的系统设置中,可以设置方向是否锁定,锁定时是竖屏,没有锁定时可以旋转切换;
  • 根据手机的物理传感器感应到设备的方向;
  • 在App中的代码设置横竖屏属性。

注意:以上三个因素没有所谓的优先级,所以,我们即使在系统设置中锁定了方向,但是如果在App的代码中设置了方向,也会根据代码中设置的属性设置屏幕的方向,不过仅限于App中设置的界面。

横竖屏的设置

因为是通过属性设置的,首先先看一下设置横竖屏有哪些属性值呢?

属性值 说明
unspecified 默认值。由系统选择方向。
behind 与Activity栈中紧接着它的Activity的方向相同。
landscape 横向方向(显示的宽度大于高度)
portrait 纵向方向(显示的高度大于宽度)
reverseLandscape 与正常横向方向相反的横向方向。API 9及以上。
reversePortrait 与正常纵向方向相反的纵向方向。API 9及以上。
sensorLandscape 横向方向,但根据设备传感器,可以是正常或者反向的横向方向。API 9及以上。
sensorPortrait 纵向方向,但根据设备传感器,可以是正常或者反向的纵向方向。API 9及以上。
userLandscape 横向方向,但根据设备传感器和用户的传感器首选项,可以是正常或反向的横向方向。 如果用户锁定了基于传感器的旋转,其行为与 landscape 相同,否则,其行为与 sensorLandscape 相同。API 18及以上。
userPortrait 纵向方向,但根据设备传感器和用户的传感器首选项,可以是正常或反向的纵向方向。 如果用户锁定了基于传感器的旋转,其行为与 portrait 相同,否则,其行为与 sensorPortrait 相同。API 18及以上。
sensor 方向由设备方向传感器决定。显示方向取决于用户如何手持设备,它会在用户旋转设备时发生变化。 但一些设备默认情况下不会旋转到所有四种可能的方向。要允许全部四种方向,请使用 "fullSensor"。
fullSensor 方向由 4 种方向中任一方向的设备方向传感器决定。这与 "sensor" 类似,不同的是它允许所有 4 种可能的屏幕方向,无论设备正常情况下采用什么方向(例如,一些设备正常情况下不使用反向纵向或反向横向,但它支持这些方向)。API 9及以上。
nosensor 决定方向时不考虑物理方向传感器。传感器会被忽略,因此显示不会随用户对设备的移动而旋转。 除了这个区别,系统在选择方向时使用的政策与“unspecified”设置相同。
user 用户当前的首选方向。
fullUser 如果用户锁定了基于传感器的旋转,其行为与 user 相同,否则,其行为与 fullSensor 相同,允许所有 4 种可能的屏幕方向。API 18及以上。
locked 将方向锁定在其当前的任意旋转方向。API 18及以上。

在开发中一般用到的属性值也就那么几个,分别是:unspecifiedlandscapeportrait,除非有其他需求进行不同的设置。

了解了上面介绍的属性值,下面说一下横竖屏的设置,有两种方式:

  • 在AndroidManifest.xml文件中的<activity></activity>标签中设置
    android:screenOrientation属性,其属性值根据具体需求可以设置上述表格中介绍的。例如,看视频是设置为横向屏:
<activity 
    android:name=".MainActivity"
    android:screenOrientation="landscape">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
  • 通过Java代码的方式
    上述表格的属性值在代码中与之对应的是ActivityInfo.SCREEN_ORIENTATION_XXX,例如:unspecified属性值对应的是ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED,具体设置方式如下:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

通过上面的介绍,在开发App时如何设置所有Activity屏幕方向呢?
总结如下:

  1. 在Application的style中设置android:screenOrientation属性,但是通过测试这样是不可行的,因为要求Activity必须在运行中设置才会有效;
  2. 在AndroidManifest.xml配置文件中,针对每个<activity>标签设置android:screenOrientation属性;
  3. 写一个基类BaseActivity,在该类中通过Java代码的方式设置,然后让子类Activity继承BaseActivity

阻止Activity被重建

我们知道Activity横竖屏切换时他的生命周期会执行完一次,再重新创建一个Activity实例,这个时候相当于是Activity在运行时发生配置更改时,默认情况下会关闭Activity然后将其重新启动,如何阻止Activity被重建,并且会保持运行状态呢?

  • <activity>标签中设置android:configChanges属性;

下面记录一下该属性的所有属性值。

属性值 说明
mcc IMSI 移动国家/地区代码 (MCC) 发生了变化 - 检测到了 SIM 并更新了 MCC。
mnc IMSI 移动网络代码 (MNC) 发生了变化 - 检测到了 SIM 并更新了 MNC。
locale 语言区域发生了变化 — 用户为文本选择了新的显示语言。
touchscreen 触摸屏发生了变化。(这种情况通常永远不会发生。)
keyboard 键盘类型发生了变化 — 例如,用户插入了一个外置键盘。
keyboardHidden 键盘无障碍功能发生了变化 — 例如,用户显示了硬件键盘。
navigation 导航类型(轨迹球/方向键)发生了变化。(这种情况通常永远不会发生。)
screenLayout 屏幕布局发生了变化 — 这可能是由激活了其他显示方式所致。
fontScale 字体缩放系数发生了变化 — 用户选择了新的全局字号。
uiMode 用户界面模式发生了变化 — 这可能是因用户将设备放入桌面/车载基座或夜间模式发生变化所致。API 8及以上。
orientation 屏幕方向发生了变化 — 用户旋转了设备。注意:如果您的应用面向 API 级别 13 或更高级别(按照 minSdkVersion 和 targetSdkVersion 属性所声明的级别),则还应声明 "screenSize" 配置,因为当设备在横向与纵向之间切换时,该配置也会发生变化。
screenSize 当前可用屏幕尺寸发生了变化。它表示当前可用尺寸相对于当前纵横比的变化,因此会在用户在横向与纵向之间切换时发生变化。 不过,如果您的应用面向 API 级别 12 或更低级别,则 Activity 始终会自行处理此配置变更(即便是在 Android 3.2 或更高版本的设备上运行,此配置变更也不会重新启动 Activity)。API 13及以上。
smallestScreenSize 物理屏幕尺寸发生了变化。它表示与方向无关的尺寸变化,因此只有在实际物理屏幕尺寸发生变化(如切换到外部显示器)时才会变化。 对此配置的变更对应于smallestWidth 配置的变化。 不过,如果您的应用面向 API 级别 12 或更低级别,则 Activity 始终会自行处理此配置变更(即便是在 Android 3.2 或更高版本的设备上运行,此配置变更也不会重新启动 Activity)。API 13及以上。
layoutDirection 布局方向发生了变化。例如,从从左至右 (LTR) 更改为从右至左 (RTL)。 API 17及以上。

使用上述表格的属性值时,如果是多个值使用“|”分割,例如:android:configChanges="orientation|keyboardHidden|screenSize"

  • 配置上述属性,还需要在代码中配合onConfigurationChanged(Configuration newConfig)方法,拦截横竖屏变换。

onConfigurationChanged(Configuration newConfig):该方法是当Activity运行时设备配置发生变更时由系统调用。注意。只有当android:configChanges属性配置的属性值变更时才会调用此函数,如果发生任何没有配置的属性值变更,则系统将停止并重新启动Activity,以使用新配置启动Activity。调用此函数时,将更新资源对象以返回与新配置匹配的资源值(包括视图布局、可绘制对象等),以正确处理变化。

下面看一下,如何使用:

  1. 首先在AndroidManifest.xml文件中配置android:configChanges属性:
<activity 
    android:name=".MainActivity"
    android:configChanges="orientation|screenSize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>
  1. 在Java代码中,重写onConfigurationChanged()方法:
@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if(this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
        Log.i("Alisa","竖屏");
        //这里可以针对竖屏做一些处理
    }else if(this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
        Log.i("Alisa","横屏");
        //这里可以针对横屏做一些处理
    }
}

其中,getResources().getConfiguration().orientation可以获取当前的横竖屏。

通过上述操作,可以发现,Activity不会再销毁重新创建一次,而是只调用onConfigurationChanged()方法,并且会自动保存View中的一些临时数据。

一般情况下,我们在<activity>标签中配置为:

android:configChanges="orientation|keyboardHidden|screenSize"

注意:API 13及以上,需要配置screenSize属性值,否则不起作用。

如果在配置文件中同时配置如下:

<activity 
    android:name=".MainActivity"
    android:screenOrientation="landscape"
    android:configChanges="orientation|keyboardHidden|screenSize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>

此时,不会回调onConfigurationChanged()方法,但是如果是通过Java代码的形式设置屏幕的方向,会回调onConfigurationChanged()方法。

扩展

根据上述的横竖屏切换的回调,我们就可以及时知道当前屏幕的状态变化,由于屏幕的横竖屏都有两个不同的方向,所以我们可以通过获取当前屏幕精确的方向。具体如下:

  • 获取当前屏幕的旋转角度:
Display display = getWindowManager().getDefaultDisplay();
int rotation = display.getRotation();//当前的屏幕角度

屏幕角度有4个值,以竖屏顺时针旋转,分别是:

  1. Surface.ROTATION_0:竖屏
  2. Surface.ROTATION_90:横屏
  3. Surface.ROTATION_180:反向竖屏
  4. Surface.ROTATION_270:反向横屏
  • 通过获取到的当前屏幕角度同上述4个值做判断,针对具体需求设定屏幕方向。

以上,就是这次整理的关于横竖屏的知识,欢迎大家积极留言,一起探讨学习!也请大家继续关注我的文章!

相关文章

网友评论

      本文标题:重识Activity-横竖屏的那些事儿

      本文链接:https://www.haomeiwen.com/subject/tnrdoqtx.html