有没有一种方法可以确定安卓手机屏幕的物理高度(以厘米或英寸为单位)?

55

我需要知道设备屏幕的实际长度单位以便计算每毫秒像素下的重力加速度大小。

在 Android API 中是否有相应的方法可供使用?


1
如果你想要进行一次性转换(例如从Photoshop导出雪碧图或为物理尺寸设计布局),这里有一个不错的转换工具:http://pixplicity.com/dp-px-converter/。 - Paul Lammertsma
8个回答

93

使用以下代码:

    DisplayMetrics dm = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);
    double x = Math.pow(mWidthPixels/dm.xdpi,2);
    double y = Math.pow(mHeightPixels/dm.ydpi,2);
    double screenInches = Math.sqrt(x+y);
    Log.d("debug","Screen inches : " + screenInches);

当从下面的代码中获取mWidthPixels和mHeightPixels时

private void setRealDeviceSizeInPixels()
{
    WindowManager windowManager = getWindowManager();
    Display display = windowManager.getDefaultDisplay();
    DisplayMetrics displayMetrics = new DisplayMetrics();
    display.getMetrics(displayMetrics);


    // since SDK_INT = 1;
    mWidthPixels = displayMetrics.widthPixels;
    mHeightPixels = displayMetrics.heightPixels;

    // includes window decorations (statusbar bar/menu bar)
    if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 17)
    {
        try
        {
            mWidthPixels = (Integer) Display.class.getMethod("getRawWidth").invoke(display);
            mHeightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
        }
        catch (Exception ignored)
        {
        }
    }

    // includes window decorations (statusbar bar/menu bar)
    if (Build.VERSION.SDK_INT >= 17)
    {
        try
        {
            Point realSize = new Point();
            Display.class.getMethod("getRealSize", Point.class).invoke(display, realSize);
            mWidthPixels = realSize.x;
            mHeightPixels = realSize.y;
        }
        catch (Exception ignored)
        {
        }
    }

请查看以下帖子以获取参考信息: 获取像素屏幕尺寸


10
我有大约15个测试设备,但有些设备无法正常运行,例如在摩托罗拉Milestone或中兴手机等某些型号上无法正常工作。 - STeN
7
返回的值并不精确,因为getMetrics(以及display.getWidth()display.getHeight())返回的值仅限于您的应用程序可以访问的值(例如,它不包含操作栏的高度)。 因此,在1280x800屏幕上,您可能会得到值1260x800或1280x780等。 - Dmitry Zaytsev
3
正如STeN所提到的,该计算对于某些设备是不正确的。例如,这段代码报告Droid Bionic的屏幕为3英寸,而实际上它有4.3英寸的屏幕。在Bionic上,xdpi和ydpi的返回值分别为368、365,可能是由于PenTile显示或摩托罗拉的混淆造成的。这个设备的实际DPI是sqrt(960^2+540^2)/4.3=~256dpi。 - Yojimbo
2
因此,对于Droid Bionic和其他一些设备,如果使用DisplayMetrics.densityDpi返回的近似DPI而不是使用xdpi / ydpi,则可以获得更准确的屏幕大小。 - Yojimbo
2
我的三星Galaxy Ace S5830I显示屏幕尺寸为15英寸 - 显然这不是真实情况! - slott
显示剩余7条评论

9

为了获取当前的大小,请在末尾使用Math.round。

 DisplayMetrics dm = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);
    double x = Math.pow(dm.widthPixels/dm.xdpi,2);
    double y = Math.pow(dm.heightPixels/dm.ydpi,2);
    double screenInches = Math.sqrt(x+y);
    Log.d("debug","Screen inches : " + screenInches);

screenInches=  (double)Math.round(screenInches * 10) / 10;

你刚刚是不是只是复制了Bghaak的解决方案,只是在最后一句话上做了一个表面的改变? - undefined

4
以下代码片段将帮助您获取屏幕尺寸(英寸):
public static double getScreenSizeInches(Activity activity){
    WindowManager windowManager = activity.getWindowManager();
    Display display = windowManager.getDefaultDisplay();
    DisplayMetrics displayMetrics = new DisplayMetrics();
    display.getMetrics(displayMetrics);

    // since SDK_INT = 1;
    int mWidthPixels = displayMetrics.widthPixels;
    int mHeightPixels = displayMetrics.heightPixels;

    // includes window decorations (statusbar bar/menu bar)
    if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 17) {
        try{
            mWidthPixels = (Integer) Display.class.getMethod("getRawWidth").invoke(display);
            mHeightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
        } catch (Exception ignored) {}
    }

    // includes window decorations (statusbar bar/menu bar)
    if (Build.VERSION.SDK_INT >= 17) {
        try {
            Point realSize = new Point();
            Display.class.getMethod("getRealSize", Point.class).invoke(display, realSize);
            mWidthPixels = realSize.x;
            mHeightPixels = realSize.y;
        } catch (Exception ignored) {}
    }

    DisplayMetrics dm = new DisplayMetrics();
    activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
    double x = Math.pow(mWidthPixels / dm.xdpi, 2);
    double y = Math.pow(mHeightPixels / dm.ydpi, 2);
    return Math.sqrt(x + y);
}

