【问题标题】:Do something right before Screen Rotation?在屏幕旋转之前做点什么?
【发布时间】:2013-03-26 15:22:55
【问题描述】:

每当设备从纵向旋转到横向时,我都想do_something()

我在清单中添加了<activity android:configChanges="orientation" >。因此,每当我旋转我的设备时,都会调用onConfigurationChanged()。而且它不会重新创建 Activity。

在我的onConfigurationChanged() 函数中:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        do_something();
    }
    then_fire_off_the_screen_rotation_as_normal();
    // which means re-start the Activity
    // i expect it will fire off onSaveInstanceState() -> onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onRestoreInstanceState() -> onResume()
}

我的问题是,我不知道我可以在then_fire_off_the_screen_rotation_as_normal() 中做什么。

我尝试过使用setRequestedOrientation(),但它似乎不是用于此目的的功能:

当我传入ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIEDActivityInfo.SCREEN_ORIENTATION_SENSORActivityInfo.SCREEN_ORIENTATION_USER 时,Activity 仍然没有重新启动。 (就像不打电话一样。)

当我传入ActivityInfo.SCREEN_ORIENTATION_NOSENSOR 时,方向传感器关闭。 (正如它所说。)

当我传入ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE 时,活动是强制关闭AndroidRuntime:NullPointerException


(具体一点:这是因为在纵向布局中以编程方式添加了片段,但在横向布局中没有。在do_something() 函数中,我将删除这些片段,因为它们在横向中不需要模式。)

【问题讨论】:

    标签: android android-fragments android-manifest screen-orientation onconfigurationchanged


    【解决方案1】:

    嗯,我想这个简单的方法可以满足我的需求:

    不要添加<activity android:configChanges="orientation" >。意味着不需要覆盖onConfigurationChanged()

    onSaveInstanceState():

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
            do_something();
        }
        super.onSaveInstanceState(outState);
    }
    

    * 确保你do_something() 之前 super.onSaveInstanceState()

    (因为在我的情况下,我从 Layout 和 Activity 中删除了 Fragments。如果它在 super.onSaveInstanceState() 之后,则 Layout 将已经保存到 Bundle 中。然后 Fragments 将 在Activity重新创建后重新创建。###)

    ###我已经证明了这个现象。但What to determine a Fragment restore upon Activity re-create? 的原因只是我的猜测。如果您对此有任何想法,请回复my another question。谢谢!


    嗯,对上面的方法进一步改进,解决了第一条评论提出的问题:(还是简单的)

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        if (isPortrait2Landscape()) {
            do_something();
        }
        super.onSaveInstanceState(outState);
    }
    
    private boolean isPortrait2Landscape() {
        return isDevicePortrait() && (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
    }
    

    isDevicePortrait() 就像:

    private boolean isDevicePortrait() {
        return (findViewById(R.id.A_View_Only_In_Portrait) != null);
    }
    

    * 请注意,我们不能使用getResources().getConfiguration().orientation 来确定设备当前是否为纵向。这是因为Resources 对象在屏幕旋转RIGHT AFTER - EVEN BEFORE onSaveInstanceState() 是叫!!

    如果您不想使用findViewById() 来测试方向(出于任何原因,而且它毕竟不是那么整洁),请保留一个全局变量private int current_orientation; 并在onCreate() 中将其初始化为current_orientation = getResources().getConfiguration().orientation;。这看起来更整洁。但我们应该注意不要在 Activity 生命周期的任何地方更改它。

    【讨论】:

    • 嗯,我已经想到了这种方法的决定性弱点。当我们处于横向模式时,然后切换应用程序或锁定屏幕,这将触发do_something(),这是不应该的。
    【解决方案2】:
     // which means re-start the Activity
     // i expect it will fire off onSaveInstanceState() -> onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onRestoreInstanceState() -> onResume()
    

    onPause()、onStop() 等会触发的假设是不正确的。通过使用onConfigurationChanged,您是在告诉Android 不要执行这些步骤,而是您将处理在临时变量中保存有关布局的信息,然后调用InitializeUI(),然后将布局设置回您想要的方式。我将在稍后发布一个我拥有的类似并为我工作的示例。

    编辑:这里是示例

    @Override
    public void onConfigurationChanged(Configuration newConfig){
        super.onConfigurationChanged(newConfig);
        setContentView(R.layout.main);
        Log.i("configChange", "configChange");
    
        String tmp = connect.getText().toString();
        boolean onTmp = on.isEnabled();
        boolean offTmp = off.isEnabled();
        boolean connTmp = reconnect.isEnabled();
    
        InitializeUI();
    
        connect.setText(tmp);
        on.setEnabled(onTmp);
        off.setEnabled(offTmp);
        reconnect.setEnabled(connTmp);
    }
    

    现在我的InitializeUI() 方法只不过是一堆findViewById 和设置onClickListeners。还要确保调用InitializeUI() in youronCreate()`。

    希望这会有所帮助。

    【讨论】:

    • 感谢您的回复@TronicZomB。我也想过这种方法。您的示例确实提醒我保存InitializeUI() 之前的状态并稍后恢复它们。但是在阅读您的建议时,我想出了一个解决方案,我认为它更简单并且可以解决我的问题。如有不足请指正:)
    • 您提出的新解决方案是什么?
    猜你喜欢
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-01
    • 2015-03-04
    相关资源
    最近更新 更多