Android:暂时禁用活动中的方向更改

我的主要活动有一些代码,使一些数据库的变化,不应该被打断。 我在另一个线程中做了繁重的工作,并使用了我设置为不可取消的进度对话框。 不过,我注意到,如果我旋转我的电话,它会重新启动对于正在运行的进程是非常不利的活动,并且我得到一个强制closures。

我想要做的是以编程方式禁用屏幕方向更改,直到我的过程完成,在此时方向更改已启用。

正如克里斯在自己的回答中所解释的那样,呼吁

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); 

接着

 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); 

真正的作品像魅力…在真实的设备上!

不要以为在仿真器上testing时会损坏,ctrl + F11快捷键总是改变屏幕的方向,而不模仿传感器的移动。

编辑:这不是最好的答案。 正如评论中所解释的那样,这个方法有问题。 真正的答案在这里 。

没有其他的答案完全适合我,但这是我发现的。

locking方向到当前…

 if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 

当改变方向时,应该再次允许,设置回默认…

 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 

这里是一个更完整和最新的解决scheme,适用于API 8 +,适用于反向纵向和横向,并在“自然”方向为横向的Galaxy选项卡上工作(调用activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)解锁方向):

 @SuppressWarnings("deprecation") @SuppressLint("NewApi") public static void lockActivityOrientation(Activity activity) { Display display = activity.getWindowManager().getDefaultDisplay(); int rotation = display.getRotation(); int height; int width; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) { height = display.getHeight(); width = display.getWidth(); } else { Point size = new Point(); display.getSize(size); height = size.y; width = size.x; } switch (rotation) { case Surface.ROTATION_90: if (width > height) activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); else activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; case Surface.ROTATION_180: if (height > width) activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); else activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; case Surface.ROTATION_270: if (width > height) activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); else activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; default : if (height > width) activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); else activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } } 

为了pipe理相反的方向模式,我使用这个代码来解决活动方向:

 int rotation = getWindowManager().getDefaultDisplay().getRotation(); switch(rotation) { case Surface.ROTATION_180: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; case Surface.ROTATION_270: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; case Surface.ROTATION_0: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; case Surface.ROTATION_90: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; } 

再次允许方向:

 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 

我find了答案。 要做到这一点,在一个活动,你可以调用setRequestedOrientation(int)与这里指定的值之一: http : //developer.android.com/reference/android/R.attr.html#screenOrientation

在我启动我的线程之前,我调用了setRequestedOrientation(OFF) (OFF = nosensor),当线程完成时,我调用了setRequestedOrientation(ON) (ON = sensor)。 奇迹般有效。

谢谢大家。 我修改了Pilot_51的解决scheme,以确保我恢复到以前的状态。 我也投入了一些修改来支持非横向和非纵向的屏幕(但还没有在这样的屏幕上进行testing)。

 prevOrientation = getRequestedOrientation(); if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); } 

然后恢复它

 setRequestedOrientation(prevOrientation); 

使用setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); locking当前的方向,无论是风景还是肖像。

使用setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); 解锁方向。

这里是一个解决scheme,每次工作,并保留当前的方向(使用Activity.Info.SCREEN_ORIENTATION_PORTRAIT设置为0°,但用户可以有一个180°的方向作为当前)。

 // Scope: Activity private void _lockOrientation() { if (super.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT); } else { super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE); } } private void _unlockOrientation() { super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); } 
 protected void setLockScreenOrientation(boolean lock) { if (Build.VERSION.SDK_INT >= 18) { setRequestedOrientation(lock?ActivityInfo.SCREEN_ORIENTATION_LOCKED:ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); return; } if (lock) { switch (getWindowManager().getDefaultDisplay().getRotation()) { case 0: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; // value 1 case 2: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; // value 9 case 1: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; // value 0 case 3: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; // value 8 } } else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); // value 10 } 

这对我来说是完美的。 它解决了平板电话不同“自然方向”的问题;)

 int rotation = getWindowManager().getDefaultDisplay().getRotation(); Configuration config = getResources().getConfiguration(); int naturalOrientation; if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) && config.orientation == Configuration.ORIENTATION_LANDSCAPE) || ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) && config.orientation == Configuration.ORIENTATION_PORTRAIT)) { naturalOrientation = Configuration.ORIENTATION_LANDSCAPE; } else { naturalOrientation = Configuration.ORIENTATION_PORTRAIT; } // because getRotation() gives "rotation from natural orientation" of device (different on phone and tablet) // we need to update rotation variable if natural orienation isn't 0 (mainly tablets) if (naturalOrientation == Configuration.ORIENTATION_LANDSCAPE) rotation = ++rotation % 4; switch (rotation) { case Surface.ROTATION_0: //0 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; case Surface.ROTATION_90: //1 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; case Surface.ROTATION_180: //2 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; case Surface.ROTATION_270: //3 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; } } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); } 