希望这能帮到您。

给出了错误的结果。我有模拟器屏幕4'65,结果是4'59。虽然比其他解决方案好,但它们都给了我4'3。 - Desolator

4

4
你好,一些模型返回错误的xdpi和ydpi值,请参阅我的评论。 - STeN

1
我尝试了其他答案中提到的大多数方法,但这些方法在特定设备上失败。因此,这是我对解决此问题做出的一点贡献。代码是用Kotlin编写的。
获取DisplayMetrics对象:
    val manager = mContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager
    val displayMetrics = DisplayMetrics()
    manager.getDefaultDisplay().getMetrics(displayMetrics)

计算屏幕的英寸宽度如下:
    val widthInDotPoints : Double = (displayMetrics.widthPixels * (160 * 1.0 /displayMetrics.densityDpi))
    val widthInInches : Double = width / displayMetrics.xdpi

在这里,我使用widthPixels计算了设备的宽度(以dp为单位),然后将其转换为英寸宽度。我使用160即DisplayMetrics.DENSITY_MEDIUM作为转换因子,将widthPixels转换为widthInDotPoints。

同样地,计算屏幕高度(以英寸为单位):

    val heightInDotPoints : Double = (displayMetrics.heightPixels * (160 * 1.0 /displayMetrics.densityDpi))
    val heightInInches : Double = height / displayMetrics.ydpi

0

我用这个来获取真实大小

final DisplayMetrics metrics = new DisplayMetrics();
final WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    windowManager.getDefaultDisplay().getRealMetrics(metrics);
}
else {
    windowManager.getDefaultDisplay().getMetrics(metrics);
}
int realHeight = metrics.heightPixels; // This is real height
int realWidth = metrics.widthPixels; // This is real width

0
有些设备像素返回的xdpi和ydpi不正确。 所以你可以根据密度来计算。
fun getScreenSizeInInches(context: Context): Float {
    try {
        val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val display = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            context.display
        } else {
            windowManager.defaultDisplay
        }

        val metrics = DisplayMetrics()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            display?.getRealMetrics(metrics)
        } else {
            display?.getMetrics(metrics)
        }
        // Calculate the diagonal size in inches using Pythagorean theorem
        var xdpi = metrics.xdpi
        if (xdpi < 160) {
            xdpi = getDPIFromDensity(metrics.density)
        }
        var ydpi = metrics.ydpi
        if (ydpi < 160) {
            ydpi = getDPIFromDensity(metrics.density)
        }
        val widthInInches = metrics.widthPixels / xdpi
        val heightInInches = metrics.heightPixels / ydpi
        val diagonalInInches = sqrt(widthInInches.pow(2) + heightInInches.pow(2))
        Log.d("diagonalInInches", metrics.toString() + "\n" + diagonalInInches.toString())
        return diagonalInInches
    } catch (e: Exception) {
        return 6.0f
    }
}

/*
* Some device pixel return xdpi, ydpi not correct.
* */
private fun getDPIFromDensity(density: Float): Float {
    val dpi = 160 * density
    Log.d("getDPIFromDensity", dpi.toString())
    return dpi
}

-4

您需要使用屏幕密度来进行计算。

Context.getResources().getDisplayMetrics().density

根据文件说明:

显示的逻辑密度。这是Density Independent Pixel(DIP)单位的比例因子,其中一个DIP是大约160dpi屏幕上的一个像素(例如240x320,1.5英寸x2英寸的屏幕),提供系统显示的基线。因此,在160dpi屏幕上,此密度值将为1;在120 dpi屏幕上,它将为0.75;等等。

此值不完全遵循实际屏幕大小(由xdpi和ydpi给出),而是用于根据显示dpi的总体变化步骤来缩放整个UI的大小。例如,240x320屏幕的密度为1,即使其宽度为1.8英寸、1.3英寸等。但是,如果屏幕分辨率增加到320x480,但屏幕大小仍为1.5英寸x2英寸,则密度将增加(可能增加到1.5)。


2
请按照其他帖子中的描述使用xdpi和ydpi。密度故意不是对物理屏幕尺寸的绝对映射,而是一种更抽象的单位,可以量化为少量离散值(目前为120dpi、160dpi、240dpi)。 - hackbod
这是一种糟糕的方法,会导致dpi和分辨率的值都不准确。 - grebulon

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