【问题标题】:how to get android screen size programmatically, once and for all?如何一劳永逸地以编程方式获取android屏幕尺寸?
【发布时间】:2013-07-03 02:40:47
【问题描述】:

如何以编程方式找出我的屏幕尺寸, 在触摸事件使用的单位中 和查看测量/布局? 换句话说,我想要坐标 屏幕右下角的, 在触摸事件使用的坐标系中' getRawX()/getRawY()View.getLocationOnScreen()

我不愿将所需的事件/视图单位称为“像素” 因为显然有几个“像素”的概念 在我的手机上以各种模式, 而且它们并没有形成一个一致的故事。

我看到这个问题已经被问过很多次了 在stackoverflow和其他地方, 但没有的答案实际上在我的手机上有效 (droid 4, android 4.1.2) 在所有模式下:

(哇!)

这适用于需要工作的库代码 无论应用是否处于“屏幕兼容模式” (即清单中的 targetSdkVersion


以下是事实:

  1. 我的手机(运行 android 4.1.2 的 droid 4) 具有 540x960 物理像素, 即小彩色发光点。

  2. 以所需单位显示的屏幕尺寸, 通过查看触摸事件和查看测量,是 360x640 当应用处于屏幕兼容模式时, 当应用程序未处于屏幕兼容模式时为 540x960。 这些是我需要以编程方式找到的数字, 无需使用触摸事件或视图来查找它们, 但我很难找到任何 API 这将返回这些数字。

  3. 已获得 Display 和 DisplayMetrics 对象 以各种方式都声称屏幕尺寸 是 540x960“像素” (无论是否在屏幕兼容模式下)。 具体来说,以下都是 540x960: DisplayMetrics.{width,height}像素, 显示.getSize(), Display.getRealSize(), Display.get{Width,Height}(),

  4. 通过各种方式获得的配置对象 都说屏幕{Width,Height}Dp = 360x614 (无论是否在屏幕兼容模式下)。 我不相信那代表整个屏幕, 因为纵横比是错误的。 (我认为是整个屏幕 减去状态栏;我需要整个屏幕。) 我认为可以肯定地说整个屏幕是 360x640 dp, 虽然我不知道任何返回 640 的 API。

  5. DisplayMetrics 以各种方式获得 说“密度”是 1.0f 在屏幕兼容模式下, 不处于屏幕兼容模式时为 1.5f。

  6. 活动的 getWindow().getAttributes().{width,height} 没有帮助,因为它通常包含 MATCH_PARENT 而不是实际尺寸。 但我显然可以从活动中得到想要的答案 getWindow().getDecorView().getMeasured{Width,Height}() (这实际上令人惊讶,因为 活动窗口的 decorView 看起来不像是占据了整个屏幕; 看起来它正在占用屏幕减去状态栏)。 但我不想依赖这个,因为如果窗口被调整大小 (出现软键盘?有人调用 window.setAttributes()? 或者我可能根本不在活动中), 这显然是错误的。

我了解以下公式应该成立: 像素 = dp * 密度 这似乎与所有报告的数字一致(上面的(3),(4),(5)) 当 not 处于屏幕兼容模式时: 540x960 = 360x640 * 1.5 但在屏幕兼容模式下,它不会加起来: 540x960 != 360x640 * 1 所以,有些不对劲。

我认为最简单的解释是, 就是上面(3)中列出的方法 只是在“像素”时给出错误的答案 在屏幕兼容模式下——也就是说,它们是有意的 返回 360x640“像素”,但他们错误地返回 540x960。 但可能还有其他方式来看待它。

在任何情况下,无论模式如何,都能获得所需的数字, 从上面的拼图来看,肯定是一个棘手的难题。 我找到了一种似乎在两种模式下都可以在手机上使用的方法, 但它非常迂回, 它依赖于两个看起来仍然相当不稳定的假设 (如下面的代码 cmets 所述)。

这是我的食谱:

/** get screen size in "pixels", i.e. touchevent/view units.
* on my droid 4, this is 360x640 or 540x960
* depending on whether the app is in screen compatibility mode
* (i.e. targetSdkVersion<=10 in the manifest) or not. */
public void getScreenSizePixels(int widthHeightInPixels[/*2*/])
{
    Resources resources = getResources();
    Configuration config = resources.getConfiguration();
    DisplayMetrics dm = resources.getDisplayMetrics();
    // Note, screenHeightDp isn't reliable
    // (it seems to be too small by the height of the status bar),
    // but we assume screenWidthDp is reliable.
    // Note also, dm.widthPixels,dm.heightPixels aren't reliably pixels
    // (they get confused when in screen compatibility mode, it seems),
    // but we assume their ratio is correct.
    double screenWidthInPixels = (double)config.screenWidthDp * dm.density;
    double screenHeightInPixels = screenWidthInPixels * dm.heightPixels / dm.widthPixels;
    widthHeightInPixels[0] = (int)(screenWidthInPixels + .5);
    widthHeightInPixels[1] = (int)(screenHeightInPixels + .5);
}

有没有更好/更清洁的方法 找到屏幕的大小??

【问题讨论】:

  • +1 很好的问题,并且展示了很多研究工作。
  • @Don 在docs 中,解释说兼容模式​​将停止对旧设置进行“缩放以适应”操作。但是,根据您的观察,没有清楚地解释“它是如何工作的”,我认为它们只是关闭了密度缩放,即:1px 变为 1dp。可能这种变化只发生在渲染部分,DisplayMetrics 永远不会更新这种变化。有类似this 的问题已经提交。
  • @user117 - 有趣。好吧,DisplayMetrics 的 部分 至少得到了更新——密度更改为 1.0。但是 widthPixels/heightPixels 似乎并没有被更改为匹配。关于引用的问题,看起来行为恢复到 3.1 行为(即我看到 heightPixels include 状态栏......但似乎单位错误)
  • @DonHatch 谢谢,好心——我实际上是想赞扬一个深思熟虑的问题,奇怪的是在 StackExchange 上不那么受欢迎——请注意这个问题不仅仅是“真实”的问题答案,讲的是听众对该主题的知识的(低)质量。现在,我可能会因为自己的问题因“不真实”而被一个接一个地关闭而受到创伤,幽默感可能让我失望,但它开始看起来像是有“好”答案的问题真的是这一切都在这里发生了什么......当然,我赞成你的:)
  • 顺便说一句!这是我怀疑的内容:@ 987654336@(尤其是参见他的(1)点,即快速制作的答案——实际上就是这个Q的情况!)。无论如何,快乐的纽约(我的在 11 分钟内到来)! :)

