¿Cómo determinar el ancho de la pantalla en términos de dp o dip en tiempo de ejecución en Android?

193

Necesito codificar el diseño de los widgets de Android usando dip / dp (en archivos java). En tiempo de ejecución si codifico,

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

Esto devuelve el ancho de la pantalla en píxeles (px). Para convertir esto a dp, codifiqué:

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

Esto no parece devolver la respuesta correcta. Creé el emulador de WVGA800 cuya resolución de pantalla es de 480 por 800. Cuando ejecuté el emulador y dejé que el código imprimiera los valores de píxel y dp, llegó a 320 en ambos. Este emulador es de 240 ppp, cuyo factor de escala sería de 0,75.

Khushboo
fuente

Respuestas:

377

Prueba esto

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;

O

Gracias @ Tomáš Hubálek

DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();    
float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
Dax
fuente
9191
¿Por qué es necesario llamar a WindowManager? ¿Qué hay de este código? DisplayMetrics displayMetrics = resources.getDisplayMetrics (); float screenWidthDp = displayMetrics.widthPixels / displayMetrics.density;
Tomáš Hubálek
2
Esto no funcionó para mí usando una pantalla de muy alta densidad. Era como si solo tuviera una pequeña porción de la pantalla. Esta solución funcionó para mí: stackoverflow.com/a/18712361/956975 Display display = getWindowManager (). GetDefaultDisplay (); Tamaño del punto = nuevo punto (); display.getSize (tamaño); int ancho = tamaño.x; int height = size.y;
marienke
1
@dsdsdsdsd: context es cualquier instancia de la clase Context. En particular, Activity es una subclase de Context (así que úsala en una Activity y getActivity () en un Fragment). Aplicación y servicio también son subclases de contexto.
François POYER
112

Me topé con esta pregunta de Google, y más tarde encontré una solución fácil válida para API> = 13.

Para futuras referencias:

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.

Ver referencia de clase de configuración

Editar: como señaló Nick Baicoianu, esto devuelve el ancho / alto utilizable de la pantalla (que deberían ser los interesantes en la mayoría de los usos). Si necesita las dimensiones de visualización reales , manténgase en la respuesta superior.

serjlee
fuente
23
Una diferencia importante entre el uso de screenWidthDp / screenHeightDp vs DisplayMetrics widthPixels / heightPixels de Configuration es que Configuration devuelve las dimensiones de visualización utilizables (menos la barra de estado, etc.), mientras que DisplayMetrics devuelve las dimensiones de pantalla completa.
Nick Baicoianu
Esto es sólo para la API de nivel 13 y hasta
ono
Para agregar al comentario de @ NickBaicoianu, los métodos getConfiguration () y getDisplayMetrics () funcionan en modo de ventanas múltiples. es decir, los tamaños reflejan el de la ventana, no la pantalla.
nmw
7

Falta el valor de densidad predeterminado de 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

En otras palabras, si diseña su diseño con un ancho igual a 160dip en modo vertical, será la mitad de la pantalla en todos los dispositivos ldpi / mdpi / hdpi (excepto las tabletas, creo)

Mykhailo Gaidai
fuente
Lo que ha respondido es el razonamiento lógico detrás de mi pregunta. Entiendo esto. ¿Cómo debo codificar esto en Java para que, en tiempo de ejecución, sea cual sea la resolución de la pantalla, el código elija el ancho correcto de ppp?
Khushboo
Espero hacerlo bien esta vez :) Úselo DisplayMetrics outMetrics = null; getWindowManager().getDefaultDisplay().getMetrics(outMetrics);dentro de la Actividad. Luego, outMetrics.densityle dará el factor de escala del dispositivo actual, como se indica en los documentos
Mykhailo Gaidai
6

¿Qué tal usar esto en su lugar?

final DisplayMetrics displayMetrics=getResources().getDisplayMetrics();
final float screenWidthInDp=displayMetrics.widthPixels/displayMetrics.density;
final float screenHeightInDp=displayMetrics.heightPixels/displayMetrics.density;
desarrollador de Android
fuente
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
fuente
8
Considere dar alguna explicación
bigbounty
5

Respuesta en kotlin:

  context?.let {
        val displayMetrics = it.resources.displayMetrics
        val dpHeight = displayMetrics.heightPixels / displayMetrics.density
        val dpWidth = displayMetrics.widthPixels / displayMetrics.density
    }
Bolling
fuente
4

Simplificado para Kotlin:

val widthDp = resources.displayMetrics.run { widthPixels / density }
val heightDp = resources.displayMetrics.run { heightPixels / density }
TheYogi
fuente
2

Obtenga el ancho y la altura de la pantalla en términos de DP con una buena decoración:

Paso 1: crear interfaz

public interface ScreenInterface {

   float getWidth();

   float getHeight();

}

Paso 2: crear una clase de implementador

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

Paso 3: Obtenga ancho y alto en la actividad:

Screen screen = new Screen(this); // Setting Screen
screen.getWidth();
screen.getHeight();
Ali Azaz Alam
fuente
¿Devuelve esto alto y ancho en píxeles o dp?
Taslim Oseni
como se llama .density por eso te da en dp
Ali Azaz Alam
No creo que sea una buena idea agregar tonos de código a su aplicación para resolver una tarea simple
Ruslan Berozov
Señor, depende de usted implementar la clase o codificarla directamente. Desde la clase definida, puede extraer fácilmente el código para la implementación directa.
Ali Azaz Alam
0

Si solo quiere saber sobre el ancho de su pantalla, puede buscar el "ancho de pantalla más pequeño" en sus opciones de desarrollador. Incluso puedes editarlo.

canal matemático
fuente
0

Prueba esto:

Display display   = getWindowManager().getDefaultDisplay();
Point displaySize = new Point();
display.getSize(displaySize);
int width  = displaySize.x;
int height = displaySize.y;
Muhammed naseef Koppilakkal
fuente
-5

Su problema es lanzar el flotador a un int, perdiendo precisión. También debe multiplicar con el factor y no dividir.

Hacer esto:

int dp = (int)(pixel*getResources().getDisplayMetrics().density);
Dirk le Roux
fuente
3
Esta respuesta es incorrecta. De developer.android.com/guide/practices/… , Pixel = Dp * Density.
Vance-Turner el