Jak określić szerokość ekranu w kategoriach dp lub dip w czasie wykonywania w Androidzie?

193

Muszę zakodować układ widgetów Androida za pomocą dip / dp (w plikach Java). W czasie wykonywania, jeśli koduję

int pixel=this.getWindowManager().getDefaultDisplay().getWidth();

to zwraca szerokość ekranu w pikselach (px). Aby przekonwertować to na dp, kodowałem:

int dp =pixel/(int)getResources().getDisplayMetrics().density ;

Wydaje się, że nie zwraca poprawnej odpowiedzi. Zrobiłem emulator WVGA800, którego rozdzielczość ekranu wynosi 480 na 800. Kiedy uruchom emulator i pozwól kodowi wydrukować wartości pikseli i dp, w obu wypadło 320. Ten emulator ma rozdzielczość 240 dpi, której współczynnik skali wyniósłby 0,75.

Khushboo
źródło

Odpowiedzi:

377

Spróbuj tego

Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics ();
display.getMetrics(outMetrics);

float density  = getResources().getDisplayMetrics().density;
float dpHeight = outMetrics.heightPixels / density;
float dpWidth  = outMetrics.widthPixels / density;

LUB

Dzięki @ Tomáš Hubálek

DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();    
float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
Dax
źródło
91
Dlaczego konieczne jest wywołanie WindowManager? Co z tym kodem? DisplayMetrics displayMetrics = resources.getDisplayMetrics (); float screenWidthDp = displayMetrics.widthPixels / displayMetrics.density;
Tomáš Hubálek,
2
Nie działało to dla mnie przy użyciu ekranu o bardzo wysokiej gęstości. To było tak, jakby miał tylko niewielką część ekranu. To rozwiązanie działało dla mnie: stackoverflow.com/a/18712361/956975 Wyświetl display = getWindowManager (). GetDefaultDisplay (); Rozmiar punktu = nowy punkt (); display.getSize (rozmiar); int width = size.x; int wysokość = rozmiar. y;
marienke
1
@dsdsdsdsd: kontekst to dowolna instancja klasy Context. Przede wszystkim Activity jest podklasą Context (więc użyj tego w Activity, a getActivity () we fragmencie). Aplikacja i usługa są również podklasami kontekstu.
François POYER
112

Natknąłem się na to pytanie od Google, a później znalazłem łatwe rozwiązanie ważne dla API> = 13.

Dla przyszłych referencji:

Configuration configuration = yourActivity.getResources().getConfiguration();
int screenWidthDp = configuration.screenWidthDp; //The current width of the available screen space, in dp units, corresponding to screen width resource qualifier.
int smallestScreenWidthDp = configuration.smallestScreenWidthDp; //The smallest screen size an application will see in normal operation, corresponding to smallest screen width resource qualifier.

Zobacz Odwołanie do klasy konfiguracji

Edycja: Jak zauważył Nick Baicoianu, zwraca użyteczną szerokość / wysokość ekranu (które powinny być interesujące w większości zastosowań). Jeśli potrzebujesz rzeczywistych wymiarów wyświetlacza, trzymaj się górnej odpowiedzi.

serjlee
źródło
23
Jedną ważną różnicą między używaniem screenWidthDp / screenHeightDp konfiguracji w DisplayMetrics widthPixels / heightPixels w konfiguracji jest to, że konfiguracja zwraca użyteczne wymiary wyświetlania (minus pasek stanu itp.), A DisplayMetrics zwraca wymiary pełnego ekranu.
Nick Baicoianu,
Dotyczy to wyłącznie poziomu API 13 i
wyższego
Aby dodać do komentarza @ NickBaicoianu, zarówno metody getConfiguration (), jak i getDisplayMetrics () działają w trybie wielu okien. tzn. rozmiary odzwierciedlają rozmiar okna, a nie ekranu.
nmw
7

Brakuje domyślnej wartości gęstości 160.

    2 px = 3 dip if dpi == 80(ldpi), 320x240 screen
    1 px = 1 dip if dpi == 160(mdpi), 480x320 screen
    3 px = 2 dip if dpi == 240(hdpi), 840x480 screen

Innymi słowy, jeśli projektujesz układ o szerokości równej 160dip w trybie pionowym, będzie to połowa ekranu na wszystkich urządzeniach ldpi / mdpi / hdpi (chyba, że ​​na tabletach)

