我想在代码中确定当前设备屏幕的大小,包括小、中、大或超大。在SDK文档中没有找到任何有助于获得这些信息的内容。我查看的所有方法/类都只提供绝对值(即像素屏幕尺寸、屏幕密度等)。
是否有一种方式可以在代码中告诉我当前运行的屏幕类型?
我想在代码中确定当前设备屏幕的大小,包括小、中、大或超大。在SDK文档中没有找到任何有助于获得这些信息的内容。我查看的所有方法/类都只提供绝对值(即像素屏幕尺寸、屏幕密度等)。
是否有一种方式可以在代码中告诉我当前运行的屏幕类型?
最终我使用了放置在不同桶文件夹中的bool
资源。我只需要区分普通(小/中)和大型(大/超大)屏幕,所以我这样做:
values/bools.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="screen_large">false</bool>
</resources>
values-large/bools.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="screen_large">true</bool>
</resources>
然后,我只需要调用getBoolean(R.bool.screen_large)
来判断屏幕是否大屏幕。这样,完全由平台决定设备的屏幕大小。
密度和屏幕类型是有区别的。
由于您可以获取像素和密度,因此您始终可以使用静态 Helper 类来确定它们。
您可以使用该类将像素转换为 dp。
public static float dpFromPixels(int pixels) {
float dp = (float) ((pixels) / Density.scale);
return dp;
}
我认为您可能需要在像素值上加或减0.5f,因为从dp获取像素值是基于该代码的。
public static int pixelsFromDp(float dps) {
int pixels = (int) (dps * Density.scale + 0.5f);
return pixels;
}
以下是来自文档的内容:
超大屏幕至少为 960dp x 720dp
大屏幕至少为 640dp x 480dp
普通屏幕至少为 470dp x 320dp
小屏幕至少为 426dp x 320dp
Density.scale
是从哪里来的? - Qwertiepublic static boolean isLargeScreen(Context context) {
int screenSize = context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK;
return screenSize >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
我认为Felix的回答非常优雅。但是,我认为在这篇文章中我发现的方法可能更加简单如何使用代码确定设备屏幕大小类别(小、正常、大、超大)?
使用 DisplayMetrics
类...
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
// DENSITY_LOW, DENSITY_MEDIUM, DENSITY_HIGH, or DENSITY_XHIGH
int density = dm.densityDpi;
小 = DisplayMetrics.DENSITY_LOW
中 = DisplayMetrics.DENSITY_MEDIUM
大 = DisplayMetrics.DENSITY_HIGH
特大 = DisplayMetrics.DENSITY_XHIGH
DisplayMetrics
确实给出了像素大小。可能你需要撤销你的投票。 - Ron作为对Felix答案的补充,您可以使用以下代码获取屏幕尺寸,而无需创建任何值-XXX文件夹:
int screenSize = getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
Log.d(TAG, "screenSize = "+screenSize);
switch(screenSize) {
case Configuration.SCREENLAYOUT_SIZE_LARGE:
Log.d(TAG, "Large Screen");
break;
case Configuration.SCREENLAYOUT_SIZE_NORMAL:
Log.d(TAG, "Normal Screen");
break;
case Configuration.SCREENLAYOUT_SIZE_SMALL:
Log.d(TAG, "Small Screen");
break;
case Configuration.SCREENLAYOUT_SIZE_XLARGE :
Log.d(TAG, "XLarge Screen");
break;
default:
Log.d(TAG, "Screen size is neither large, normal or small or xlarge");
}
public static boolean isLargeScreen(Configuration toCheckConfig) {
int screenSizeBucket = toCheckConfig.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
if (screenSizeBucket >= Configuration.SCREENLAYOUT_SIZE_LARGE) {
return true;
}
else return false;
}
Configuration
对象还包含SCREENLAYOUT_SIZE_SMALL
、SCREENLAYOUT_SIZE_XLARGE
等(如果您需要特别测试大小桶)。
这也可以很好地与这两个实用函数配合使用:
public static int getPixelsFromDp(Context context, int dpValue) {
return (int) (context.getResources().getDisplayMetrics().density * dpValue);
}
public static int getDpfromPixels(Context context, int pixels) {
return (int) (pixels / context.getResources().getDisplayMetrics().density);
}
当 context.getResources().getDisplayMetrics().density
等于 1.0
, 1.5
, 2.0
时,分别代表着 mdpi
, hdpi
, xhdpi
。
其他方案将设备屏幕分类为4个桶(小、正常、大、特大)。
对于那些想要将设备分类为6个可绘制桶的人,可以使用以下方法。
这种方法的优点是不需要执行屏幕密度计算,因为这可能与操作系统的计算方式不同。相反,该解决方案纯粹依赖于操作系统来决定密度桶。这种解决方案的缺点是需要创建冗余的可绘制资源,这并不优雅。
有6个屏幕密度桶:
该解决方案需要创建6个可绘制图像,并将其放置到密度文件夹中的一个副本中,以便每个密度文件夹都缺少相应命名的资源。例如,pixel_not_ldpi.png应放置在所有文件夹中,除了drawable-ldpi文件夹。
资源
注意:
一旦放置了这些图像,请编写一个帮助方法,使用6个try/catch块尝试加载每个资源。捕获Resources.NotFoundException。无论哪个资源引发异常,都是设备的屏幕密度。这适用于Android应用程序包。
这不是理想的解决方案,但它全面回答了问题,并且与其他涉及算术的解决方案不同,它纯粹依赖于操作系统来确定密度。
边界情况:App捆绑包未正确侧载
一些用户通过从Play商店之外或其他途径下载应用程序进行侧载,但有时会犯下载仅部分资源而非完整应用程序捆绑包的错误。这些用户可以安装并启动应用程序,但某些资源可能会丢失,这将导致在我们上面的try/catch块中触发资源未找到异常,从而无法确定资源是故意缺失还是因为不完整的应用程序捆绑包而丢失。
为了区分这两种情况,只需要使用相同的方法。将另一个资源pixel.png放入所有6个密度可绘制文件夹中,并尝试使用try/catch加载它。如果抛出异常,则说明应用程序已被错误下载。
享受吧!
DisplayMetrics
包含了你所需要的一切。要获取它,
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
heightPixels
和 widthPixels
,它们给出了显示器的绝对高度和宽度(以像素为单位)。 - Ron