【问题标题】:Android: Temporarily disable orientation changes in an ActivityAndroid:暂时禁用活动中的方向更改
【发布时间】:2011-04-06 09:40:39
【问题描述】:

我的主要活动有一些代码可以进行一些不应中断的数据库更改。我正在另一个线程中进行繁重的工作,并使用我设置为不可取消的进度对话框。但是,我注意到,如果我旋转手机,它会重新启动对正在运行的进程非常不利的活动,并且我会收到强制关闭。

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

【问题讨论】:

标签: android screen-orientation android-orientation


【解决方案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 相同的相反问题:在纵向使用它会导致活动切换到横向并返回到纵向。
  • 原问题的真正答案在那里:stackoverflow.com/questions/3821423/…
  • 这对我不起作用。这个虽然有效:stackoverflow.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 类检测这种方向的方法。
  • 这行得通。上述问题的答案位于此答案中。 stackoverflow.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 在此页面stackoverflow.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 方法中

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2016-07-14
                      • 1970-01-01
                      相关资源
                      最近更新 更多