如何获取Android设备的当前方向(ActivityInfo.SCREEN_ORIENTATION_*)?

59

我想找出设备的详细方向,最好是以下之一:SCREEN_ORIENTATION_LANDSCAPESCREEN_ORIENTATION_PORTRAITSCREEN_ORIENTATION_REVERSE_LANDSCAPESCREEN_ORIENTATION_REVERSE_PORTRAIT,并从 ActivityInfo 或等效方式中获取。

这里在 StackOverflow 上的某些答案包括:

getWindowManager().getDefaultDisplay().getRotation()

但是这并不能真正告诉我设备是处于纵向还是横向模式,只能告诉我设备相对于自然位置的旋转方式,而这本身就可以是纵向或横向。

getResources().getConfiguration().orientation

返回以下三种之一:ORIENTATION_LANDSCAPEORIENTATION_PORTRAITORIENTATION_SQUARE,但这并不能告诉我手机被翻转的方向(是否倒置或其朝向的哪一侧)。

我知道可以将后者与DisplayMetrics结合使用以查找设备的自然方向,但确实没有更好的方法吗?

8个回答

91

我最终使用了以下解决方案:

private int getScreenOrientation() {
    int rotation = getWindowManager().getDefaultDisplay().getRotation();
    DisplayMetrics dm = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);
    int width = dm.widthPixels;
    int height = dm.heightPixels;
    int orientation;
    // if the device's natural orientation is portrait:
    if ((rotation == Surface.ROTATION_0
            || rotation == Surface.ROTATION_180) && height > width ||
        (rotation == Surface.ROTATION_90
            || rotation == Surface.ROTATION_270) && width > height) {
        switch(rotation) {
            case Surface.ROTATION_0:
                orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
                break;
            case Surface.ROTATION_90:
                orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
                break;
            case Surface.ROTATION_180:
                orientation =
                    ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
                break;
            case Surface.ROTATION_270:
                orientation =
                    ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
                break;
            default:
                Log.e(TAG, "Unknown screen orientation. Defaulting to " +
                        "portrait.");
                orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
                break;              
        }
    }
    // if the device's natural orientation is landscape or if the device
    // is square:
    else {
        switch(rotation) {
            case Surface.ROTATION_0:
                orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
                break;
            case Surface.ROTATION_90:
                orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
                break;
            case Surface.ROTATION_180:
                orientation =
                    ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
                break;
            case Surface.ROTATION_270:
                orientation =
                    ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
                break;
            default:
                Log.e(TAG, "Unknown screen orientation. Defaulting to " +
                        "landscape.");
                orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
                break;              
        }
    }

    return orientation;
}

注意:一些用户(在评论中是Geltrude和holtaf)指出,该解决方案在所有设备上都不起作用,因为从自然方向的旋转方向不是标准化的。


5
如果您的活动具有固定的屏幕方向,则此方法将失败。只有在屏幕方向未锁定时,getRotation 才会报告一个值。 - Johann
2
很好,但如果您锁定了屏幕方向,那么您很可能知道它是锁定为横向还是纵向 - 因此您不需要这段代码来解决它。 - Zoltán
1
@Geltrude 它是怎么失败的?你能详细说明一下吗? - Zoltán
9
当你需要确定从相机意图捕获的图像旋转方向时,这就非常好用了...安卓糟糕。 - daniel.gindi
我正在使用这段代码在后台设置录制视频的方向元数据。如果屏幕被锁定,它总是返回默认方向显示而不是当前方向。 - Bruno Siqueira
显示剩余4条评论

20

简单的方法是使用

getResources().getConfiguration().orientation

1 代表竖屏,2 代表横屏。


5
这个问题要求提供更详细的信息,即包括反向肖像和反向风景模式,而这些功能并未提供。 - Zoltán

16
public static int getScreenOrientation(Activity activity) {
        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
        int orientation = activity.getResources().getConfiguration().orientation;
        if (orientation == Configuration.ORIENTATION_PORTRAIT) {
          if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270) {
            return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
          } else {
            return ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
          }
        }
        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
          if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) {
            return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
          } else {
            return ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
          }
        }
        return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
      }

由于此方法依赖于设备的自然方向,因此它在每个设备上的表现可能与预期不同。 - Şafak Gezer

