come ottenere le dimensioni dello schermo Android a livello di codice, una volta per tutte?


132

Come posso scoprire la mia dimensione dello schermo a livello di codice, nelle unità utilizzate dagli eventi touch e Visualizza misurazione / layout? In altre parole, voglio le coordinate dell'angolo in basso a destra dello schermo, nel sistema di coordinate utilizzato dagli eventi touch ' getRawX()/getRawY()e View.getLocationOnScreen().

Sono titubante nel chiamare le unità di evento / visualizzazione desiderate "pixel" poiché evidentemente ci sono diverse nozioni di "pixel" sul mio telefono in varie modalità e non si aggiungono a una storia coerente.

Vedo che è stato chiesto e risposto molto su StackOverflow e altrove, ma nessuna delle risposte funziona sul mio telefono (Droid 4, Android 4.1.2) in tutte le modalità:

(Wow!)

Questo è per il codice della libreria che deve funzionare indipendentemente dal fatto che l'app sia in "modalità compatibilità schermo" (ovvero targetSdkVersion <= 10 nel manifest) o no, e inoltre non voglio fare alcuna ipotesi sulla posizione, la dimensione o l'esistenza della barra di stato o di qualsiasi altra decorazione dello schermo simile.


Ecco i fatti:

  1. il mio telefono (un droide 4 con Android 4.1.2) ha 540x960 pixel fisici, cioè piccoli punti luminosi colorati.

  2. la dimensione dello schermo nelle unità desiderate, dalla visualizzazione degli eventi tattili e dalla visualizzazione delle misurazioni, è 360x640 quando l'app è in modalità compatibilità schermo, 540x960 quando l'app non è in modalità compatibilità schermo. Questi sono i numeri che devo trovare a livello di codice, senza confondere eventi tattili o visualizzazioni per trovarli, ma ho estrema difficoltà a trovare qualsiasi API che restituisca questi numeri.

  3. Gli oggetti Display e DisplayMetrics ottenuti in vari modi sostengono che le dimensioni dello schermo sono 540x960 "pixel" (indipendentemente dal fatto che siano compatibili o meno). Per essere precisi, tutti i seguenti dicono 540x960 per tutto il tempo: DisplayMetrics. {Larghezza, altezza} Pixel, Display.getSize (), Display.getRealSize (), Display.get {Larghezza, Altezza} (),

  4. Gli oggetti di configurazione ottenuti in vari modi dicono tutti schermo {Larghezza, Altezza} Dp = 360x614 (sia in modalità schermo compatibile o meno). Non credo che rappresenti l'intero schermo, poiché le proporzioni sono errate. (Penso che sia l'intero schermo meno la barra di stato; ho bisogno di tutto lo schermo.) Penso che sia sicuro dire che l'intero schermo è 360x640 dp, anche se non conosco alcuna API che restituisca quel 640.

  5. DisplayMetrics ottenuto in vari modi afferma che la "densità" è 1.0f quando è in modalità compatibilità schermo, 1.5f quando non è in modalità compatibilità schermo.

  6. L'attività getWindow().getAttributes().{width,height} non è utile poiché contiene in genere MATCH_PARENT anziché dimensioni effettive. Ma a quanto pare riesco a ottenere la risposta desiderata da un'attività getWindow().getDecorView().getMeasured{Width,Height}() (il che è in realtà sorprendente poiché il decorView della finestra dell'attività non sembra occupare l'intero schermo; sembra che occupi lo schermo meno la barra di stato). Ma non voglio fare affidamento su questo perché se la finestra viene mai ridimensionata (appare la tastiera virtuale? Qualcuno chiama window.setAttributes ()? O forse non sono affatto in un'attività), questo sarà chiaramente tutto sbagliato.

Capisco che la seguente formula dovrebbe contenere: pixel = densità dp * che sembra concordare con tutti i numeri riportati ((3), (4), (5) sopra) quando non è in modalità compatibilità schermo: 540x960 = 360x640 * 1.5 Ma nella modalità di compatibilità dello schermo non si somma: 540x960! = 360x640 * 1 Quindi, qualcosa non va.

La spiegazione più semplice, penso, è che i metodi elencati in (3) sopra stanno semplicemente dando la risposta sbagliata per "pixel" quando in modalità compatibilità schermo - cioè, erano destinati a restituire "pixel" 360x640 ma sono erroneamente restituendo invece 540x960. Ma potrebbero esserci altri modi di vederlo.

In ogni caso, ottenere i numeri desiderati indipendentemente dalla modalità, dai pezzi del puzzle sopra, è sicuramente un puzzle complicato. Ho trovato un modo che sembra funzionare sul mio telefono in entrambe le modalità, ma è estremamente complicato e si basa su due ipotesi che sembrano ancora piuttosto traballanti (come descritto nei commenti sul codice di seguito).

Ecco la mia ricetta:

/** get screen size in "pixels", i.e. touchevent/view units.
* on my droid 4, this is 360x640 or 540x960
* depending on whether the app is in screen compatibility mode
* (i.e. targetSdkVersion<=10 in the manifest) or not. */
public void getScreenSizePixels(int widthHeightInPixels[/*2*/])
{
    Resources resources = getResources();
    Configuration config = resources.getConfiguration();
    DisplayMetrics dm = resources.getDisplayMetrics();
    // Note, screenHeightDp isn't reliable
    // (it seems to be too small by the height of the status bar),
    // but we assume screenWidthDp is reliable.
    // Note also, dm.widthPixels,dm.heightPixels aren't reliably pixels
    // (they get confused when in screen compatibility mode, it seems),
    // but we assume their ratio is correct.
    double screenWidthInPixels = (double)config.screenWidthDp * dm.density;
    double screenHeightInPixels = screenWidthInPixels * dm.heightPixels / dm.widthPixels;
    widthHeightInPixels[0] = (int)(screenWidthInPixels + .5);
    widthHeightInPixels[1] = (int)(screenHeightInPixels + .5);
}

C'è un modo migliore / più pulito per trovare le dimensioni dello schermo ??


29
+1 Ottima domanda, e mostra molti sforzi di ricerca.
Alex Gittemeier,

1
@Don Nei documenti , viene spiegato che la modalità di compatibilità smetterà di eseguire operazioni di "zoom per adattarsi" su configurazioni meno recenti. Tuttavia non è chiaramente spiegato "come funziona", dalle tue osservazioni, penso che semplicemente disattivino il ridimensionamento della densità, ovvero: 1px diventa 1dp. È possibile che questa modifica sia solo nella parte di rendering e DisplayMetricsnon venga mai aggiornata da tali modifiche. Ci sono problemi come questo già archiviati.
SD

@utente117 - interessante. Bene, almeno una parte di DisplayMetrics è stata aggiornata: la densità è stata modificata in 1.0. A quanto pare, larghezzaPixel / altezzaPixel non sono stati modificati in modo da corrispondere. Per quanto riguarda il problema citato, sembra che il comportamento sia tornato al comportamento 3.1 (cioè sto vedendo heightPixels include la barra di stato ... ma nelle unità sbagliate sembra)
Don Hatch

@DonHatch Grazie, gentilmente - In realtà stavo cercando di elogiare una domanda ponderata di sorta stranamente non così benvenuta su StackExchange - nota come la domanda sia più che "reale" non ottiene nulla nelle risposte, parlando del (basso ) qualità delle conoscenze del pubblico sull'argomento. Ora, potrei essere traumatizzato dal fatto che le mie stesse domande siano chiuse una dopo l'altra per essere "non reale", e il senso dell'umorismo potrebbe non riuscire a farmi, ma inizia a sembrare domande per le quali ci sono risposte "piacevoli" alla risposta sono davvero cosa succede qui ... E ovviamente ho votato il tuo :)
mlvljr,

btw! ecco qualcosa sulla falsariga dei miei sospetti: michael.richter.name/blogs/… (esp. vedi il suo punto (1), quello sulle risposte rapidamente elaborate - in realtà proprio il caso con questa Q!). Buona New York, comunque (la mia arriva in 11 minuti)! :)
mlvljr

