检查onCreate是否由于屏幕方向改变而调用,这是否可能?

23

我需要在onStart()方法中根据orientation change的结果以不同的方式进行操作,这取决于onCreate()方法是如何被调用的。有可能检查到吗?

实际上,我需要在活动启动时做某事,除非用户更改了方向。

我需要清楚地区分当用户仅切换到另一个应用程序并返回时或者用户更改设备方向的情况。

8个回答

14

根据Nahtan的想法,我写了以下代码:

在onCreate()方法中:

if ( (oldConfigInt & ActivityInfo.CONFIG_ORIENTATION)==ActivityInfo.CONFIG_ORIENTATION ) {
    // ... was rotated
} else {
    // ... was not rotated
}

在onDestroy()方法中:

super.onDestroy();
oldConfigInt = getChangingConfigurations();

10
public class MyActivity extends Activity {
    boolean fromOrientation=false;
    SharedPreferences myPrefLogin;
    Editor prefsEditor;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        prefsEditor = myPrefLogin.edit();
        myPrefLogin = this.getSharedPreferences("myPrefs", Context.MODE_WORLD_READABLE);
        fromOrientation = myPrefLogin.getString("fromOrient", false);

        if(fromOrientation) {
             // do as per need--- logic of orientation changed.
        } else {
             // do as per need--- logic of default onCreate().
        }
    }

    @Override
    public Object onRetainNonConfigurationInstance() {
        prefsEditor.putString("fromOrient", true);
        prefsEditor.commit();
        return null;
    }

    @Override
    protected void onDestroy() {
        if(fromOrientation) {
            prefsEditor.putString("fromOrient", false);
            prefsEditor.commit();
        }
        super.onDestroy();
    }  
}

标志位fromOrientation(告诉状态配置是否已更改) 我们默认情况下认为 onCreate() 不是由于方向改变而调用的。如果方向改变(onRetainNonConfigurationInstance()),则我们会将标志值设置在首选项中,以便知道 onCreate() 是从方向还是其他方式调用的。 最后,在onDestroy()中,我们再次重置方向标志。


1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Kesty

5

只需检查捆绑包(bundle):当活动(activity)首次启动时,bundle将为null。如果有方向变化,则应为非空。

android文档中:

如果在先前关闭后重新初始化活动(activity),则此Bundle包含它最近在onSaveInstanceState(Bundle)中提供的数据。注意:否则它为null。

编辑:我认为您不必在onSaveInstanceState中提供bundle就可以使其在方向更改后为非null,但这很简单。


实际上我需要做的是在活动开始时执行某些操作,除非用户更改方向(从描述中复制) - Eugene
然后在onCreate中检查bundle是否为空,如果是,则执行“something”。 - Nathan Fig
明白了,你只是想要识别第一次调用。在这种情况下,我认为我有一个更好的答案,我会单独发布。 - Nathan Fig
当我在一个活动中有一个计时器需要只启动一次,并且在重新启动之前该活动已经被完成时,它对我有效。 - Matthew Mitchell

5
尝试使用getChangingConfigurations方法。使用此方法可以发现由于屏幕方向更改而导致活动被销毁的时间,设置标志,并在onCreate被调用时检查该标志。
这样做的好处是不需要覆盖清单中的方向配置,就可以知道活动为什么正在重新启动。

根据参考文档,尽管该方法并不完全可靠,但建议仅将其用作提示。 - Price

1

正如其他人所说,保存状态:

public class MyActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if(savedInstanceState == null) {
            // app started afresh, don't check orientation
            /* do application first-run stuff */
        } else {
            // re-started, so check for orientation change
            boolean orientationChanged = false;
            if(savedInstanceState != null) {
                int lastOrientation = savedInstanceState.getInt("last_orientation");
                orientationChanged = (getOrientation() != lastOrientation);
            }

            if(orientationChanged) {
                // orientation changed
                /* do stuff */
            } else {
                // orientation has not changed
                /* do stuff */
            }
        }
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putInt("last_orientation", getOrientation());
    }

    private int getOrientation() {
        // ...
    }
}