Mychajło Gaidai
źródło
Odpowiedzieliście na logiczne uzasadnienie mojego pytania. Rozumiem to. Jak mam to zakodować w Javie, aby w czasie wykonywania, niezależnie od rozdzielczości ekranu, kod wybrał prawidłową szerokość dpi?
Khushboo
Mam nadzieję, że tym razem dobrze to zrobię :) Użyj DisplayMetrics outMetrics = null; getWindowManager().getDefaultDisplay().getMetrics(outMetrics);w ramach działania. Następnie outMetrics.densitypoda współczynnik skali bieżącego urządzenia, jak stwierdzono w dokumentach
Mykhailo Gaidai
6

A może zamiast tego użyć tego?

final DisplayMetrics displayMetrics=getResources().getDisplayMetrics();
final float screenWidthInDp=displayMetrics.widthPixels/displayMetrics.density;
final float screenHeightInDp=displayMetrics.heightPixels/displayMetrics.density;
programista Androida
źródło
6
DisplayMetrics displayMetrics = new DisplayMetrics();

getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

int width_px = Resources.getSystem().getDisplayMetrics().widthPixels;

int height_px =Resources.getSystem().getDisplayMetrics().heightPixels;

int pixeldpi = Resources.getSystem().getDisplayMetrics().densityDpi;


int width_dp = (width_px/pixeldpi)*160;
int height_dp = (height_px/pixeldpi)*160;
Supun Madushanka
źródło
8
Rozważ wyjaśnienie
bigbounty,
5

Odpowiedź w kotlin:

  context?.let {
        val displayMetrics = it.resources.displayMetrics
        val dpHeight = displayMetrics.heightPixels / displayMetrics.density
        val dpWidth = displayMetrics.widthPixels / displayMetrics.density
    }
Bolling
źródło
4

Uproszczony dla Kotlin:

val widthDp = resources.displayMetrics.run { widthPixels / density }
val heightDp = resources.displayMetrics.run { heightPixels / density }
TheYogi
źródło
2

Uzyskaj szerokość i wysokość ekranu w kategoriach DP z dobrą dekoracją:

Krok 1: Utwórz interfejs

public interface ScreenInterface {

   float getWidth();

   float getHeight();

}

Krok 2: Utwórz klasę implementującą

public class Screen implements ScreenInterface {
    private Activity activity;

    public Screen(Activity activity) {
        this.activity = activity;
    }

    private DisplayMetrics getScreenDimension(Activity activity) {
        DisplayMetrics displayMetrics = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        return displayMetrics;
    }

    private float getScreenDensity(Activity activity) {
        return activity.getResources().getDisplayMetrics().density;
    }

    @Override
    public float getWidth() {
        DisplayMetrics displayMetrics = getScreenDimension(activity);
        return displayMetrics.widthPixels / getScreenDensity(activity);
    }

    @Override
    public float getHeight() {
        DisplayMetrics displayMetrics = getScreenDimension(activity);
        return displayMetrics.heightPixels / getScreenDensity(activity);
    }
} 

Krok 3: Uzyskaj szerokość i wysokość w aktywności:

Screen screen = new Screen(this); // Setting Screen
screen.getWidth();
screen.getHeight();
Ali Azaz Alam
źródło
Czy to zwraca wysokość i szerokość w pikselach lub dp?
Taslim Oseni
jak nazywa się .density, dlatego daje ci w dp
Ali Azaz Alam
Nie sądzę, że dobrym pomysłem jest dodanie tonów kodu do aplikacji, aby rozwiązać proste zadanie
Ruslan Berozov,
Sir, to zależy od tego, czy zaimplementować klasę, czy bezpośrednio ją kodować. Ze zdefiniowanej klasy można łatwo wyodrębnić kod do bezpośredniej implementacji.
Ali Azaz Alam
0

Jeśli chcesz tylko wiedzieć o szerokości ekranu, możesz po prostu wyszukać „najmniejszą szerokość ekranu” w opcjach programisty. Możesz go nawet edytować.

kanał matematyczny
źródło
0

Spróbuj tego:

Display display   = getWindowManager().getDefaultDisplay();
Point displaySize = new Point();
display.getSize(displaySize);
int width  = displaySize.x;
int height = displaySize.y;
Muhammed naseef Koppilakkal
źródło
-5

Twój problem polega na tym, że rzutowanie float na int, traci precyzję. Powinieneś także pomnożyć przez współczynnik, a nie dzielić.

Zrób to:

int dp = (int)(pixel*getResources().getDisplayMetrics().density);
Dirk le Roux
źródło
3
Ta odpowiedź jest niepoprawna. Od developer.android.com/guide/practices/… , Pixel = Dp * Gęstość.
Vance-Turner