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


516

如何在Android中以编程方式获取屏幕密度?

我的意思是:如何找到当前设备的屏幕dpi?


9
关于的回答很多getDisplayMetrics().xdpi,应该返回设备的真实dpi。请注意,制造商未在所有设备上正确设置此值,因此您不能使用它们。可悲但真实:关于真实dpi的信息不可用。来源:groups.google.com/d/msg/android-developers/g56jV0Hora0/...
sulai

2
getResources().getDisplayMetrics().xdpigetResources().getDisplayMetrics().ydpi会为您提供实际的水平和垂直密度,在大多数情况下它们是不同的。
Ωmega

Answers:


526

您可以从DisplayMetrics结构中获取显示信息:

DisplayMetrics metrics = getResources().getDisplayMetrics();

尽管Android不使用直接像素映射,但它使用了少数量化的“密度无关像素”值,然后缩放为实际屏幕尺寸。因此,metrics.densityDpi物业将是一个DENSITY_xxx常数(120160213240320480640DPI)。

如果您需要实际的 LCD像素密度(可能是OpenGL应用程序),则可以分别通过水平和垂直密度的metrics.xdpimetrics.ydpi属性来获得。

如果您定位的API级别早于4。该metrics.density属性是参考密度(160dpi)中的浮点缩放因子。现在metrics.densityDpi可以计算出相同的值

int densityDpi = (int)(metrics.density * 160f);

42
诚然这个帖子是从两年多前,但是这是在谷歌出现本次搜索的,所以任何人谁发现这个第一件事情,你不必再乘以160
roboguy12

5
从哪个版本开始不再?
TacB0sS 2013年

我已经更新了答案,以匹配人们可能正在使用的最新API版本。
joshperry

6
注意:您可能需要这个更新的API:getWindowManager().getDefaultDisplay().getRealMetrics(metrics); API 17中已正式添加了该API,但令我惊讶的是,即使在我尝试的4.0设备上,它也能正常工作。
benkc 2014年

2
还有getResources()。getDisplayMetrics()。densityDpi
amorenew

367

这也适用:

 getResources().getDisplayMetrics().density;

这将为您提供:

0.75-ldpi

1.0-mdpi

1.5-dpi

2.0-xhdpi

3.0-xxhdpi

4.0-xxxhdpi

在此处输入图片说明

参考:密度

在此处输入图片说明

参考2


10
+1当您没有直接访问权限时WindowManager(例如在Loader内部),此功能有效。只需用它乘160
米哈尔ķ

2
API级别16添加了xxdpi,在此处转换为3.0。
QED 2012年

3
这将给1.3312501 tvdpi。有关更多信息,tvdpi请参见此处
Dori

2
Nexus 7报1.3,为什么要插入括号?
尼尔

1
@selbie,您的电话可能正在提取和扩展更高质量的资源,因为您的电话报告了两个定义的密度之间的一半。
Sakiboy

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

switch(metrics.densityDpi) {
     case DisplayMetrics.DENSITY_LOW:
         break;

     case DisplayMetrics.DENSITY_MEDIUM:
         break;

     case DisplayMetrics.DENSITY_HIGH:
         break;
}

这将适用于API级别4和更高级别。


您如何处理Nexus 7这样的设备,其密度Dpi为213?
尼尔2014年

在密度值之间进行if-else手检查,例如if(metrics.densityDpi> DisplayMetrics.DENSITY_LOW && metrics.densityDpi <DisplayMetrics.DENSITY_MEDIUM)
Mitul Nakum 2014年

1
或if(metrics.densityDpi <DisplayMetrics.DENSITY_LOW){},否则if(metrics.densityDpi <DisplayMetrics。DENSITY_MEDIUM){} .....
Mitul Nakum 2014年

1
Neil,213被称为TV DPI,该DENSITY_TV有一个命名的显示指标密度。
Andrew S

63

Blundell作为静态帮助程序方法答案:

private static String getDensityName(Context context) {
    float density = context.getResources().getDisplayMetrics().density;
    if (density >= 4.0) {
        return "xxxhdpi";
    }
    if (density >= 3.0) {
        return "xxhdpi";
    }
    if (density >= 2.0) {
        return "xhdpi";
    }
    if (density >= 1.5) {
        return "hdpi";
    }
    if (density >= 1.0) {
        return "mdpi";
    }
    return "ldpi";
}

tvdpi密度呢?我猜是1.33
Anoop

@AnoopssGolden这不是真正的标准,因此您可以根据需要添加它,但是我认为答案不应该包含它。来自android docs:“这不视为“主要”密度组。它主要用于电视,大多数应用不需要它。”
qwertzguy 2014年

