Android:暂时禁用活动中的方向更改
Posted
技术标签:
【中文标题】Android:暂时禁用活动中的方向更改【英文标题】:Android: Temporarily disable orientation changes in an Activity 【发布时间】:2011-04-06 09:40:39 【问题描述】:我的主要活动有一些代码可以进行一些不应中断的数据库更改。我正在另一个线程中进行繁重的工作,并使用我设置为不可取消的进度对话框。但是,我注意到,如果我旋转手机,它会重新启动对正在运行的进程非常不利的活动,并且我会收到强制关闭。
我想要做的是以编程方式禁用屏幕方向更改,直到我的过程完成,此时启用方向更改。
【问题讨论】:
由于似乎没有人提到这部分,您将需要导入 android.content.pm.ActivityInfo 以使用 ActivityInfo 标识符。 看***.com/questions/6599770/screen-orientation-lock 参考:***.com/a/32885911/2673792 以获得最佳解决方案 【参考方案1】:正如 Chris 在他的 self-answer 中解释的那样,调用
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
然后
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
真的很像魅力......在真实设备上!
在模拟器上测试时不要以为它坏了,ctrl+F11快捷键总是改变屏幕方向,而不模拟传感器移动。
编辑:这不是最好的答案。如 cmets 中所述,此方法存在问题。 The real answer is here.
【讨论】:
我找不到那些常量。谢谢你。 这些方法有问题...如果您调用 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);当设备不在其默认方向使用时,活动方向立即更改(销毁并重新创建)为设备默认方向。例如,在手机上,如果您将其保持为横向,则在重新激活传感器时,活动将切换为纵向并返回横向。与爱可视 A5 IT 相同的相反问题:在纵向使用它会导致活动切换到横向并返回到纵向。 原问题的真正答案在那里:***.com/questions/3821423/… 这对我不起作用。这个虽然有效:***.com/a/10488012/1369016 我不得不调用 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);或 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);基于从 getResources().getConfiguration().orientation 检索到的当前方向。ActivityInfo.SCREEN_ORIENTATION_SENSOR
不尊重 Android 的本机方向锁定。将方向重置为 ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
即可。【参考方案2】:
其他答案都没有完美地为我解决问题,但这是我发现的。
锁定当前方向...
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
当应再次允许更改方向时,设置回默认值...
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
【讨论】:
这个问题是Configuration.ORIENTATION_PORTRAIT
将在两种横向模式下返回(即“正常”和反向)。因此,如果手机处于反向横向并且您将其设置为ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
,它将翻转过来。在 API 9 中,ActivityInfo 引入了SCREEN_ORIENTATION_REVERSE_LANDSCAPE
常量,但我没有看到通过Configuration
类检测这种方向的方法。
这行得通。上述问题的答案位于此答案中。 ***.com/a/10453034/1223436
对我的需求也很有帮助,非常感谢【参考方案3】:
这是一个更完整和最新的解决方案,适用于 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);
【讨论】:
非常适合我使用平板电脑和手机。 对我来说适用于各种设备的唯一正确答案。 绝对是最佳答案!您可以将此方法设为static
并添加Activity activity
作为参数。【参考方案4】:
为了管理反向模式,我使用该代码来修复活动方向:
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);
【讨论】:
【参考方案5】:使用setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
锁定当前方向,无论是横向还是纵向。
使用setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
解锁方向。
【讨论】:
短期临时锁定的最佳解决方案。不会弄乱传感器的当前方向。 适用于 Build.VERSION.SDK_INT >= 18 ,tdjprog 在此页面***.com/a/41812971/5235263 中给出了更完整的答案@【参考方案6】:我找到了答案。为此,您可以在 Activity 中使用此处指定的值之一调用 setRequestedOrientation(int)
:http://developer.android.com/reference/android/R.attr.html#screenOrientation
在我启动线程之前,我调用了setRequestedOrientation(OFF)
(OFF = nosensor),线程完成后我调用了setRequestedOrientation(ON)
(ON = sensor)。像魅力一样工作。
【讨论】:
【参考方案7】:谢谢大家。我修改了 Pilot_51 的解决方案,以确保我恢复到以前的状态。我还进行了更改以支持非横向和非纵向屏幕(但尚未在此类屏幕上进行测试)。
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);
【讨论】:
好东西——不知道你为什么不使用switch
。
我添加第三个选项后忘记清理并更改为开关。
如果您无权访问活动对象而只能访问上下文 ActivityInfo.SCREEN_ORIENTATION_NOSENSOR|ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED,我发现此方法无需获取当前配置即可工作【参考方案8】:
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
【讨论】:
您能否为您的答案添加一些解释? 当您在后台有一些工作时,只需调用 setLockScreenOrientation(true) 来锁定方向并防止破坏当前活动以重新创建它。当您确保这些作业完成后,调用 setLockScreenOrientation(false)。 这是最好的答案!【参考方案9】:这是一个每次都有效并保持当前方向的解决方案(例如,使用 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);
【讨论】:
值得一提:仅限 API 18+【参考方案10】:如果您只想在设备上启用屏幕时旋转屏幕,请使用ActivityInfo.SCREEN_ORIENTATION_USER
。
【讨论】:
【参考方案11】:这对我来说很完美。它解决了平板电脑/手机不同“自然方向”的问题;)
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);
【讨论】:
【参考方案12】:我想出了一个解决方案,它取决于显示器的旋转,然后决定设备的方向。通过知道方向,我们可以锁定方向并在以后需要时释放它。此解决方案还可以确定设备是否处于反向横向模式。
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);
【讨论】:
【参考方案13】:我认为这段代码更容易阅读。
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);
【讨论】:
【参考方案14】:我发现需要结合现有的旋转/方向值来涵盖四种可能性;有纵向/横向值和设备的自然方向。假设当屏幕处于“自然”纵向或横向时,设备的自然方向的旋转值为 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 );
【讨论】:
【参考方案15】:我不喜欢这里的大多数答案,因为在解锁时他们将其设置为 UNSPECIFIED 而不是之前的状态。 ProjectJourneyman 确实考虑到了这一点,这很棒,但我更喜欢 Roy 的锁定代码。所以,我的建议是两者兼而有之:
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);
【讨论】:
【参考方案16】:你可以使用
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;
【讨论】:
【参考方案17】:使用那行代码
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
在你的活动 oncreate 方法中
【讨论】:
以上是关于Android:暂时禁用活动中的方向更改的主要内容,如果未能解决你的问题,请参考以下文章