我的主要活动有一些代码使一些数据库更改不应被中断。我正在另一个线程中进行繁重的工作,并使用一个设置为不可取消的进度对话框。但是,我注意到,如果我旋转手机,它将重新开始活动,这对于正在运行的进程确实非常不利,并且我得到了强制关闭。
我要做的是以编程方式禁用屏幕方向更改,直到我的过程完成为止,此时启用方向更改。
我的主要活动有一些代码使一些数据库更改不应被中断。我正在另一个线程中进行繁重的工作,并使用一个设置为不可取消的进度对话框。但是,我注意到,如果我旋转手机,它将重新开始活动,这对于正在运行的进程确实非常不利,并且我得到了强制关闭。
我要做的是以编程方式禁用屏幕方向更改,直到我的过程完成为止,此时启用方向更改。
Answers:
正如克里斯在自我回答中所述,
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
然后
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
在真实设备上确实像魅力一样工作!
不要认为在模拟器上测试时坏了,ctrl + F11快捷键总是在不模拟传感器移动的情况下改变屏幕方向。
编辑:这不是最好的答案。如评论中所述,此方法存在问题。真正的答案在这里。
ActivityInfo.SCREEN_ORIENTATION_SENSOR
不遵守Android的本机方向锁定。将方向重置为do ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
。
没有其他答案对我来说是完美的诀窍,但这就是我发现的答案。
将方向锁定为当前...
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
类检测这种方向的方法。
这是一个更完整和最新的解决方案,适用于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
为参数。
为了也管理反向定向模式,我使用了该代码来修复活动定向:
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);
使用 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
用于锁定当前的方向,无论是横向还是纵向。
使用setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
的解锁方向。
我找到了答案。为此,您可以在Activity中setRequestedOrientation(int)
使用以下指定的值之一进行调用:http : //developer.android.com/reference/android/R.attr.html#screenOrientation
在启动线程之前,我调用了setRequestedOrientation(OFF)
(OFF = nosensor),并在线程完成后调用了setRequestedOrientation(ON)
(ON = sensor)。奇迹般有效。
谢谢大家 我修改了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);
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
}
这是每次都可以使用并保留当前方向的解决方案(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);
}
使用ActivityInfo.SCREEN_ORIENTATION_USER
,如果你想仅当设备启用其旋转屏幕。
这对我有效。它解决了平板电脑/手机具有不同的“自然方向”的问题;)
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);
}
我提出了一个解决方案,该解决方案取决于显示器的旋转角度,然后确定设备的方向。通过了解方向,我们可以锁定方向,然后在需要时将其释放。此解决方案还可以确定设备是否处于反向横向模式。
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的锁定代码。因此,我的建议是将两者结合在一起:
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);
在您的活动oncreate方法中