【问题标题】:Android DisplayMetrics returns incorrect screen size in pixels on ICSAndroid DisplayMetrics 在 ICS 上返回错误的屏幕尺寸(以像素为单位)
【发布时间】:2012-06-12 05:54:26
【问题描述】:

我试过这个......

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int fullscreenheight = metrics.heightPixels;
int fullscreenwidth = metrics.widthPixels;

和....

Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;

Gnex 的显示屏为 720×1280。返回的宽度/高度结​​果(当然取决于方向)永远不是 1280。我认为这可能与 Ice Cream Sandwich 中的屏幕导航栏有关,所以我将其隐藏:

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);

...然后启动一个线程,该线程连续记录屏幕尺寸高度/宽度。即使在 ICS 导航栏完全消失之后....屏幕尺寸也永远不会报告 1280 的值。我会得到这样的数字:

width  = 720
height = 1184

如何在 ICS 中获得真正的设备屏幕分辨率?

我需要这个值的原因是因为我的应用播放视频,并且我希望视频在设备处于横向时占据整个屏幕。现在我知道你在想什么,为什么不给视频视图一个高度/宽度的“match_parent”值呢?原因是我的视频有多种纵横比,我希望能够根据屏幕的整个宽度计算出正确的视频尺寸。

【问题讨论】:

    标签: android android-layout android-screen android-resolution


    【解决方案1】:

    根据 Ahmed 的回答,这是没有错误的完整代码:

        int width = 0, height = 0;
        final DisplayMetrics metrics = new DisplayMetrics();
        Display display = getWindowManager().getDefaultDisplay();
        Method mGetRawH = null, mGetRawW = null;
    
        try {
            // For JellyBean 4.2 (API 17) and onward
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
                display.getRealMetrics(metrics);
    
                width = metrics.widthPixels;
                height = metrics.heightPixels;
            } else {
                mGetRawH = Display.class.getMethod("getRawHeight");
                mGetRawW = Display.class.getMethod("getRawWidth");
    
                try {
                    width = (Integer) mGetRawW.invoke(display);
                    height = (Integer) mGetRawH.invoke(display);
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        } catch (NoSuchMethodException e3) {  
            e3.printStackTrace();
        }
    

    【讨论】:

      【解决方案2】:

      我只为 ICS 找到了这个隐藏的宝藏......如果您的目标 API 高于 ICS,请参阅下面 Chris Schmich 的评论。

      How to hide and display the navigation bar on Android ICS build

      如果链接失效....这里是获取实际设备屏幕尺寸的方法.....

      Display display = getWindowManager().getDefaultDisplay();     
      Method mGetRawH = Display.class.getMethod("getRawHeight");
      Method mGetRawW = Display.class.getMethod("getRawWidth");
      int rawWidth = (Integer) mGetRawW.invoke(display);
      int rawHeight = (Integer) mGetRawH.invoke(display);
      

      编辑(2012 年 11 月 19 日)

      上面的代码在 Android 4.2 上将不起作用,并且会引发异常....我还没有找到在 Android 4.2 中获取设备全屏尺寸的方法。当我这样做时,我会编辑这个答案,但现在,你应该为 android 4.2 编写应急代码!!

      【讨论】:

      • - 为什么 Google 非得让我去生?
      • 非常感谢,省了很多麻烦
      • 在 Android 4.2 (API 17) 及更高版本上,您可以使用 Display.getRealMetrics 获取实际的物理显示指标。我确认这适用于我的带有 Jelly Bean (4.2.1) 的三星 Galaxy Nexus。见developer.android.com/reference/android/view/…
      • 另请注意,getRawHeight 和 getRawWidth 仅在 API 14 之后可用。因此我们只能将它们用于 API 14、15 和 16。
      • 我在另一个问题上 written an answer 使用此选项和其他选项在 api 10+ 上获得最佳显示指标。
      【解决方案3】:

      您可以使用getRealSize 获取屏幕分辨率。 API 17 及更高版本正式支持它,但它实际上存在于 API 14 之后的 SDK 中。如果您使用 API 17 或更高版本的 SDK 平台,您可以正常访问该方法,只需绕过关于它仅在 API 中可用的警告17.

      /**
       * Gets the device's native screen resolution rotated
       * based on the device's current screen orientation.
       */
      @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) //To remove warning about using
                                                     //getRealSize prior to API 17
      private Point screenResolution() {
          WindowManager windowManager =
              (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
          Display display = windowManager.getDefaultDisplay();
          Point screenResolution = new Point();
      
          if (Build.VERSION.SDK_INT < 14)
              throw new RuntimeException("Unsupported Android version.");
          display.getRealSize(screenResolution);
      
          return screenResolution;    
      }
      

      我已经在真正的 Android 5.0.2 设备和运行 4.1.1(可能还有其他)的模拟器中对此进行了测试。

      感谢benc pointing this out in the comments

      【讨论】:

        【解决方案4】:

        试试这个

            final DisplayMetrics metrics = new DisplayMetrics(); 
            Display display = getWindowManager().getDefaultDisplay();     
            Method mGetRawH = null,mGetRawW = null;
        
            try {
                            // For JellyBeans and onward
                if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN){
                    display.getRealMetrics(metrics);
        
                    realWidth = metrics.widthPixels;
                    realHeight = metrics.heightPixels;
                }else{
                    mGetRawH = Display.class.getMethod("getRawHeight");
                    mGetRawW = Display.class.getMethod("getRawWidth");
        
                    try {
                        realWidth = (Integer) mGetRawW.invoke(display);
                        realHeight = (Integer) mGetRawH.invoke(display);
                    } catch (IllegalArgumentException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
        

        【讨论】:

        • 到目前为止,在我有限的测试中,即使在 4.0 设备上,getRealMetrics() 也能给出正确的结果,您可能会认为它会崩溃。另外值得注意的是 getRealMetrics 返回正确的 DPI,而其他获取 DisplayMetrics 的方法可能返回虚假数据。 (用其他方法,我的S4自称是mpdi设备!)
        【解决方案5】:
        public static Point getRealSize(Display display) {
                Point outPoint = new Point();
                Method mGetRawH;
                try {
                    mGetRawH = Display.class.getMethod("getRawHeight");
                    Method mGetRawW = Display.class.getMethod("getRawWidth");
                    outPoint.x = (Integer) mGetRawW.invoke(display);
                    outPoint.y = (Integer) mGetRawH.invoke(display);
                    return outPoint;
                } catch (Throwable e) {
                    return null;
                }
            }
        
            public static Point getSize(Display display) {
                if (Build.VERSION.SDK_INT >= 17) {
                    Point outPoint = new Point();
                    DisplayMetrics metrics = new DisplayMetrics();
                    display.getRealMetrics(metrics);
                    outPoint.x = metrics.widthPixels;
                    outPoint.y = metrics.heightPixels;
                    return outPoint;
                }
                if (Build.VERSION.SDK_INT >= 14) {
                    Point outPoint = getRealSize(display);
                    if (outPoint != null)
                        return outPoint;
                }
                Point outPoint = new Point();
                if (Build.VERSION.SDK_INT >= 13) {
                    display.getSize(outPoint);
                } else {
                    outPoint.x = display.getWidth();
                    outPoint.y = display.getHeight();
                }
                return outPoint;
            }
        

        【讨论】:

          【解决方案6】:

          在某些设备上,例如平板电脑,导航栏根本无法隐藏(source,请参阅“系统 UI 可见性控制”部分),因为没有硬件按钮作为备份。如果在您的设备上您设法隐藏了该栏,您可以制作一个全屏视图并使用 getWidth() 和 getHeight() 请求其大小。

          据我所知,没有可靠的方法来获取所有 ICS 设备上的屏幕尺寸。

          【讨论】:

          • 必须有办法做到这一点。 ICS 的 youtube 应用程序以某种方式吹走了 ICS 导航栏并使视频视图成为整个屏幕的宽度。
          • 这取决于设备,在带有 ICS 的平板电脑上,该栏被涂黑(控件被隐藏),但并未消失。
          • Stuart,我无法确认您是否可以在运行 ICS 的平板电脑上彻底清除操作系统导航栏的屏幕,但即使您说的是真的......操作系统导航栏取决于设备......我不知道为什么 Google 会故意阻止开发人员获取设备的确切尺寸。那会有什么意义?顺便说一句....请不要将此视为对您的回答的攻击。感谢您的讨论!
          • 别担心,我也很欣赏这次讨论,我同意 Android 提供一种请求屏幕分辨率的方法是有意义的。我最近一直想自己使用这个功能,但是当我搜索如何做到这一点时,我找不到如何做。如果您希望验证导航栏不能在某些设备上隐藏,我已经添加了一个指向我的原始答案的链接。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-07-19
          • 2015-12-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-16
          相关资源
          最近更新 更多