在android中以编程方式获取屏幕密度?
Posted
技术标签:
【中文标题】在android中以编程方式获取屏幕密度?【英文标题】:getting the screen density programmatically in android? 【发布时间】:2011-03-11 03:19:23 【问题描述】:如何在 android 中以编程方式获取屏幕密度?
我的意思是:如何找到当前设备的屏幕dpi?
【问题讨论】:
很多答案参考getDisplayMetrics().xdpi
,它应该返回设备的真实dpi。请注意,制造商在不同设备上设置的值不一致,因此您无法使用它们。悲伤但真实:没有关于真实 dpi 的信息。来源:groups.google.com/d/msg/android-developers/g56jV0Hora0/…
getResources().getDisplayMetrics().xdpi
和 getResources().getDisplayMetrics().ydpi
将为您提供实际的水平和垂直密度,在大多数情况下它们是不同的。
【参考方案1】:
您可以从 DisplayMetrics 结构中获取有关显示的信息:
DisplayMetrics metrics = getResources().getDisplayMetrics();
虽然 Android 不使用直接像素映射,但它使用少量量化的密度独立像素值,然后缩放到实际屏幕尺寸。所以metrics.densityDpi
属性将是DENSITY_xxx
常量之一(120
、160
、213
、240
、320
、480
或640
dpi)。
如果您需要实际 lcd 像素密度(可能对于 OpenGL 应用程序),您可以分别从水平和垂直密度的 metrics.xdpi
和 metrics.ydpi
属性中获得它。
如果您的目标 API 级别早于 4。metrics.density
属性是参考密度 (160dpi) 的浮点缩放因子。现在可以计算metrics.densityDpi
提供的相同值
int densityDpi = (int)(metrics.density * 160f);
【讨论】:
虽然这篇文章是两年多前的,但这是谷歌搜索的第一件事,所以对于找到这个的人,你不再需要乘以 160。 从哪个版本开始不再使用? 我已更新答案以匹配人们可能正在使用的最新 API 修订版。 注意:您可能需要这个更新的 API:getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
这是在 API 17 中正式添加的,但我惊讶地发现它即使在我尝试过的 4.0 设备上也能正常工作。
还有getResources().getDisplayMetrics().densityDpi【参考方案2】:
这也有效:
getResources().getDisplayMetrics().density;
这会给你:
0.75 - ldpi
1.0 - mdpi
1.5 - hdpi
2.0 - xhdpi
3.0 - xxhdpi
4.0 - xxxhdpi
ref: density
ref 2
【讨论】:
+1 当您无法直接访问WindowManager
(例如在加载程序中)时,此方法有效。只需乘以 160
API 级别 16 添加了 xxdpi,此处转换为 3.0。
这将为tvdpi
提供1.3312501。有关tvdpi
的更多信息,请参阅here
Nexus 7 报告 1.3,为什么要加入括号?
@selbie,您的手机可能正在拉取和扩展更高质量的资源,因为您的手机报告的数据介于两个定义的密度之间。【参考方案3】:
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 的设备? 在密度值之间进行 if-else 手动检查,例如 if (metrics.densityDpi > DisplayMetrics.DENSITY_LOW && metrics.densityDpi OR if (metrics.densityDpi Neil,213 称为 TV DPI,该 DENSITY_TV 有一个命名的显示指标密度。【参考方案4】:Blundell's 作为静态辅助方法回答:
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 @AnoopssGolden 这不是真正的标准,因此您可以根据需要添加它,但我认为答案不应该包含它。来自 android 文档:“这不被视为“主要”密度组。它主要用于电视,大多数应用程序不需要它。 但是nexus 7设备属于tvdpi密度组。 我知道这有点旧,但只是补充一下; MDPI 可能适用于 Nexus 7 上的大多数事情,但正如我现在正在尝试的那样,作为 MDPI 下降的图像还不够大。我必须定义 TVDPI,然后从我的服务器请求更大的图像大小。它可能不会被大量使用,但这并不意味着 MDPI 会拿起一切。 嘿@Andrew S,使用 elses 不会改变代码的效率,因为每个 if 都会立即返回。删除大括号只是样式问题,恕我直言,在维护代码时更容易出错。【参考方案5】:试试这个:
DisplayMetrics dm = context.getResources().getDisplayMetrics();
int densityDpi = dm.densityDpi;
【讨论】:
我更喜欢这个,因为它依赖于上下文而不是活动。 同意,我可以从View
更轻松地使用它(这正是我需要的地方!)【参考方案6】:
这里有一些密度常数,source:
除了标准密度外,还有 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;
【讨论】:
【参考方案7】:获取 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;
【讨论】:
dm.densityDpi 返回 DENSITY_LOW 或 DENSITY_MEDIUM 或 DENSITY_HIGH。那么xhdpi呢?有没有DENSITY_XHIGH左右? 是的,有:developer.android.com/reference/android/util/…【参考方案8】:以下答案是基于 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
【讨论】:
这段代码可以做一些其他的事情,它后面的和号和条件是多余的。 @Andrew,感谢您的更正。我已经相应地编辑了答案。 @San 你在任何这些条件下都不需要 &&,只要你一直检查 >= else if 将在第一个条件为真时终止。 这不会为我的 Nexus 5X(顺便说一句默认的谷歌设备)返回正确的结果。设备密度为xxhdpi,返回的双倍密度在2.6左右。【参考方案9】:实际上,如果您想要 真正的显示 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 .. 但我不确定这是否是正确的做法!
【讨论】:
使用 Density*xdpi 在过去 6 个月里我在 google play 上的所有应用程序上运行良好 乘以密度 * xdpi 是不合逻辑的,现在有更多更高密度的设备更清楚了 - 密度和 xdpi 都增加了,因此将它们相乘将重复计算增加。我会说三星 ace 2 是供应商的错误。 Android 规范是 xdpi 和 ydpi 是真正的像素密度 - 不要乘以任何东西。【参考方案10】:这应该有助于您的活动......
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
【讨论】:
【参考方案11】: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;
【讨论】:
【参考方案12】:如果您想从服务中检索密度,它的工作原理如下:
WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
【讨论】:
这个在我没有windowManager的时候帮助了我【参考方案13】:你应该试试这个。刚刚添加了一个可以找到并显示 Toast 的方法。设备属于哪个类别。
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
【讨论】:
【参考方案14】:这应该可行。
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels; //320
int height = dm.heightPixels; //480
【讨论】:
显示的像素大小不是密度。 这是与密度无关的像素,而不是像素。你看到的 320 是 320dip 而不是 320px。 px的计算不一样看这个***.com/questions/6840904/…【参考方案15】:又一个答案:
/**
* @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";
【讨论】:
【参考方案16】:另一种获取设备加载密度的方法:
为每个密度创建values
文件夹
在各自的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
我省略了LDPI
,因为对于我的用例来说它不是必需的。
【讨论】:
我认为这是获得密度的正确方法。因为我使用getResources().getDisplayMetrics().density,所以如果我在设置中改变显示尺寸,密度会改变。【参考方案17】:试试这个……
在科特林中
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
【讨论】:
【参考方案18】:我正在使用以下代码从模块访问 DPI(无需访问上下文对象):
(Resources.getSystem().getDisplayMetrics().xdpi
Resources.getSystem().getDisplayMetrics().ydpi)/2
【讨论】:
【参考方案19】:在 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;
像这样在 Kotlin 中:
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
请务必定期check if new densities are added。
【讨论】:
以上是关于在android中以编程方式获取屏幕密度?的主要内容,如果未能解决你的问题,请参考以下文章
android: android中dipdppxsp和屏幕密度
Android 屏幕适配屏幕适配基础概念 ③ ( 屏幕像素密度 DPI 与素材大小关联 | 屏幕像素密度 DPI 与 屏幕密度限定符关联 )
Android 屏幕适配屏幕适配基础概念 ③ ( 屏幕像素密度 DPI 与素材大小关联 | 屏幕像素密度 DPI 与 屏幕密度限定符关联 )
Android 屏幕适配屏幕适配基础概念 ② ( 像素 px 与 密度无关像素 dip | 像素 px 与 密度无关像素 dip 在不同屏幕像素密度 dpi 下的换算关系 )