2012-01-29 15 views
6

Czy ktoś może mi powiedzieć, w jaki sposób Android liczy gęstość ekranu?Obliczanie gęstości ekranu Androida:

Mój problem jest mieć urządzenie (ODYS spacja) o rozdzielczości 480x800 oraz z 7" przekątnej ekranu. Gdybym oblicz jego gęstość uzyskać wartość 133 DPI ale Android (2.2 i 2.3 zbyt) informuje go jak „średni "Gęstość urządzenia (160 DPI)

Walczę z obsługą wielu ekranów, więc przypuszczam, że 133 DPI będzie raczej zgłaszane jako" NISKI "niż" ŚREDNI ", więc teraz mój układ ekranu wygląda dość głupio na tym medium zgłoszonym urządzeniu.

sprawdzić urządzenie z kodem tak:

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

Jeśli uruchomię ten kod na skonfigurowanym urządzeniu wirtualnym (480x800/7 "i 133 DPI), wówczas otrzymam gęstość = 120.

Na prawdziwym urządzeniu dlaczego zamiast tego mówi się po 160?

+0

Jeśli szukasz nagrody, zobacz odpowiedź Petera O. i mój komentarz poniżej. Główną kwestią jest to, w jaki sposób Android oblicza gęstość, a nie w jaki sposób pobiera ustawienia. Na przykład, gdzie jest granica między LDPI i MDPI, MDPI i HDPI, i tak dalej ... dlaczego dana liczba jest zaokrąglana do górnej gęstości, a nie do niższej sąsiadującej gęstości, i tak dalej. Ponownie, podpowiedź odpowiedzi można zobaczyć w Edytorze urządzeń AVD, ale jak dotąd nie udało mi się znaleźć deterministycznej, pewnej, poprawnej odpowiedzi. – davidcesarino

+0

DPI - urządzenie niezależne pikseli nie może mieć wartości własnych, ponieważ istnieje starndards 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 –

Odpowiedz

0

Jeśli sprawdzisz numer docs (zobacz sekcję "Używanie kwalifikatorów konfiguracji"), urządzenie będzie uważane za "niską wartość DPI" do momentu osiągnięcia wartości 120 DPI.

+0

Tak. androis mówi 120 = LOW; 160 = ŚREDNI; 240 = WYSOKI. to jest w porządku (wiem też, że używa on jakiegokolwiek zaokrąglenia, gdy oblicza się standardowe wartości). – rugo

+1

ALE dlaczego android zaokrągla 133 DPI do 160 przeciwnych 120, jak się spodziewałem? – rugo

+0

Jestem pewien, że mieli dobre powody, ale ja ich nie znam. – dmon

0

Używam tego samego kodu i widziałem wartości tylko 160, 240, 320 gęstościDisplay. Myślę, że to taka normalizacja na Androidzie. To moja sugestia, tylko nie znam szczegółowych informacji technicznych.

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

Mam aktualizowane jeden z pozostałych rozwiązań do 2014

wywołanie tej metody w jednym ze swoich działań:

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

właściwie, jeśli chcesz mieć rzeczywistym wyświetlania dpi odpowiedź jest gdzieś pomiędzy jeśli zapytanie do wyświetlania danych:

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

densityDpi daje Wartości/sugestię których gęstość należy użyć

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 

jak określono w poprzednich postach

ale dm.xdpi nie da Ci zawsze NIERUCHOMOŚCI dpi z danego ekranu, tak może prawdziwy dpi wyświetlacza powinna być 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; 

}

To będzie działać w API lavel 4 lub wyżej.

3

Tu są dwie różne rzeczy.

  1. Zachowanie w emulatorze, które jest połączeniem menedżera AVD konfigurującego sam AVD i może z wykorzystaniem definicji urządzenia. Obrazy systemu emulatora zapaliły się w wartościach, dzięki czemu możemy wysłać ten sam obraz dla wszystkich konfiguracji urządzeń. Ta wartość pieczenia wynosi mdpi dla gęstości. Gdy tworzysz AVD o innej gęstości, wstrzykniemy tuż przed startem nową wartość. Wartość wtrysku jest konwertowana na wartość kubełkową gęstości (ldpi, mdpi, hdpi, ...) na podstawie podstawowych reguł (jeśli minąłeś pół punktu między wartością wiadra, przejdziesz do następnej wartości).

Tak więc pół punktu między 120 a 160 wynosi 140, a zatem 133dpi -> ldpi.

  1. Urządzenie zrobić, co chce. Jest to proces ręczny, w którym każdy producent OEM decyduje, jaka jest wartość jego zasobnika, a następnie ustawia się w usłudze. Nie jest on obliczany dynamicznie w oparciu o rzeczywisty rozmiar ekranu urządzenia. Możesz zrobić urządzenie, które ma rzeczywistą gęstość ekranu 133 i umieścić je w wiadrze xxdpi, jeśli chcesz.

Rezultat końcowy jest taki, że musisz utworzyć nową definicję urządzenia, w której ręcznie powiesz, że urządzenie 7 "480 x 800 jest w rzeczywistości urządzeniem o średniej gęstości, i powinno działać. Jeśli nie, jest to błąd po naszej stronie, gdy konfigurujemy emulator dla konkretnego urządzenia AVD, to nie jest problem na samej platformie Android, który niczego nie oblicza.

+0

Jasne, wiedziałem, że producenci OEM zdefiniowali swoją własną wartość (podobnie, jak przypuszcza wspólnota modingowa). O edytorze AVD, nie wiedziałem _exactly_ jak okno obliczyło gęstość (nie widząc kodu). To powiedziawszy, dziękuję za potwierdzenie tego, co podejrzewałem przez eksperymentowanie: to wybiera wiadro, które jest najbliższe obliczonej gęstości.Z tymi informacjami poszedłem znaleźć dokładnie to, gdzie się znajdował i znalazłem klasę "SizeListener' w" DeviceCreationDialog' (w sdkuilib), która dała mi dokładny algorytm używany w tej sytuacji. Dziękuję Ci. – davidcesarino

0

Producent wybiera gęstość, gdy tworzy obraz ROM dla twojego urządzenia. Nie jest ona obliczana w czasie wykonywania:

Jeśli spojrzysz na źródło: https://github.com/android/platform_frameworks_base/blob/master/core/java/android/util/DisplayMetrics.java#L294 zobaczysz funkcję getDeviceDensity() próbuje użyć dwóch właściwości systemu, jedna jest wartością emulatora qemu: qemu.sf.lcd_density, a druga jest wartością fabryczną producenta ro.sf.lcd_density, a na koniec, jeśli producent zapomniał ustawić jeden, system powraca do wartości domyślnej. DENSITY_DEFAULT jest ustawiony na DENSITY_MEDIUM, który jest ustawiony na 160.

można zweryfikować własność urządzenia, podłączając urządzenia i uruchomieniu tego polecenia:

adb shell getprop ro.sf.lcd_density 

Właściwości są przechowywane w /system/build.prop i są ładowane przy starcie. Możesz sprawdzić zawartość pliku za pomocą następującego polecenia:

adb shell cat /system/build.prop 
Powiązane problemy