Android,如何在旋转设备时不销毁活动?

86

我有一个只能在竖屏模式下运行的应用程序,并且我已经在清单文件中为每个活动更改了方向,使其始终保持竖屏。但是当我旋转设备时,活动会重新创建。 如何避免销毁活动?


1
这通常被认为不是一个好主意,你可以尝试使用编程的方式设置你的应用程序方向,例如:setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - stealthcopter
8
为什么要反对呢?假设我们有一个需要运行2秒钟的服务。如果每次活动销毁,那么这个服务会在每次活动启动时都运行,而我只需要它运行一次即可。 - Mohamed Mansour
7个回答

138

对于API 12及以下:添加

android:configChanges="orientation"

如果您的目标是API 13或更高版本,请添加“screenSize”,因为每当您的方向更改时,屏幕大小也会发生变化,否则新设备将继续破坏您的活动。有关使用“screenSize”的更多信息,请参见下面Egg的答案。
android:configChanges="orientation|screenSize"

将其添加到AndroidManifest.xml中的活动。 这样您的活动就不会自动重新启动。有关更多信息,请参见文档


活动已重新启动。即使活动并没有真正旋转,也要执行所有必须完成的操作,我不知道这样做的意义何在。是否有一种方法可以禁用传感器向操作系统发送关于旋转的消息或类似的东西,从根本上解决此问题? - Vasil
6
你正在使用什么设备进行编程?请记住,例如滑出键盘也可能会重新启动你的活动...(如果这是原因,请将confChanges设置为“keyboard|keyboardHidden|orientation")。 - user235064
2
这会禁用布局更改。我该怎么解决? - Noobification
1
这个解决方案解决了销毁和创建活动的问题,但是如何处理布局更改呢?我的意思是说当更改方向时,加载相应的布局。 - sandeepmaaram
有没有一种方法可以通过编程方式设置android:configChanges参数,而不是在清单文件中设置? - CodyF

109

根据官方文档flurin所说,

注意:如果您的应用程序的目标API级别为13或更高(由minSdkVersion和targetSdkVersion属性声明),则您还应声明"screenSize"配置,因为在设备在纵向和横向方向之间切换时,它也会发生变化。

因此,如果您的应用程序目标API级别为13或更高,则应设置此配置:

android:configChanges="orientation|screenSize"


4
非常感谢!其他所有答案都漏掉了API级别13引入的这个“screenSize”东西的部分。 你刚刚拯救了我的生命! :) - Tamás Barta
1
很好的提示,如果你只是业余时间编程,很难跟进文档。 - Jacob Waller
1
+1 很棒的操作,谢谢你与我们分享这个解决方案。你救了我的一天。谢谢 ;) - Simon Dorociak

9
正确的解决方案是:
android:configChanges="orientation|screenSize"

Android文档:

当前可用的屏幕尺寸已更改。这表示相对于当前宽高比,当前可用尺寸发生了变化,因此当用户在横向和纵向之间切换时会发生变化。但是,如果您的应用程序针对API级别12或更低版本,则您的活动始终自己处理此配置更改(即使在运行Android 3.2或更高版本设备时,此配置更改也不会重新启动您的活动)。


6

我曾经搞砸了一段时间,后来发现在清单文件中,我将configChanges放在了应用程序级别而不是活动级别。以下是代码,在正确工作时的样子。

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
                  android:configChanges="orientation|screenSize|keyboardHidden">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity> 
</application> 

2
你应该在帖子中分享代码而不是图片。 - Jules Dupont
请**[编辑]**您的帖子,将实际清单代码显示为文本,而不是屏幕截图。其他人无法从您的图像中复制和粘贴。有关详细信息,请参见此处。谢谢。 - Pang

1

现在 Android 支持分屏显示(在 Android 中称为“多窗口”),您可能希望添加 screenSize|smallestScreenSize|screenLayout|orientation。因此,为了处理旋转和分屏,您需要在 android:configChanges 中使用类似以下内容的代码。

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
                  android:configChanges="orientation|screenSize|keyboardHidden|smallestScreenSize|screenLayout">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity> 
</application>

0

-1
在清单中编写:
android:configChanges="orientation|screenSize|keyboardHidden"

并在解决问题的活动中覆盖此内容:

 @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
}

6
覆盖onConfigurationChanged方法并调用原始实现有什么作用? - ricosrealm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接