但是nexus 7设备属于tvdpi密度组。
Anoop

1
我知道这有点老了,不过是为了补充一下;MDPI可以在Nexus 7上适用于大多数情况,但是正如我现在所尝试的那样,由于MDPI导致的图像不足。我必须定义TVDPI,然后从服务器请求更大的图像大小。它可能不会被大量使用,但这并不意味着MDPI会处理所有事情。
RED_ 2014年

3
嘿@Andrew S,使用elses不会改变代码的效率,因为每个if都会立即返回。删除花括号只是样式问题,恕我直言,在维护代码时,它更容易出错。
qwertzguy

45

尝试这个:

DisplayMetrics dm = context.getResources().getDisplayMetrics();
int densityDpi = dm.densityDpi;

5
我更喜欢它,因为它依赖于上下文而不是活动。
greg7gkb 2012年

同意,我可以View轻松得多地使用它(这是我需要的!)
Andrew Wyld 2012年

37

要获得dpi:

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

// will either be DENSITY_LOW, DENSITY_MEDIUM or DENSITY_HIGH
int dpiClassification = dm.densityDpi;

// these will return the actual dpi horizontally and vertically
float xDpi = dm.xdpi;
float yDpi = dm.ydpi;

4
dm.densityDpi返回DENSITY_LOW或DENSITY_MEDIUM或DENSITY_HIGH。xhdpi呢?有DENSITY_XHIGH左右吗?
Eugene Chumak'4


34

这是密度常数,来源

在此处输入图片说明

除标准密度外,还有5种中间密度。考虑到这一事实,以下代码将是一个完整的工作示例:

float density = getResources().getDisplayMetrics().density;

if (density == 0.75f)
{
    // LDPI
}
else if (density >= 1.0f && density < 1.5f)
{
    // MDPI
}
else if (density == 1.5f)
{
    // HDPI
}
else if (density > 1.5f && density <= 2.0f)
{
    // XHDPI
}
else if (density > 2.0f && density <= 3.0f)
{
    // XXHDPI
}
else
{
    // XXXHDPI 
}

另外,您可以使用来找到密度常数densityDpi

int densityDpi = getResources().getDisplayMetrics().densityDpi;

switch (densityDpi)
{
    case DisplayMetrics.DENSITY_LOW:
        // LDPI
        break;

    case DisplayMetrics.DENSITY_MEDIUM:
        // MDPI
        break;

    case DisplayMetrics.DENSITY_TV:
    case DisplayMetrics.DENSITY_HIGH:
        // HDPI
        break;

    case DisplayMetrics.DENSITY_XHIGH:
    case DisplayMetrics.DENSITY_280:
        // XHDPI
        break;

    case DisplayMetrics.DENSITY_XXHIGH:
    case DisplayMetrics.DENSITY_360:
    case DisplayMetrics.DENSITY_400:
    case DisplayMetrics.DENSITY_420:
        // XXHDPI
        break;

    case DisplayMetrics.DENSITY_XXXHIGH:
    case DisplayMetrics.DENSITY_560:
        // XXXHDPI
        break;
}

29

以下答案是基于qwertzguy答案的一个小改进。

double density = getResources().getDisplayMetrics().density;
if (density >= 4.0) {
   //"xxxhdpi";
}
else if (density >= 3.0 && density < 4.0) {
   //xxhdpi
}
else if (density >= 2.0) {
   //xhdpi
}
else if (density >= 1.5 && density < 2.0) {
   //hdpi
}
else if (density >= 1.0 && density < 1.5) {
   //mdpi
}

1
该代码可以处理其他代码,并且在其后的&符和条件是多余的。
Andrew S

1
@Andrew,感谢您的纠正。我已经相应地编辑了答案。
2015年

2
@San在任何情况下都不需要&&,只要您始终检查> =,否则else if将在第一个为真的条件下终止。
dbenson

3
对于我的Nexus 5X(默认的Google设备顺便说一句),这不能为我返回正确的结果。设备密度为xxhdpi,返回的双密度约为2.6。
Tobliug

20

实际上,如果您想获得实际的显示dpi,则在查询显示指标时答案就介于两者之间:

DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int dpiClassification = dm.densityDpi;
float xDpi = dm.xdpi;
float yDpi = dm.ydpi;

densityDpi * 160将为您提供应使用的密度值/建议

0.75 - ldpi - 120 dpi
1.0 - mdpi - 160 dpi
1.5 - hdpi - 240 dpi
2.0 - xhdpi - 320 dpi
3.0 - xxhdpi - 480 dpi
4.0 - xxxhdpi - 640 dpi

