【问题标题】:How to check device natural (default) orientation on Android (i.e. get landscape for e.g., Motorola Charm or Flipout)如何在 Android 上检查设备自然(默认)方向(即获取横向,例如 Motorola Charm 或 Flipout)
【发布时间】:2011-06-01 00:27:03
【问题描述】:

我有一个显示相机预览的活动,因此只需将其设置为横向。在底部(不管设备旋转)我想显示一个文本视图。我正在使用 OrientationEventListener 从其自然位置给出设备的方向。我可以实现一个在纵向默认设备上运行良好的解决方案,但要使其在横向默认设备上也能正常工作,我需要注意在这样的设备上运行。因此问题是如何检查它?

【问题讨论】:

    标签: android


    【解决方案1】:

    经过一番谷歌搜索,我发现一个博客提到通过 adb shell 执行wm size 命令时,它总是会返回未旋转的“自然”屏幕分辨率,然后作者搜索到here

            mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService(
                            Context.WINDOW_SERVICE));
    

    here:

                    mWm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize);
    

    所以,Android 似乎实际上知道初始/未旋转/“自然”屏幕尺寸,但是,它只是不想让应用知道吗?我很困惑...

    【讨论】:

      【解决方案2】:

      这是我一直在使用的:

       /**
           * returns the natural orientation of the device: Configuration.ORIENTATION_LANDSCAPE or Configuration.ORIENTATION_PORTRAIT .<br/>
           * The result should be consistent no matter the orientation of the device
           */
          public static int getScreenNaturalOrientation(@NonNull final Context context) {
              //based on : http://stackoverflow.com/a/9888357/878126
              final WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
              final Configuration config = context.getResources().getConfiguration();
              final int rotation = windowManager.getDefaultDisplay().getRotation();
              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))
                  return Configuration.ORIENTATION_LANDSCAPE;
              else
                  return Configuration.ORIENTATION_PORTRAIT;
          }
      

      您也可以像这样获得自然分辨率:

      /**
       * returns the natural screen size (in pixels). The result should be consistent no matter the orientation of the device
       */
      public static
      @NonNull
      Point getScreenNaturalSize(@NonNull final Context context) {
          if (sNaturalScreenSize != null)
              return sNaturalScreenSize;
          final int screenNaturalOrientation = getScreenNaturalOrientation(context);
          final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
          final int currentOrientation = context.getResources().getConfiguration().orientation;
          if (currentOrientation == screenNaturalOrientation)
              return sNaturalScreenSize = new Point(displayMetrics.widthPixels, displayMetrics.heightPixels);
          //noinspection SuspiciousNameCombination
          return sNaturalScreenSize = new Point(displayMetrics.heightPixels, displayMetrics.widthPixels);
      }
      

      【讨论】:

        【解决方案3】:

        对于 Xamarin 开发人员,这是 C# 中此检查的一个版本:

        var orientation = ContextHelper.Current.Resources.Configuration.Orientation;
        if (orientation == Android.Content.Res.Orientation.Undefined)
        {
            //unknown, you can provide special handling for this case
        }
        
        var isLandscape = false;
        var rotation = windowManager.DefaultDisplay.Rotation;           
        
        switch (rotation)
        {
            case SurfaceOrientation.Rotation0:
            case SurfaceOrientation.Rotation180:
                isLandscape = orientation == Android.Content.Res.Orientation.Landscape;
                break;
            default:
                isLandscape = orientation == Android.Content.Res.Orientation.Portrait;
                break;
        }
        

        【讨论】:

          【解决方案4】:

          您可以使用旋转和方向来定义。无需使用传感器或任何侦听器,只需调用 isDefaultLandscape 方法即可。

          private boolean isDefaultLandscape(final Context context)
          {
              Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
              int rotation = display.getRotation();
              int orientation = context.getResources().getConfiguration().orientation;
          
              switch (rotation)
              {
                  case Surface.ROTATION_180:
                  case Surface.ROTATION_0:
                  {
                      return orientation == Configuration.ORIENTATION_LANDSCAPE;
                  }
                  default:
                  {
                      return orientation == Configuration.ORIENTATION_PORTRAIT;
                  }
              }
          }
          

          【讨论】:

            【解决方案5】:

            解决这个问题很简单

            int orient=this.getResources().getConfiguration().orientation;

            如果它返回 1 或 2

            1 是纵向 2是风景

            【讨论】:

            • 否,返回当前方向。这个问题是关于默认或自然方向的。目标是始终为手机返回 PORTRAIT,为平板电脑返回 LANDSCAPE——无论用户如何旋转设备。 (在三星 Tab S 10 上测试)。在某些情况下需要此信息,以正确处理可用值。例如,在对加速度计输出进行低级滞后算法时。
            【解决方案6】:
            public static boolean isDeviceDefaultOrientationLandscape(Activity a) {
            
                WindowManager windowManager = (WindowManager) a.getSystemService(Context.WINDOW_SERVICE);
            
                Configuration config = a.getResources().getConfiguration();
            
                int rotation = windowManager.getDefaultDisplay().getRotation();
            
                boolean defaultLandsacpeAndIsInLandscape = (rotation == Surface.ROTATION_0 ||
                        rotation == Surface.ROTATION_180) &&
                        config.orientation == Configuration.ORIENTATION_LANDSCAPE;
            
                boolean defaultLandscapeAndIsInPortrait = (rotation == Surface.ROTATION_90 ||
                        rotation == Surface.ROTATION_270) &&
                        config.orientation == Configuration.ORIENTATION_PORTRAIT;
            
                return defaultLandsacpeAndIsInLandscape || defaultLandscapeAndIsInPortrait;
            }
            

            【讨论】:

              【解决方案7】:

              这个方法可以帮助:--

              public int getDeviceDefaultOrientation() {
              
                  WindowManager windowManager =  (WindowManager) getSystemService(Context.WINDOW_SERVICE);
              
                  Configuration config = getResources().getConfiguration();
              
                  int rotation = windowManager.getDefaultDisplay().getRotation();
              
                  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)) {
                    return Configuration.ORIENTATION_LANDSCAPE;
                  } else { 
                    return Configuration.ORIENTATION_PORTRAIT;
                  }
              }
              

              【讨论】:

              • 我会在 if 测试之前添加一个“未定义”旋转测试: if(rotation == Configuration.ORIENTATION_UNDEFINED) return Configuration.ORIENTATION_UNDEFINED;
              • @Pascal:这似乎是错误的。旋转不是方向。你的意思是config.orientation != Configuration.ORIENTATION_UNDEFINED
              • @VioletGiraffe 在新 API 中,getOrientation() 已被弃用并实现为“return getRotation()”。新的 API 显然发生了变化……感谢您的评论。
              • 我发现有时这不能正常工作; orientationgetRotation 在某些时间点不同步。
              • 要获得用于旋转的 windowManager,您还可以使用:int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
              【解决方案8】:

              感谢上面diyism的出色回答,我还添加了检查实际方向位置的逻辑(横向右侧,纵向,横向左侧,纵向翻转): 代码如下:

              @Override
              public void onSensorChanged(SensorEvent event) {
              if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
                  //The coordinate-system is defined relative to the screen of the phone in its default orientation
                  int orientation = 0;
                  float roll=0;
                  float pitch=0;
                  switch (getWindowManager().getDefaultDisplay().getRotation())  {
                      case Surface.ROTATION_0:
                               roll=event.values[2];
                               pitch=event.values[1];
                          break;
                          case Surface.ROTATION_90:
                               roll=event.values[1];
                               pitch=-event.values[2];
                          break;
                          case Surface.ROTATION_180:
                               roll=-event.values[2];
                               pitch=-event.values[1];
                          break;
                          case Surface.ROTATION_270:
                               roll=-event.values[1];
                               pitch=event.values[2];
                          break;
                         }
              
                  if (pitch >= -45 && pitch < 45 && roll >= 45)
                      orientation = 0;
                  else if (pitch < -45 && roll >= -45 && roll < 45) 
                      orientation = 1; 
                  else if (pitch >= -45 && pitch < 45 && roll < -45) 
                      orientation = 2;
                  else if (pitch >= 45 && roll >= -45 && roll < 45 ) 
                      orientation = 3;
              
                  if (m_nOrientation != orientation) { //orientation changed event
                      m_Inst.Debug(LOG_TAG,"onSensorChanged: orientation:" + orientation);
                      m_nOrientation = orientation;
                      // fire event for new notification, or update your interface here
                  }
              }
              

              这段代码也贴在这里:http://www.pocketmagic.net/?p=2847

              【讨论】:

                【解决方案9】:

                可以使用Display.getOrientation()Display.getRotation() 来完成(API 级别>= 8)。

                【讨论】:

                • 这个答案怎么能被选为最佳答案,它甚至没有回答问题。如果您使用 Display.getRotation(),您只知道从自然方向旋转的角度,即在 Asus Transformer eeePad 上纵向的 Surface.ROTATION_90 和三星 Galaxy Nexus 上的横向结果相同。所以绝对不是好答案。
                • @Climbatize,它确实回答了这个问题,但它只是没有提供示例实现或算法。您可以将方向与旋转进行比较以推断自然方向。但是,我建议不要这样做,因为我发现这两个值有时会不同步。
                • @Sam 哦,是的,我明白你的意思,我想我太难过了,没有注意到这个答案包含答案的基础:)
                【解决方案10】:

                我的解决方案(在 HTC 渴望和三星 Galaxy Tab 10.1 测试):

                    private class compass_listener implements SensorEventListener
                            {public void onAccuracyChanged(Sensor sensor, int accuracy) {}
                
                             public void onSensorChanged(SensorEvent event)
                                    {float roll=0;
                                     float pitch=0;
                                     switch (((Activity)context).getWindowManager().getDefaultDisplay().getRotation())
                                            {case Surface.ROTATION_0:
                                                  roll=event.values[2];
                                                  pitch=event.values[1];
                                             break;
                                             case Surface.ROTATION_90:
                                                  roll=event.values[1];
                                                  pitch=-event.values[2];
                                             break;
                                             case Surface.ROTATION_180:
                                                  roll=-event.values[2];
                                                  pitch=-event.values[1];
                                             break;
                                             case Surface.ROTATION_270:
                                                  roll=-event.values[1];
                                                  pitch=event.values[2];
                                             break;
                                            }
                                     JSONObject json=new JSONObject();
                                     try
                                         {json.put("roll", roll);
                                          json.put("pitch", pitch);
                                          json.put("azimuth", event.values[0]);
                                         }
                                     catch (JSONException e)
                                           {throw new RuntimeException(e);
                                           }
                                     java_2_js(webview, "intent_compass_change", json);
                                    }
                            }
                

                【讨论】:

                  【解决方案11】:

                  这是我的解决方案:

                  public class ActivityOrientationTest extends Activity {
                  private static final String TAG = "ActivityOrientationTest";
                  private int mNaturalOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
                  private TextView mTextView;
                  /** Called when the activity is first created. */
                  @Override
                  public void onCreate(Bundle savedInstanceState) {
                      super.onCreate(savedInstanceState);        
                      setContentView(R.layout.main);
                      mTextView = (TextView)findViewById(R.id.text);
                      setDefaultOrientation();        
                  }
                  
                  private void setDefaultOrientation(){
                      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
                  
                      Display display;         
                      display = getWindow().getWindowManager().getDefaultDisplay();
                      int rotation = display.getRotation();
                      int width = 0;
                      int height = 0;
                      switch (rotation) {
                      case Surface.ROTATION_0:
                      case Surface.ROTATION_180:
                          Log.i(TAG, "Rotation is: 0 or 180");
                          width = display.getWidth();
                          height = display.getHeight();
                          break;
                      case Surface.ROTATION_90:       
                      case Surface.ROTATION_270:
                          Log.i(TAG, "Rotation is: 90 or 270");
                          width = display.getHeight();
                          height = display.getWidth();
                          break;
                      default:
                          break;
                      }
                  
                      if(width > height){
                          Log.i(TAG, "Natural Orientation is landscape");
                          mTextView.setText("Natural Orientation is landscape");
                          mNaturalOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
                      } else {
                          Log.i(TAG, "Natural Orientation is portrait");
                          mNaturalOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
                          mTextView.setText("Natural Orientation is portrait");
                      } 
                  
                      setRequestedOrientation(mNaturalOrientation);
                  }
                  

                  Display.getRotation() 仅在 API 级别 8 或更高级别中受支持,因此如果您需要支持旧设备,则需要调用 Display.getOrientation()。

                  【讨论】:

                    【解决方案12】:

                    经过数小时试图弄清楚这一点。这是不可能的。但是,您可以做的最接近的事情是将方向设置为“NOSENSOR”

                     setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
                    

                    这会将您的应用程序设置为设备的自然方向。此时您可以使用 DisplayMetrics 类获取显示器的高度和宽度,并计算您是横向还是纵向。在你确定它是横向还是纵向之后,你就可以这样做了

                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_XXXXX);

                    其中 XXXX 是横向或纵向。

                    如果你有滑出式键盘,这样做可能不起作用。

                    【讨论】:

                    • 应该设置RequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
                    • @diyism,据我所知,SCREEN_ORIENTATION_UNSPECIFIED 允许用户启用自动屏幕旋转或系统USER_ROTATION 设置值更改来覆盖活动方向。
                    【解决方案13】:

                    好吧,您可以了解@Urboss 所说的当前方向。当然,您无法以这种方式获得布局(横向/纵向),因此您必须获取屏幕宽度/高度以检查当前位置(无论是否更改,但您已经检查过;))位置是横向或肖像:

                        DisplayMetrics dm = new DisplayMetrics();
                        getWindowManager().getDefaultDisplay().getMetrics(dm);
                        wPix = dm.widthPixels;
                        hPix = dm.heightPixels;
                    

                    (因此,如果旋转为 0 并且您使用上述矩阵获得横向,则您的设备默认为横向。如果旋转为 90 度并且您为纵向,则默认也是横向,依此类推)

                    【讨论】:

                      【解决方案14】:

                      @Urboss,它不能。您需要首先知道设备的默认方向,因为这两种方法都基于它返回更改(我的意思是,如果默认为纵向,则您要查找的结果将是 1 或 ROTATE_90 - 所以它是横向-,但是, 如果默认为横向,则结果为 0)。

                      据我所知,找到设备的默认方向并非易事:(

                      任何人都可以对这个主题有所了解吗?

                      【讨论】:

                      • 我希望我知道。我真的希望能够找到运行我的应用程序的设备的自然方向。 >=\
                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-03-29
                      • 1970-01-01
                      • 2011-07-02
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多