标签: android


【解决方案1】:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;

现在您可以以像素为单位测量屏幕尺寸,这是比厘米更好的测量单位,因为所有按钮、文本视图等都是以该单位测量的。我平时用的那个

【讨论】:

  • 根据Op(特别是第3点),这在屏幕兼容模式下不会不正确吗?
【解决方案2】:

通过使用 DisplayMetrics,您可以获得任何设备屏幕的高度和宽度。请注意,宽度和高度对旋转很敏感。 这是代码。

DisplayMetrics metrics; 
int width = 0, height = 0;

在你的 onCreate 方法中

 metrics = new DisplayMetrics();        
 getWindowManager().getDefaultDisplay().getMetrics(metrics);

 height = Math.min(metrics.widthPixels, metrics.heightPixels); //height
 width = Math.max(metrics.widthPixels, metrics.heightPixels); //width

试试这个。

【讨论】:

  • 不,正如我在 (3) 中所说,指标。{width,height}Pixels 在屏幕兼容模式下给出正确答案。
  • 我还发现:似乎 lite metrics.heightPixels 可能会在屏幕旋转的情况下给出宽度,反之亦然!
【解决方案3】:

在您的 #6 中,您注意到 DecorView 似乎提供了您想要的东西,但您认为它不可靠。我相信这是尽可能接近的。根据Window.getDecorView的文档:

检索顶层窗口装饰视图(包含标准窗口框架/装饰和其中的客户端内容),可以将其作为窗口添加到窗口管理器。

状态栏是那里提到的窗口装饰的一部分。软件键盘和其他覆盖将接收自己的窗口,因此它们不应干扰相关值。正确的不是精确的显示指标,但如果您的应用程序是全屏的,它应该始终是通过兼容性转换器过滤的全屏尺寸。其他应用程序无法访问您的应用程序的Window,因此无需担心其他应用程序会在您不查看时更改属性。

希望对您有所帮助。

【讨论】:

    【解决方案4】:

    我应该将此作为评论,但我没有代表。
    这可能不是一个完全正确的答案,但是当我在 DisplayMetrics 方法中切换高度和宽度时,我得到了我的尺寸。

        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);   
        width = metrics.heightPixels;
        height = metrics.widthPixels;
    

    正如我所说,这可能不正确,但我不知道为什么,但它对我有用。

    【讨论】:

    • 我相信这是因为你的屏幕已经旋转了。
    • 不相信我。
    【解决方案5】:

    如果您使用 17 级或更高级别的 API,请查看 Display 中的 getRealMetrics 和 getRealSize

    对于 api 级别 14,15 和 16,请查看 here

    【讨论】:

      【解决方案6】:

      我已经使用毕达哥拉斯定理找到了 Android 手机/平板电脑屏幕的对角线尺寸,同样的原理可以应用于 iPhone 或 Blackberry 屏幕。

      DisplayMetrics met = new DisplayMetrics();                
      this.getWindowManager().getDefaultDisplay().getMetrics(met);// get display metrics object
      String strSize = 
      new DecimalFormat("##.##").format(Math.sqrt(((met.widthPixels / met.xdpi) *
      (met.widthPixels / met.xdpi)) +
      ((met.heightPixels / met.ydpi) * (met.heightPixels / met.ydpi))));
      // using Dots per inches with width and height
      

      毕达哥拉斯一定是个天才,他多年前就知道智能手机编程:p

      【讨论】:

        【解决方案7】:

        我使用下面的方法来获取设备的宽度:

        public static int getDeviceWidth(Context context){
            WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            Display display = wm.getDefaultDisplay();
            int width=display.getWidth();
            return width;
        }
        

        【讨论】:

        • 此方法已弃用。请使用 displaymetrics 方法。
        【解决方案8】:

        我认为这个功能将帮助您简单地获取您的 android 屏幕尺寸的宽度和高度。该函数将宽度和高度作为整数数组返回,如下所示

        private int[] getScreenSIze(){
                DisplayMetrics displaymetrics = new DisplayMetrics();
                getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
                int h = displaymetrics.heightPixels;
                int w = displaymetrics.widthPixels;
        
                int[] size={w,h};
                return size;
        
            }
        

        并在您的创建方法上输出您的宽度和高度,如下所示

         int[] screenSize= getScreenSIze();
                int width=screenSize[0];
                int height=screenSize[1];
                screenSizes.setText("Phone Screen sizes \n\n  width = "+width+" \n Height = "+height);
        

        Download source code 并在您的 android studio 上进行测试

        【讨论】:

          【解决方案9】:

          这对我有用:

          int width = Resources.getSystem().getDisplayMetrics().widthPixels;

          int height = Resources.getSystem().getDisplayMetrics().heightPixels;

          我用它在水平回收器视图中更新我的项目的宽度。(根据我的要求) 希望它可以帮助某人!

          【讨论】:

            【解决方案10】:

            对于 Kotlin 中的这个解决方案,试试这个:

            private fun yourFunction(){
               val metrics = DisplayMetrics()
               windowManager.defaultDisplay.getMetrics(metrics)
               val width = metrics.widthPixels
               val height = metrics.heightPixels
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-01-06
              • 2012-01-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多