如以前的帖子中所述

dm.xdpi不会始终为您提供给定显示的REAL dpi:示例:

Device: Sony ericsson xperia mini pro (SK17i)
Density: 1.0 (e.g. suggests you use 160dpi resources)
xdpi: 193.5238
Real device ppi is arround 193ppi


Device: samsung GT-I8160 (Samsung ace 2)
Density 1.5 (e.g. suggests you use 240dpi resources)
xdpi 160.42105
Real device ppi is arround 246ppi

因此,显示器的实际dpi应该是Density * xdpi ..但我不确定这是否是正确的方法!


1
到目前为止,在过去6个月中,到目前为止我在Google Play上的所有应用上均使用Density * xdpi完美运行
Marek Halmo

乘以密度* xdpi是不合逻辑的,因为密度更高的设备越来越多-密度和xdpi都增加了,所以这将变得更加清楚,因此将它们乘以将是对增加值的双重计算。我会说三星ace 2是供应商的错误。Android规范规定xdpi和ydpi是真正的像素密度-请勿相乘。
制造商

17

这应该有助于您的活动...

void printSecreenInfo(){

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

    Log.i(TAG, "density :" +  metrics.density);

    // density interms of dpi
    Log.i(TAG, "D density :" +  metrics.densityDpi);

    // horizontal pixel resolution
    Log.i(TAG, "width pix :" +  metrics.widthPixels);

     // actual horizontal dpi
    Log.i(TAG, "xdpi :" +  metrics.xdpi);

    // actual vertical dpi
    Log.i(TAG, "ydpi :" +  metrics.ydpi);

}

输出:

I/test( 1044): density :1.0

I/test( 1044): D density :160

I/test( 1044): width pix :800

I/test( 1044): xdpi :160.0

I/test( 1044): ydpi :160.42105

13
public static String getDensity(Context context) {
    String r;
    DisplayMetrics metrics = new DisplayMetrics();

    if (!(context instanceof Activity)) {
        r = "hdpi";
    } else {
        Activity activity = (Activity) context;
        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);

        if (metrics.densityDpi <= DisplayMetrics.DENSITY_LOW) {
            r = "ldpi";
        } else if (metrics.densityDpi <= DisplayMetrics.DENSITY_MEDIUM) {
            r = "mdpi";
        } else {
            r = "hdpi";
        }
    }

    return r;
}

11

如果要从服务中检索密度,则其工作方式如下:

WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);

当我没有windowManager时,这对我有所帮助
–silentsudo

8

您应该尝试一下。刚刚添加了一种方法,它将查找并显示吐司。设备属于哪个类别。

public static int differentDensityAndScreenSize(Context context) {
  int value = 20;
  String str = "";
  if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_SMALL) {
   switch (context.getResources().getDisplayMetrics().densityDpi) {
   case DisplayMetrics.DENSITY_LOW:
    str = "small-ldpi";
    value = 20;
    break;
   case DisplayMetrics.DENSITY_MEDIUM:
    str = "small-mdpi";
    value = 20;
    break;
   case DisplayMetrics.DENSITY_HIGH:
    str = "small-hdpi";
    value = 20;
    break;
   case DisplayMetrics.DENSITY_XHIGH:
    str = "small-xhdpi";
    value = 20;
    break;
   case DisplayMetrics.DENSITY_XXHIGH:
    str = "small-xxhdpi";
    value = 20;
    break;
   case DisplayMetrics.DENSITY_XXXHIGH:
    str = "small-xxxhdpi";
    value = 20;
    break;
   case DisplayMetrics.DENSITY_TV:
    str = "small-tvdpi";
    value = 20;
    break;
   default:
    str = "small-unknown";
    value = 20;
    break;
   }

  } else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_NORMAL) {
   switch (context.getResources().getDisplayMetrics().densityDpi) {
   case DisplayMetrics.DENSITY_LOW:
    str = "normal-ldpi";
    value = 82;
    break;
   case DisplayMetrics.DENSITY_MEDIUM:
    str = "normal-mdpi";
    value = 82;
    break;
   case DisplayMetrics.DENSITY_HIGH:
    str = "normal-hdpi";
    value = 82;
    break;
   case DisplayMetrics.DENSITY_XHIGH:
    str = "normal-xhdpi";
    value = 90;
    break;
   case DisplayMetrics.DENSITY_XXHIGH:
    str = "normal-xxhdpi";
    value = 96;
    break;
   case DisplayMetrics.DENSITY_XXXHIGH:
    str = "normal-xxxhdpi";
    value = 96;
    break;
   case DisplayMetrics.DENSITY_TV:
    str = "normal-tvdpi";
    value = 96;
    break;
   default:
    str = "normal-unknown";
    value = 82;
    break;
   }
  } else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) {
   switch (context.getResources().getDisplayMetrics().densityDpi) {
   case DisplayMetrics.DENSITY_LOW:
    str = "large-ldpi";
    value = 78;
    break;
   case DisplayMetrics.DENSITY_MEDIUM:
    str = "large-mdpi";
    value = 78;
    break;
   case DisplayMetrics.DENSITY_HIGH:
    str = "large-hdpi";
    value = 78;
    break;
   case DisplayMetrics.DENSITY_XHIGH:
    str = "large-xhdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_XXHIGH:
    str = "large-xxhdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_XXXHIGH:
    str = "large-xxxhdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_TV:
    str = "large-tvdpi";
    value = 125;
    break;
   default:
    str = "large-unknown";
    value = 78;
    break;
   }

  } else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE) {
   switch (context.getResources().getDisplayMetrics().densityDpi) {
   case DisplayMetrics.DENSITY_LOW:
    str = "xlarge-ldpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_MEDIUM:
    str = "xlarge-mdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_HIGH:
    str = "xlarge-hdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_XHIGH:
    str = "xlarge-xhdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_XXHIGH:
    str = "xlarge-xxhdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_XXXHIGH:
    str = "xlarge-xxxhdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_TV:
    str = "xlarge-tvdpi";
    value = 125;
    break;
   default:
    str = "xlarge-unknown";
    value = 125;
    break;
   }
  }
