在 Android 中处理活动轮换

发布于 2024-09-25 05:35:27 字数 894 浏览 10 评论 0 原文

我需要为我的活动的纵向和横向应用不同的布局。此外,如果方向是纵向,我需要显示警报。

我已在 AndroidManifest.xml 中指定了 android:configChanges="orientation|keyboardHidden"我还像这样重写 onConfigurationChanged 方法:

@Override
public void onConfigurationChanged(Configuration newConfig)
{
    Log.d("tag", "config changed");
    super.onConfigurationChanged(newConfig);

    int orientation = newConfig.orientation;
    if (orientation == Configuration.ORIENTATION_PORTRAIT)
        Log.d("tag", "Portrait");
    else if (orientation == Configuration.ORIENTATION_LANDSCAPE)
        Log.d("tag", "Landscape");
    else
        Log.w("tag", "other: " + orientation);

    ....
}

从横向旋转到纵向日志时看起来像:

config changed
Portrait

但是从纵向更改为横向时看起来像

config changed
Portrait
config changed
Landscape

为什么 onConfigurationChanged 被调用两次?我怎样才能避免它?

I need to apply different layouts for portrait and landscape orientations of my activity. Besides, I need to show alert if orientation is portrait.

I have specified android:configChanges="orientation|keyboardHidden" in AndroidManifest. I also override onConfigurationChanged method like this:

@Override
public void onConfigurationChanged(Configuration newConfig)
{
    Log.d("tag", "config changed");
    super.onConfigurationChanged(newConfig);

    int orientation = newConfig.orientation;
    if (orientation == Configuration.ORIENTATION_PORTRAIT)
        Log.d("tag", "Portrait");
    else if (orientation == Configuration.ORIENTATION_LANDSCAPE)
        Log.d("tag", "Landscape");
    else
        Log.w("tag", "other: " + orientation);

    ....
}

While rotating from landscape to portrait log looks like:

config changed
Portrait

But while changing from portrait to landscape it looks like

config changed
Portrait
config changed
Landscape

Why onConfigurationChanged is called twice? How can I avoid it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

苍景流年 2024-10-02 05:35:27

请参阅我对另一个问题的回答: https://stackoverflow.com/a/3252547/338479

简而言之,处理配置正确的改变是很难做到的。最好实现 onRetainNonConfigurationInstance()在您的应用程序由于配置更改而即将停止并重新启动之前调用。使用此方法保存您想要的任何内容(“这是一个不错的选择”),然后让系统拆除您的应用程序。

当您的应用程序使用新配置重新启动时,请使用 getLastNonConfigurationInstance () 检索您刚刚保存的状态,并使用它来继续您的应用程序,而无需对捆绑包和共享首选项进行任何处理。

See my answer to another question here: https://stackoverflow.com/a/3252547/338479

In short, handling configuration changes correctly is hard to do. It's best to implement onRetainNonConfigurationInstance() which is called just before your application is about to be stopped and restarted due to a configuration change. Use this method to save anything you want ('this' is a good choice) and then let the system tear down your app.

When your app gets restarted with the new configuration, use getLastNonConfigurationInstance() to retrieve the state you just saved, and use it to continue your application without all that mucking about with bundles and shared preferences.

月依秋水 2024-10-02 05:35:27

您可以简单地保存之前的方向并检查它是否确实发生了变化。

如果您在 AndroidManifest.xml android:configChanges 中将 Activity 的 keyboardHidden|orientation 设置为 onCreate 等。不会被调用。这使得实施变得更加容易实施。但当然布局也会从纵向变为横向。

You can simply save the previous orientation and check if it has really changed.

If you set in AndroidManifest.xml android:configChanges to keyboardHidden|orientation for your activity, onCreate etc... won't be called. That makes the implementation significantly easier to implement. But of course layout will change from portrait to landscape as well.

司马昭之心 2024-10-02 05:35:27

您选择以这种方式处理轮换有什么特殊原因吗?虽然它更快,因为活动不会在方向改变时重新启动,但如果我没记错的话,通常不建议这样做。处理方向更改的另一种方法是重写 onConfigurationChanged(),而是重写 onCreate()onStart()onResume() 这样

@Override
public void onStart() {
    super.onStart();
    int orientation = getWindowManager().getDefaultDisplay().getOrientation();
    if(orientation == Configuration.ORIENTATION_PORTRAIT) {
        Log.i(TAG, "Orientation is portrait");
        // show whatever alerts here
    }
}

,然后指定两种布局 - 一种用于纵向,一种用于横向。布局的纵向版本将保留在 res/layout/whatever.xml 中,横向版本将保留在 res/layout-land/whatever.xml 中。 AndroidGuys 就这个主题写了很多好文章,请参阅 http: //androidguys.com/?s=rotational+forces&x=9&y=9

Is there any particular reason you chose to handle rotation in this manner? While it is quicker since the activity doesn't get restarted on an orientation change, it isn't typically recommended, if I recall correctly. Another way to handle orientation changes is instead of overriding onConfigurationChanged(), overriding onCreate(), onStart() or onResume() such that

@Override
public void onStart() {
    super.onStart();
    int orientation = getWindowManager().getDefaultDisplay().getOrientation();
    if(orientation == Configuration.ORIENTATION_PORTRAIT) {
        Log.i(TAG, "Orientation is portrait");
        // show whatever alerts here
    }
}

and then specifying two layouts - one for portrait, one for landscape. The portrait version of the layout would remain at res/layout/whatever.xml, and the landscape version would live in res/layout-land/whatever.xml. The AndroidGuys had written a bunch of good articles on this topic, see http://androidguys.com/?s=rotational+forces&x=9&y=9

悲欢浪云 2024-10-02 05:35:27

我很确定您会想使用 onCreate 而不是 onStart。唯一的区别似乎是当应用程序到达前台时 onStart 将被调用。在这种情况下,您不想让用户等待您重新初始化 UI。否则,只需根据该 if 条件更改 setContentView 调用即可。

I'm pretty sure you would want to use onCreate rather than onStart. The only difference appears to be that onStart will get called when the application comes to the foreground. That wouldn't be a case where you'd want to make the user wait for you to re-initialize the UI. Otherwise, just change your setContentView call based on that if condition.

倥絔 2024-10-02 05:35:27

Android 在更改方向时会启动 Activity 的新实例,因此使用 onCreate 是理想的方法。显然,您必须保存/恢复活动的数据,以便从上次中断的地方继续操作 - 但无论如何您都应该这样做,因为任何数量的事件都可能使您的应用程序失去焦点/终止。

Android starts a new instance of your activity when changing orientation so using onCreate is the ideal method. You will have to save/restore your activity's data obviously in order to pick up where you left off - but you should be doing this anyway since any number of events can unfocus/kill your application.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文