2012-01-29 4 views
6

Может ли кто-нибудь сказать мне, как Android подсчитывает плотность экрана?Расчет плотности экрана Android

У меня есть устройство (ODYS Space) с разрешением 480x800 и с диагональю 7 дюймов. Если я вычислил его плотность, я получаю значение 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 вместо этого?

+0

Если вы ищете щедрость, см. Ответ Питера О. и мой комментарий ниже. Главное здесь - то, как Android фактически вычисляет плотность, а не как извлекает настройки. Например, где находится отсечка между LDPI и MDPI, MDPI и HDPI и т. Д. ... почему заданное число округляется до верхней плотности, а не от нижней соседней плотности и т. Д. Опять же, намек на ответ можно увидеть в редакторе AVD-устройств, но до сих пор я не смог найти детерминированный, определенный, правильный ответ. – davidcesarino

+0

DPI - Устройство независимый пиксель Вы не можете иметь собственные значения, потому что есть starndards 0,75 - ldpi - 120 точек на дюйм 1,0 - MDPI - 160 точек на дюйм 1,5 - ИПЧР - 240 точек на дюйм 2,0 - xhdpi - 320 точек на дюйм 3,0 - xxhdpi - 480 dpi 4.0 - xxxhdpi - 640 dpi –

ответ

0

Если вы проверите docs (см. Раздел «Использование классификаторов конфигурации»), устройство считается «низким уровнем DPI», пока вы не обходите/ниже 120 DPI.

+0

Да. androis говорит 120 = LOW; 160 = СРЕДНЯЯ; 240 = ВЫСОКИЙ. это нормально (также я знаю, что он использует любое округление при расчете стандартных значений) – rugo

+1

НО, почему андроидные раунды 133 DPI до 160 против 120, как я и ожидал? – rugo

+0

Я уверен, что у них были веские причины для этого, но я их не знаю. – dmon

0

Я использую тот же код, и я видел только значения плотности 160, 240, 320 плотности. Я думаю, что это такая нормализация на android os. Это мое предложение, но я не знаю подробной технической информации.

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; 
     } 

    } 
} 
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;  
     } 
    } 
1

Actualy, если вы хотите иметь реального отображение точек на дюйм ответ находится где-то между , если вы запрашиваете показатели показаний:

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 не даст вам всегда РЕАЛ точек на дюйм от данного дисплея, так может быть реальным дюйм дисплея должно быть Density*xdpi

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 lavel 4 или выше.

3

Здесь есть две разные вещи.

  1. Поведение в эмуляторе, которое представляет собой комбинацию AVD-менеджера, настраивающего сам AVD и, возможно, использование определения устройства. Изображения системы эмулятора выпекаются в значениях, поэтому мы можем отправить одно и то же изображение для всех конфигураций устройств. Это запеченное значение mdpi для плотности. Когда вы создаете AVD с другой плотностью, мы вводим перед загрузкой новое значение. Инжектированное значение преобразуется в значение плотности (ldpi, mdpi, hdpi, ...) на основе базовых правил (если вы пройдете половину точки между значением ведра, вы переходите к следующему значению).

Таким образом, половина пункта между 120 и 160 равна 140, и поэтому 133dpi -> ldpi.

  1. Устройство делает все, что захочет. Для любого OEM-производителя это вручную, чтобы определить, что такое ведро для своего устройства, и это устанавливается в свойстве. Он не динамически вычисляется на основе фактического размера аппаратного экрана устройства. Вы можете сделать устройство с истинной плотностью экрана 133 и все же поместить его в ведро xxdpi, если хотите.

Конечный результат заключается в том, что вам необходимо создать новое определение устройства, в котором вы вручную скажете, что ваше устройство 780x800 на самом деле является устройством средней плотности, и оно должно работать. Если это не так, это ошибка на наша сторона, когда мы настраиваем эмулятор для конкретного AVD на устройстве. Это не проблема на самой платформе Android, которая ничего не вычисляет.

+0

Конечно, я знал, что OEM-производители определили свою ценность (похоже, как это делает сообщество моддинга, я думаю). О редакторе AVD я не знал _exactly_, как диалог рассчитал плотность (не видя кода). Тем не менее, спасибо за подтверждение того, что я подозревал в эксперименте: это выбор ведра, ближайшего к расчетной плотности.С этой информацией я пошел, чтобы найти, где именно он был найден, и нашел класс 'SizeListener' в' DeviceCreationDialog' (в sdkuilib), который дал мне точный алгоритм, используемый в этом обстоятельстве. Спасибо. – davidcesarino

0

Производитель выбирает плотность при создании образа ПЗУ для вашего устройства. Он не рассчитывается во время выполнения.

Если вы посмотрите на источник: 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 
Смежные вопросы