8
我认为你的问题在于,你可以检测横屏和竖屏,但是无法检测反向横屏和反向竖屏,因为它们不受旧版本的支持。要检测你可以做的是同时使用方向和旋转。我给你一个想法,它可能对你有用。
尝试这个,我认为它可能解决你的问题。
            int orientation = getResources().getConfiguration().orientation;
            int rotation = getWindowManager().getDefaultDisplay().getRotation();
            int actual_orientation = -1;
            if (orientation == Configuration.ORIENTATION_LANDSCAPE
            &&  (rotation == Surface.ROTATION_0 
            ||  rotation == Surface.ROTATION_90)){
                orientation = Configuration.ORIENTATION_LANDSCAPE;
            } else if (orientation == Configuration.ORIENTATION_PORTRAIT
                  &&  (rotation == Surface.ROTATION_0 
                   ||  rotation == Surface.ROTATION_90)) {
                orientation = Configuration.ORIENTATION_PORTRAIT;
            } else if (orientation == Configuration.ORIENTATION_LANDSCAPE
                  &&  (rotation == Surface.ROTATION_180 
                   ||  rotation == Surface.ROTATION_270)){
                orientation = //any constant for reverse landscape orientation;
            } else {
                if (orientation == Configuration.ORIENTATION_PORTRAIT
                        &&  (rotation == Surface.ROTATION_180 
                         ||  rotation == Surface.ROTATION_270)){
                      orientation = //any constant for reverse portrait orientation;
                }
            }

是的,最终我采用了类似的解决方案。我将其发布为答案。 - Zoltán

7

getResources().getConfiguration().orientation是了解当前屏幕方向的标准方法。但如果这不能满足您的需求,也许您可以使用传感器来计算角度。阅读这篇文章这篇文章了解更多信息。


是的,我知道。我只是想知道是否有一种单一的方法可以返回关于屏幕方向的完整信息,包括它所转向的方向(不仅仅是横向或纵向),即倒置、左侧或右侧。 - Zoltán
是的,我明白你的意思。所以你可以通过使用这些传感器来创建自己的单个静态方法... - waqaslam

2

我最终采用了Zoltán上面的答案,这个方法非常好用,但是当我在平板电脑(三星P6210 Galaxy Tab 7.0 Plus)上尝试时出现了问题。在竖屏模式下,它返回SCREEN_ORIENTATION_REVERSE_PORTRAIT。因此,在else语句中(如果自然方向为横屏),我交换了ROTATION_90和ROTATION_270的情况,一切似乎都正常工作。(我没有足够的声望将此作为对Zoltán回答的评论发布。)


你知道其他横屏平板电脑上是否也会出现这种情况吗?也许所有自然横屏设备的这两种情况应该互换一下? - Zoltán
确认,在华硕Transformer Prime上也发生了这种情况,交换外壳可以解决问题。 - tru7

0
你可以用非常简单的方式实现: 获取屏幕widhtheight。 当设备处于横向方向时,屏幕宽度始终会更高。
Display display = getWindowManager().getDefaultDisplay();
    int width = display.getWidth(); 
    int height = display.getHeight();
    Toast.makeText(getApplicationContext(), "" + width + "," + height,
            Toast.LENGTH_SHORT).show();
    if (width > height) {
        Toast.makeText(getApplicationContext(), "LandScape",
                Toast.LENGTH_SHORT).show();
    }

3
问题实际上是如何获得详细的方向信息,包括设备的朝向。您提出的方法没有区分不同的方向,例如纵向和倒置的纵向等。 - Zoltán

-1

这个解决了你的问题吗?

public static int getscrOrientation(Activity act)
{
    Display getOrient = act.getWindowManager()
            .getDefaultDisplay();

    int orientation = getOrient.getOrientation();

    // Sometimes you may get undefined orientation Value is 0
    // simple logic solves the problem compare the screen
    // X,Y Co-ordinates and determine the Orientation in such cases
    if (orientation == Configuration.ORIENTATION_UNDEFINED) {

        Configuration config = act.getResources().getConfiguration();
        orientation = config.orientation;

        if (orientation == Configuration.ORIENTATION_UNDEFINED) {
            // if height and widht of screen are equal then
            // it is square orientation
            if (getOrient.getWidth() == getOrient.getHeight()) {
                orientation = Configuration.ORIENTATION_SQUARE;
            } else { // if widht is less than height than it is portrait
                if (getOrient.getWidth() < getOrient.getHeight()) {
                    orientation = Configuration.ORIENTATION_PORTRAIT;
                } else { // if it is not any of the above it will defineitly
                            // be landscape
                    orientation = Configuration.ORIENTATION_LANDSCAPE;
                }
            }
        }
    }
    return orientation; // return value 1 is portrait and 2 is Landscape
                        // Mode
}

1
像我在问题中提到的那样,我需要知道屏幕的朝向。肖像或风景模式是不足够的信息。例如,如果它是一台高大或竖直设备,并且处于横向方向,则我需要知道它是否向左或向右翻转等信息。 - Zoltán

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接