优雅地处理活动启动期间的屏幕方向更改

4
我正在寻找一种正确处理设置活动的方式,其中其方向是由启动它的意图中的数据确定的。这是为了一个游戏,用户可以选择关卡,其中一些是纵向方向,一些是横向方向。我面临的问题是,setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)只有在活动完全加载后才会生效。对我来说,这是一个问题,因为我在启动期间执行一些加载和图像处理,我希望只需执行一次。
目前,如果用户选择横向关卡:
- 活动从onCreate()开始,默认为纵向 - 通过分析其启动Intent发现应处于横向方向 - 继续到onResume(),加载信息并执行其他设置任务 - 此时setRequestedOrientation生效,因此应用程序运行到onPause()到onDestroy() - 然后再次从onCreate()开始,并重复从早期进行的设置,直到onResume()
有没有办法避免这样做并使其不重复加载两次?例如,理想情况下,在调用onCreate之前,活动将知道它是否应该是纵向或横向,具体取决于启动意图的某个属性,但除非我错过了什么,否则不可能。我设法通过检查耗时加载步骤之前的布尔值来解决避免重复加载的方法,但这似乎不是正确的做法。我想我可以覆盖onSaveInstanceState,但那需要大量额外的编码。有没有简单的方法来做到这一点?
解决方法:
根据Daniel的答案,这实际上很容易解决。我只需要进行一些小的更改。在我的“菜单”活动中,玩家将选择要玩的级别,我只需要添加一个if / else检查以选择由我的Intent启动的类。这是通过一个简单的int表示纵向或横向完成的,在玩家选择级别时确定。然后,我创建了第二个类,扩展了我的“GameLogic”类;这是包含大部分游戏本身代码的类,而不是菜单、说明等。
public class GameLandscape extends GameLogic{
}

这真的很简单,完全没有内容。这样它就继承了我之前活动中的所有代码,在那里我已经编写了不同方向处理事物的代码。最后,我只需要在清单中添加一行,指定GameLandscape始终在横向运行,而GameLogic始终在纵向运行。

所以这是一个非常简单的问题。

2个回答

6
您可以创建两个活动 - 一个用于纵向级别,另一个用于横向级别 - 然后在AndroidManifest.xml中使用android:screenOrientation属性设置Activity的方向。如果使用继承,您甚至不需要重复代码;将当前Activity用作基类活动,只需创建横向/纵向活动作为该Activity的子类即可。
我认为更好的解决方案是Intent打开这两种情况下的正确Activity,但如果您必须让所有内容通过Intent extra分析路由,则可以将所有级别转发到第三个仅分析Intent然后将其转发到正确Activity的Activity。

好主意,谢谢。我会试一下的。(不过我不确定我需要第三个活动 - 是的,我需要处理Intent以获取存储在extras中的其他信息,但是那段代码已经存在于我的Activity中了。如果你的意思是我可能需要第三个Activity来选择要发送到哪一个,那么我可以在一开始存储方向时就这样做。我在你的回答中哪里误解了呢?:P) - Steve Haley
好的,你说了如何使用Intent来确定是横屏还是竖屏模式。如果你真的需要这样做,你可以使用第三个Activity来分析它然后转发它。但是像我说的那样,最好的解决方案是让Intent在第一次调用时直接调用正确的方向。(如果我的回答有点令人困惑,对不起)。 - Dan Lew
这个方法非常有效,而且实现起来非常简单。对于其他遇到同样问题的人,请查看我在问题下面添加的细节信息。 - Steve Haley

2
您还可以重写 onRetainNonConfigurationInstance() 方法。这样,您可以暂时存储一个项目,并通过调用 getLastNonConfigurationInstance() 方法来检索它。这样,您就可以加载所有需要的东西,在您的 onRetainNonConfigurationInstance() 方法中将其全部保存到数据结构中并返回。然后在您的 onCreate() 方法中,如果 getLastNonConfigurationInstance() 返回 null,则加载所有内容;如果它返回某些东西,则已经全部加载完成。以下是一个快速示例:
public class MyActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        DataStructure myData = (DataStructure)getLastNonConfigurationInstance();
        if(myData == null)
        {
            // Load everything in
        }
        else
        {
            // Unpack myData
        }
    }

    @Override
    public Object onRetainNonConfigurationInstance()
    {
        DataStructure myData = new DataStructure();
        // Put everything in to myData
        return myData;
    }
}

啊,是的,我忘记了onRetainNonConfigurationInstance,但这个解决方案似乎与覆盖onSaveInstanceState类似。两者都需要一些工作来确保我正确保存了所有内容。但丹尼尔上面的解决方案要容易得多,这就是为什么我选择它的原因。 - Steve Haley
当您需要进行预处理一次时,这是正确的方法。 - MrSnowflake

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