// The Toast will show the Device falls in Which Categories.
Toast.makeText(MainActivity.this, ""+str, Toast.LENGTH_SHORT).show();

  return value;
 }

http://www.androidwarriors.com/2016/01/how-to-find-different-devices-screen.html


7

这应该工作。

DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels; //320
int height = dm.heightPixels; //480

4
显示器的像素大小不是密度。
joshperry

1
这是与密度无关的像素,而不是像素。而且您看到的320是320dip而不是320px。PX的计算是不同的看到这个stackoverflow.com/questions/6840904/...
Lukap

7

还有一个答案:

/**
* @return "ldpi", "mdpi", "hdpi", "xhdpi", "xhdpi", "xxhdpi", "xxxhdpi", "tvdpi", or "unknown".
*/
public static String getDensityBucket(Resources resources) {
    switch (resources.getDisplayMetrics().densityDpi) {
        case DisplayMetrics.DENSITY_LOW:
            return "ldpi";
        case DisplayMetrics.DENSITY_MEDIUM:
            return "mdpi";
        case DisplayMetrics.DENSITY_HIGH:
            return "hdpi";
        case DisplayMetrics.DENSITY_XHIGH:
            return "xhdpi";
        case DisplayMetrics.DENSITY_XXHIGH:
            return "xxhdpi";
        case DisplayMetrics.DENSITY_XXXHIGH:
            return "xxxhdpi";
        case DisplayMetrics.DENSITY_TV:
            return "tvdpi";
        default:
            return "unknown";
    }
}

3

获取设备加载的密度的另一种方法:

values为每种密度创建文件夹

  • 值(默认为mdpi)
  • 值-hdpi
  • 值-xhdpi
  • 值-xxhdpi
  • 值-xxxhdpi

在各自的字符串中添加字符串资源strings.xml

<string name="screen_density">MDPI</string>    <!-- ..\res\values\strings.xml -->
<string name="screen_density">HDPI</string>    <!-- ..\res\values-hdpi\strings.xml -->
<string name="screen_density">XHDPI</string>   <!-- ..\res\values-xhdpi\strings.xml -->
<string name="screen_density">XXHDPI</string>  <!-- ..\res\values-xxhdpi\strings.xml -->
<string name="screen_density">XXXHDPI</string> <!-- ..\res\values-xxxhdpi\strings.xml -->

然后,只需获取字符串资源,即可获得密度:

String screenDensity = getResources().getString(R.string.screen_density);

如果密度大于XXXHDPI,则默认为XXXHDPI,如果小于HDPI则默认为MDPI

R.strings.screen_density值

我省略了LDPI,因为对于我的用例来说这是没有必要的。


我认为这是获得密度的正确方法。因为我使用的是getResources()。getDisplayMetrics()。density,所以如果更改设置中的显示大小,密度将发生变化。
幻想坊

1

尝试这个...

在科特林

