如何一劳永逸地以编程方式获取android屏幕尺寸?

Posted

技术标签:

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

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

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

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

Can I find out width of screen programmatically in android app? How do I get the ScreenSize programmatically in android Android set View visibility programmatically based on screen size How do I get the height of the screen in Android? Get the screen height in Android https://groups.google.com/forum/#!topic/android-developers/IpxnfvDFrpc http://shuklaxyz.blogspot.com/2012/02/how-to-programmatically-figure-out.html http://coderock.net/how-to-determine-screen-resolution-programmatically/ http://www.codeproject.com/Tips/313848/Get-actual-screen-size-for-the-application-layout Android and setting width and height programmatically in dp units http://www.simplecodestuffs.com/how-to-get-screen-dimensions-programmatically-in-android/ http://www.androidsnippets.com/get-size-and-orientation-of-the-screen http://grokbase.com/t/gg/android-developers/127aatfqb6/how-to-determine-screen-resolution-programmatically

(哇!)

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


以下是事实:

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

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

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

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

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

    活动的 getWindow().getAttributes().width,height 没有帮助,因为它通常包含 MATCH_PARENT 而不是实际尺寸。 但我显然可以从活动中得到想要的答案 getWindow().getDecorView().getMeasuredWidth,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 分钟内到来)! :) 【参考方案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,heightPixels 在屏幕兼容模式下给出正确答案。 我还发现:似乎 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

【讨论】:

以上是关于如何一劳永逸地以编程方式获取android屏幕尺寸?的主要内容,如果未能解决你的问题,请参考以下文章

在android中以编程方式获取屏幕密度?

如何获取直到标签栏底部的屏幕尺寸

获取 iPhone 的物理屏幕尺寸(以英寸为单位)

android 获取屏幕高度和宽度 的方法

您如何以编程方式在 Android ICS 及更高版本上截取屏幕截图?

如何以编程方式获取用户在 Android OS 配置上设置的数据使用限制?