Risposte:


41
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;

Ora puoi misurare le dimensioni dello schermo in pixel, che è un'unità di misura migliore del centimetro perché tutti i pulsanti, le visualizzazioni di testo ecc. Sono misurati in questa unità. Quello che uso normalmente


3
Secondo l'Op (in particolare il punto 3), ciò non sarebbe errato in modalità compatibilità schermo?
Tom,

9

Utilizzando DisplayMetrics è possibile ottenere l'altezza e la larghezza dello schermo di qualsiasi dispositivo. Si noti che larghezza e altezza sono sensibili alla rotazione. ecco il codice.

DisplayMetrics metrics; 
int width = 0, height = 0;

Nel tuo metodo onCreate

 metrics = new DisplayMetrics();        
 getWindowManager().getDefaultDisplay().getMetrics(metrics);

 height = Math.min(metrics.widthPixels, metrics.heightPixels); //height
 width = Math.max(metrics.widthPixels, metrics.heightPixels); //width

Prova questo.


2
no, come ho detto in (3), metriche. {larghezza, altezza} I pixel non danno la risposta giusta in modalità compatibilità schermo.
Don Hatch,

Inoltre ho scoperto: sembra lite metrics.heightPixels potrebbe dare la larghezza nel caso in cui lo schermo venga ruotato e viceversa!
JohnyTex,

