Android屏幕密度计算

时间:2012-01-29 14:08:05

标签: android screen

有人可以告诉我Android如何计算屏幕密度吗?

我的问题是我有一个480x800分辨率和7“对角线屏幕的设备(ODYS Space)。 如果我计算它的密度,我得到一个133 DPI的值,但Android(2.2和2.3)也报告它像“MEDIUM”密度设备(160 DPI)。

我正在与多屏幕支持作斗争所以我认为133 DPI会报告为“LOW”而不是“MEDIUM”所以现在我的屏幕布局看起来非常愚蠢这个媒体报道设备。

我用这样的代码检查设备:

DisplayMetrics dMetrics = new DisplayMetrics(); 
getWindowManager().getDefaultDisplay().getMetrics(dMetrics);  
int d=dMetrics.densityDpi;

如果我在配置的虚拟设备上运行该代码(480x800 / 7“和133 DPI),那么我的密度= 120。

在真实设备上为什么会说160呢?

8 个答案:

答案 0 :(得分:3)

这里有两件不同的事情。

  1. 仿真器中的行为,它是配置AVD本身的AVD管理器和可能使用设备定义的组合。仿真器系统映像已烘焙值,以便我们可以为所有设备配置提供相同的映像。这个烘焙的值是密度的mdpi。 当您创建具有不同密度的AVD时,我们在启动时间之前注入新值。根据基本规则将注入的值转换为密度桶值(ldpi,mdpi,hdpi,...)(如果超过桶值之间的半点,则进入下一个值)。
  2. 因此,120和160之间的半点是140,因此133dpi - > LDPI。

    1. 设备随心所欲。对于任何OEM来说,这是一个手动过程,可以决定其设备的存储区值,并在属性中设置。它不是根据设备的实际硬件屏幕大小动态计算的。您可以使用真正的屏幕密度为133的设备,如果需要,可以将其放入xxdpi存储桶中。
    2. 最终结果是你需要创建一个新的设备定义,你手动说你的7“480x800设备实际上是一个中等密度的设备,它应该工作。如果没有,这是我们的一个错误我们为特定的基于设备的AVD配置仿真器。这不是Android平台本身的问题,它不会计算任何东西。

答案 1 :(得分:2)

我更新了2014年的其他解决方案之一。

在您的某个活动中调用此方法:

private void tellMeDensity() {
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        int dpiClassification = dm.densityDpi;

        float xDpi = dm.xdpi;
        float yDpi = dm.ydpi;

        Toast.makeText(this, "xdpi=" + xDpi, Toast.LENGTH_SHORT).show();
        Toast.makeText(this, "ydpi=" + yDpi, Toast.LENGTH_SHORT).show();

        switch(dpiClassification) {
           case DisplayMetrics.DENSITY_LOW:
               Toast.makeText(this, "low density", Toast.LENGTH_SHORT).show();
               break;    
           case DisplayMetrics.DENSITY_MEDIUM:
               Toast.makeText(this, "medium density", Toast.LENGTH_SHORT).show();
               break;                
           case DisplayMetrics.DENSITY_HIGH:
               Toast.makeText(this, "high density", Toast.LENGTH_SHORT).show();
               break;    
           case DisplayMetrics.DENSITY_XHIGH:
               Toast.makeText(this, "xhigh density", Toast.LENGTH_SHORT).show();
               break;                  
           case DisplayMetrics.DENSITY_XXHIGH:
               Toast.makeText(this, "xxhigh density", Toast.LENGTH_SHORT).show();
               break;                  
           case DisplayMetrics.DENSITY_XXXHIGH:
               Toast.makeText(this, "xxxhigh density", Toast.LENGTH_SHORT).show();
               break;      
        }
    }

答案 2 :(得分:1)

Actualy如果你想拥有真实显示dpi ,答案就在介于两者之间 如果您查询显示指标:

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

densityDpi会为您提供您应该使用的密度值/建议

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 ,所以显示器的真实dpi可能是 Density*xdpi

答案 3 :(得分:0)

如果您检查docs(查找“使用配置限定符”部分),设备将被视为“低DPI”,直到您达到/低于120 DPI。

答案 4 :(得分:0)

我正在使用相同的代码,我只看到了值160,240,320 densityDpi值。我认为这是android os上的这种规范化。这是我的建议,只是我不知道详细的技术信息。

答案 5 :(得分:0)

**dpi calculation programitically:**

public class SampleActivity extends Activity
{

   @Override
   public void onCreate(Bundle savedInstanceState)
    {
      super.onCreate(savedInstanceState);
       setContentView(R.layout.main);
       DisplayMetrics dm = new DisplayMetrics();
       getWindowManager().getDefaultDisplay().getMetrics(dm);
       int dpiClassification = dm.densityDpi;

    float xDpi = dm.xdpi;
    float yDpi = dm.ydpi;

    Toast.makeText(SampleActivity.this, "xdpi="+xDpi, Toast.LENGTH_SHORT).show();
    Toast.makeText(SampleActivity.this, "ydpi="+yDpi, Toast.LENGTH_SHORT).show();


    switch(dpiClassification)
    {
       case DisplayMetrics.DENSITY_LOW:
           Toast.makeText(SampleActivity.this, "low density",    
                   Toast.LENGTH_SHORT).show();

                 break;

       case DisplayMetrics.DENSITY_MEDIUM:
           Toast.makeText(SampleActivity.this, "low medium", 
                  Toast.LENGTH_SHORT).show();

                 break;
       case DisplayMetrics.DENSITY_HIGH:
           Toast.makeText(SampleActivity.this, "low high", 
                     Toast.LENGTH_SHORT).show();

                  break;



       case DisplayMetrics.DENSITY_XHIGH:
           Toast.makeText(SampleActivity.this, "low xhigh", 
                  Toast.LENGTH_SHORT).show();

                 break;
       }

    }
 }

答案 6 :(得分:0)

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或更高级别中运行。

答案 7 :(得分:0)

制造商在为您的设备制作ROM映像时选择密度。它不是在运行时计算的。

如果您查看来源:https://github.com/android/platform_frameworks_base/blob/master/core/java/android/util/DisplayMetrics.java#L294,您会看到getDeviceDensity()函数尝试使用两个系统属性,一个是qemu模拟器值qemu.sf.lcd_density,另一个是制造商设置值ro.sf.lcd_density,最后如果制造商忘记设置一个,系统将回退到默认值。 DENSITY_DEFAULT设置为DENSITY_MEDIUM,设置为160

您可以通过插入设备并运行此命令来验证设备属性:

adb shell getprop ro.sf.lcd_density

属性存储在/system/build.prop中,并在引导时加载。您可以使用以下命令查看文件的内容:

adb shell cat /system/build.prop