如果您将应用程序最小化并从横向模式重新启动,则此方法将无效。在这种情况下,您将拥有不同的方向,并触发if条件,这是不符合要求的。 - Eugene
为什么需要确定用户在Activity内部或外部更改了方向? - Dave
因为我需要在用户启动应用程序时执行一项操作,但不需要在用户使用应用程序时执行(例如更改设备方向)。 - Eugene
其实,Nathan的回答绝对值得追查! - Dave
你应该进行区分,因为如果你在纵向模式下工作,你的currentOrientation == 1(例如),然后你切换到另一个应用程序,将方向更改为横向并切换回应用程序。你的currentOrienataion == 0。在这种情况下,你有oldOrientation != currentOrientation -> 方向已更改,当用户启动应用程序时我需要执行的“事情”不会发生。我希望这次我表述清楚了。 - Eugene
显示剩余3条评论

0
您可以尝试以下方法。 在每个onStart中,您可以保存当前方向(请查看此处)。 如果这是第一次onStart调用,则不执行任何操作;在其他调用中,检查方向是否已更改并执行所需操作。
private int m_currentOrientation = -1;

public void onStart()
{
   int oldOrientation = m_currentOrientation; // 
   m_currentOrientation = getCurrentOrientation(); // As in the link above
   if ((oldOrientation != -1) && (oldOrientation != m_currentOrientation))
   {
       // Do what you need
   }
}

1
你可以使用onSaveInstanceState,这里有详细内容:https://dev59.com/MnVC5IYBdhLWcg3w51hv#151940 - Lior Ohana
无论如何,onCreate() 不仅会在屏幕方向改变后发生,还可能在其他情况下发生(例如,在应用程序中转到主屏幕并返回)。 - Eugene
但在这种情况下,m_CurrentOrientation将是相同的。 - Lior Ohana
@Nikola,这并不完全正确,因为您可以将值保存在saveInstanceState()中。当您第二次启动应用程序时,如果没有进行任何配置更改,则此方法将无法正常工作。 - Eugene
@Lior,你提出的方案是正确的,但我稍微更新了一下描述,情况变得有点困难。如果您只是第二次启动应用程序,则您的建议不起作用,该值将为-1,并且两个值相等,这不会触发该情况,但它应该。我需要其他方法。 - Eugene
显示剩余3条评论

0
在这种情况下,为什么不自己处理配置更改(方向)呢?告诉Android不要处理屏幕方向。
android:configChanges="keyboardHidden|orientation"

然后,您只需覆盖onConfigurationChanged方法以获取视图重新排列或其他需要完成的事情。留下您不想执行的内容。

@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  //do your jobs 
}

1
如果他希望在纵向和横向模式下拥有不同的布局,这将会在未来造成问题。Android在方向更改期间重新启动活动是有原因的。 - Nathan Fig
仍然可以通过这种方法设置不同的布局。我们所需要做的就是检查新配置中的方向,将其放置在条件语句中,并执行“setContentView(properlayout)”操作。无论如何,我同意“Android在方向更改期间重新启动活动”的事实。但是,我们可以根据自己的需求进行操作,不是吗? - PH7
1
如果您以这种方式处理旋转并从onConfigurationChanged调用setContentView,则视图的状态不会被保存和恢复。例如,如果您有一个EditView,它的内容将被重置。 - Salw

0

如果应用程序是第一次启动,则 mCurrentOrientation 将为 -1。

static int mCurrentOrientation = -1;

public void onStart()
{
   int oldOrientation = mCurrentOrientation; 
   mCurrentOrientation = getCurrentOrientation(); 
   if ((oldOrientation != -1) && (oldOrientation != mCurrentOrientation)) {
       // Do your something here.
   }
}

如果我正确理解了你的问题,我认为这个应该适合你。

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