fun determineScreenDensityCode(): String {
      return when (resources.displayMetrics.densityDpi) {
         DisplayMetrics.DENSITY_LOW -> "ldpi"
         DisplayMetrics.DENSITY_MEDIUM -> "mdpi"
         DisplayMetrics.DENSITY_HIGH -> "hdpi"
         DisplayMetrics.DENSITY_XHIGH, DisplayMetrics.DENSITY_280 -> "xhdpi"
         DisplayMetrics.DENSITY_XXHIGH, DisplayMetrics.DENSITY_360, DisplayMetrics.DENSITY_400, DisplayMetrics.DENSITY_420 -> "xxhdpi"
         DisplayMetrics.DENSITY_XXXHIGH, DisplayMetrics.DENSITY_560 -> "xxxhdpi"
         else -> "Unknown code ${resources.displayMetrics.densityDpi}"
     }
}

您可以通过呼叫,println("density: ${determineScreenDensityCode()}") 输出将是System.out: density: xxxhdpi


0

我正在使用以下代码从模块访问DPI(无需访问上下文对象):

(Resources.getSystem().getDisplayMetrics().xdpi
Resources.getSystem().getDisplayMetrics().ydpi)/2

0

在Android中,您可以这样获得屏幕密度:

public static String getScreenDensity(Context context)
{
    String density;
    switch (context.getResources().getDisplayMetrics().densityDpi)
    {
        case DisplayMetrics.DENSITY_LOW:
            density = "LDPI";
            break;
        case DisplayMetrics.DENSITY_140:
            density = "LDPI - MDPI";
            break;
        case DisplayMetrics.DENSITY_MEDIUM:
            density = "MDPI";
            break;
        case DisplayMetrics.DENSITY_180:
        case DisplayMetrics.DENSITY_200:
        case DisplayMetrics.DENSITY_220:
            density = "MDPI - HDPI";
            break;
        case DisplayMetrics.DENSITY_HIGH:
            density = "HDPI";
            break;
        case DisplayMetrics.DENSITY_260:
        case DisplayMetrics.DENSITY_280:
        case DisplayMetrics.DENSITY_300:
            density = "HDPI - XHDPI";
            break;
        case DisplayMetrics.DENSITY_XHIGH:
            density = "XHDPI";
            break;
        case DisplayMetrics.DENSITY_340:
        case DisplayMetrics.DENSITY_360:
        case DisplayMetrics.DENSITY_400:
        case DisplayMetrics.DENSITY_420:
        case DisplayMetrics.DENSITY_440:
            density = "XHDPI - XXHDPI";
            break;
        case DisplayMetrics.DENSITY_XXHIGH:
            density = "XXHDPI";
            break;
        case DisplayMetrics.DENSITY_560:
        case DisplayMetrics.DENSITY_600:
            density = "XXHDPI - XXXHDPI";
            break;
        case DisplayMetrics.DENSITY_XXXHIGH:
            density = "XXXHDPI";
            break;
        case DisplayMetrics.DENSITY_TV:
            density = "TVDPI";
            break;
        default:
            density = "UNKNOWN";
            break;
    }

    return density;
}

在科特林这样:

fun getScreenDensity(context: Context): String {
    val density: String
    when (context.resources.displayMetrics.densityDpi) {
        DisplayMetrics.DENSITY_LOW -> density = "LDPI"
        DisplayMetrics.DENSITY_140 -> density = "LDPI - MDPI"
        DisplayMetrics.DENSITY_MEDIUM -> density = "MDPI"
        DisplayMetrics.DENSITY_180, DisplayMetrics.DENSITY_200, DisplayMetrics.DENSITY_220 -> density = "MDPI - HDPI"
        DisplayMetrics.DENSITY_HIGH -> density = "HDPI"
        DisplayMetrics.DENSITY_260, DisplayMetrics.DENSITY_280, DisplayMetrics.DENSITY_300 -> density = "HDPI - XHDPI"
        DisplayMetrics.DENSITY_XHIGH -> density = "XHDPI"
        DisplayMetrics.DENSITY_340, DisplayMetrics.DENSITY_360, DisplayMetrics.DENSITY_400, DisplayMetrics.DENSITY_420, DisplayMetrics.DENSITY_440 -> density =
            "XHDPI - XXHDPI"
        DisplayMetrics.DENSITY_XXHIGH -> density = "XXHDPI"
        DisplayMetrics.DENSITY_560, DisplayMetrics.DENSITY_600 -> density = "XXHDPI - XXXHDPI"
        DisplayMetrics.DENSITY_XXXHIGH -> density = "XXXHDPI"
        DisplayMetrics.DENSITY_TV -> density = "TVDPI"
        else -> density = "UNKNOWN"
    }

    return density
}

确保定期检查是否添加了新的密度

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.