在屏幕旋转之前做一些事情?

时间:2013-03-26 15:22:55

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

我想在设备从纵向旋转到横向时do_something()

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

在我的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时,活动仍然重新启动。 (就像不打电话一样。)

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

当我通过ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE时,活动强制关闭 AndroidRuntime:NullPointerException


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

2 个答案:

答案 0 :(得分:3)

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

添加<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()

(因为在我的情况下,我从布局和活动中删除碎片。如果它在super.onSaveInstanceState()之后,布局将已经保存到Bundle中。然后碎片将<在活动重新创建后重新创建strong> 。###)

###我已经证明了这一现象。但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 - 以前 {{ 1}}被称为!!

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

答案 1 :(得分:1)

 // 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 your onCreate()`。

希望这会有所帮助。