使用ActivityInfo.SCREEN_ORIENTATION_USER如果你想旋转屏幕只有当它的设备上启用。

我已经想出了一个解决scheme,这取决于显示器的旋转,然后决定设备的方向。 从知道方向我们可以locking方向,并在需要时再放行。 此解决scheme还可以确定设备是否处于反向横向模式。

 private void lockOrientation(){ switch (((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation()) { // Portrait case Surface.ROTATION_0: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; //Landscape case Surface.ROTATION_90: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; // Reversed landscape case Surface.ROTATION_270: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; } } 

然后,如果我们需要释放方向,我们可以调用这个方法:

 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 

我认为这个代码更容易阅读。

 private void keepOrientation() { int orientation = getResources().getConfiguration().orientation; int rotation = getWindowManager().getDefaultDisplay().getRotation(); switch (rotation) { case Surface.ROTATION_0: if (orientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } break; case Surface.ROTATION_90: if (orientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } break; case Surface.ROTATION_180: if (orientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); } break; default: if (orientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); } } } 

我发现现有的旋转/方向值的组合需要涵盖四种可能性; 有肖像/风景值和设备的自然方向。 假设当屏幕处于“自然”纵向或横向时,设备的自然方向将具有0度的旋转值。 同样的,当它处于横向或纵向时,会有一个90度的旋转值(注意它与@ 0度的方向相反)。 所以不是0或90度的旋转值意味着“反向”的方向。 好的,下面是一些代码:

 public enum eScreenOrientation { PORTRAIT (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT), LANDSCAPE (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE), PORTRAIT_REVERSE (ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT), LANDSCAPE_REVERSE (ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE), UNSPECIFIED_ORIENTATION (ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); public final int activityInfoValue; eScreenOrientation ( int orientation ) { activityInfoValue = orientation; } } public eScreenOrientation currentScreenOrientation ( ) { final int rotation = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation(); final int orientation = getResources().getConfiguration().orientation; switch ( orientation ) { case Configuration.ORIENTATION_PORTRAIT: if ( rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90 ) return eScreenOrientation.PORTRAIT; else return eScreenOrientation.PORTRAIT_REVERSE; case Configuration.ORIENTATION_LANDSCAPE: if ( rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90 ) return eScreenOrientation.LANDSCAPE; else return eScreenOrientation.LANDSCAPE_REVERSE; default: return eScreenOrientation.UNSPECIFIED_ORIENTATION; } } public void lockScreenOrientation ( ) throws UnsupportedDisplayException { eScreenOrientation currentOrientation = currentScreenOrientation( ); if ( currentOrientation == eScreenOrientation.UNSPECIFIED_ORIENTATION ) throw new UnsupportedDisplayException("Unable to lock screen - unspecified orientation"); else setRequestedOrientation( currentOrientation.activityInfoValue ); } public void unlockScreenOrientation ( ) { setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED ); } 

我不喜欢这里的大部分答案,因为在解锁状态下,他们将其设置为“未定”而不是之前的状态。 ProjectJourneyman确实考虑到了这一点,但是我更喜欢Roy的locking代码。 所以,我的build议是两个组合:

 private int prevOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; private void unlockOrientation() { setRequestedOrientation(prevOrientation); } @SuppressWarnings("deprecation") @SuppressLint("NewApi") private void lockOrientation() { prevOrientation = getRequestedOrientation(); Display display = getWindowManager().getDefaultDisplay(); int rotation = display.getRotation(); int height; int width; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) { height = display.getHeight(); width = display.getWidth(); } else { Point size = new Point(); display.getSize(size); height = size.y; width = size.x; } switch (rotation) { case Surface.ROTATION_90: if (width > height) setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); else setRequestedOrientation(9/* reversePortait */); break; case Surface.ROTATION_180: if (height > width) setRequestedOrientation(9/* reversePortait */); else setRequestedOrientation(8/* reverseLandscape */); break; case Surface.ROTATION_270: if (width > height) setRequestedOrientation(8/* reverseLandscape */); else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; default : if (height > width) setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } } 

您可以使用

 public void swapOrientaionLockState(){ try{ if (Settings.System.getInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 1) { Display defaultDisplay = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); Settings.System.putInt(mContext.getContentResolver(), Settings.System.USER_ROTATION, defaultDisplay.getRotation()); Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0); } else { Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 1); } Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, !orientationIsLocked() ? 1 : 0); } catch (Settings.SettingNotFoundException e){ e.printStackTrace(); } } public boolean orientationIsLocked(){ if(canModifiSetting(mContext)){ try { return Settings.System.getInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 0; } catch (Settings.SettingNotFoundException e) { e.printStackTrace(); } } return false; } public static boolean canModifiSetting(Context context){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return Settings.System.canWrite(context); } else { return true; } } 

使用这一行代码

 this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 

在你的活动中创build方法