8

Nel tuo numero 6, noti che DecorView sembra fornire ciò che desideri, ma non pensi che sia realizzabile. Credo che sia il più vicino possibile. Secondo la documentazione per Window.getDecorView:

Recupera la vista della decorazione della finestra di livello superiore (contenente la cornice / le decorazioni standard della finestra e il contenuto del client all'interno di essa), che può essere aggiunta come finestra al gestore delle finestre.

La barra di stato fa parte della decorazione della finestra qui menzionata. Le tastiere del software e gli altri overlay riceveranno la propria finestra, quindi non dovrebbero interferire con i valori pertinenti. È corretto che non siano esattamente le metriche di visualizzazione, ma se l'applicazione è a schermo intero dovrebbe sempre essere la dimensione dello schermo intero filtrata attraverso il traduttore di compatibilità. Altre applicazioni non avranno accesso a quelle della tua applicazioneWindow , quindi non c'è bisogno di preoccuparsi che qualche altra app cambi gli attributi mentre non stai guardando.

Spero che aiuti.


5

Dovrei mettere questo come un commento, ma non ho il rappresentante per quello.
Questa potrebbe non essere una risposta totalmente corretta ma ho ottenuto le mie dimensioni quando ho cambiato l'altezza e la larghezza nel metodo DisplayMetrics.

    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);   
    width = metrics.heightPixels;
    height = metrics.widthPixels;

come ho detto questo potrebbe non essere corretto ma non so perché ma ha funzionato per me.


Questo perché il tuo schermo è ruotato credo.
JohnyTex,

Non mi fidavo di me.
abhyudayasrinet,

3

Se stai usando un livello di API 17 o superiore, controlla getRealMetrics e getRealSize in Display

Per api livello 14,15 e 16 guarda qui


3

Ho usato il teorema di Pitagora per trovare le dimensioni diagonali dello schermo del telefono / tablet Android, lo stesso principio può essere applicato allo schermo di iPhone o Blackberry.

DisplayMetrics met = new DisplayMetrics();                
this.getWindowManager().getDefaultDisplay().getMetrics(met);// get display metrics object
String strSize = 
new DecimalFormat("##.##").format(Math.sqrt(((met.widthPixels / met.xdpi) *
(met.widthPixels / met.xdpi)) +
((met.heightPixels / met.ydpi) * (met.heightPixels / met.ydpi))));
// using Dots per inches with width and height

Pitagora deve essere stato un genio, conosceva la programmazione degli smartphone così tanti anni fa: p


1

Uso il metodo seguente per ottenere la larghezza del dispositivo:

public static int getDeviceWidth(Context context){
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    int width=display.getWidth();
    return width;
}

Questo metodo è obsoleto. Si prega di utilizzare il metodo displaymetrics.
Simone,

0

Penso che questa funzione ti aiuterà semplicemente a ottenere la larghezza e l'altezza delle dimensioni dello schermo Android. La funzione restituisce la larghezza e l'altezza come una matrice di numeri interi come mostrato di seguito

private int[] getScreenSIze(){
        DisplayMetrics displaymetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        int h = displaymetrics.heightPixels;
        int w = displaymetrics.widthPixels;

        int[] size={w,h};
        return size;

    }

e sul tuo metodo di creazione output la tua larghezza e altezza, come mostrato di seguito

 int[] screenSize= getScreenSIze();
        int width=screenSize[0];
        int height=screenSize[1];
        screenSizes.setText("Phone Screen sizes \n\n  width = "+width+" \n Height = "+height);

Scarica il codice sorgente e testalo sul tuo Android Studio


0

Questo funziona per me:

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

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

L'ho usato per aggiornare la larghezza dei miei oggetti in una vista di riciclaggio orizzontale. (Secondo il mio requisito) Spero che aiuti qualcuno!


-1

Per questa soluzione in Kotlin , prova questo:

private fun yourFunction(){
   val metrics = DisplayMetrics()
   windowManager.defaultDisplay.getMetrics(metrics)
   val width = metrics.widthPixels
   val height = metrics.heightPixels
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.