2013-07-05 13 views
115

Come posso trovare le dimensioni dello schermo a livello di programmazione, nelle unità utilizzate dagli eventi di tocco e Visualizza misura/layout? In altre parole, voglio le coordinate nell'angolo in basso a destra dello schermo, nel sistema di coordinate utilizzato dagli eventi di tocco ' getRawX()/getRawY() e View.getLocationOnScreen().come ottenere le dimensioni dello schermo di Android a livello di programmazione, una volta per tutte?

Sono riluttanti a chiamare la manifestazione/unità di visualizzazione desiderata "pixel" in quanto evidentemente ci sono diversi concetti di "pixel" sul mio telefono in vari modi, e non sono aggiungendo fino a una storia coerente .

vedo questo è stato chiesto e ha risposto molto su StackOverflow e altrove, ma nessuno delle risposte effettivamente lavorare sul mio cellulare (Droid 4, 4.1.2 Android) in tutte le modalità:

(wow!)

Questo è per il codice libreria che ha bisogno di lavorare indipendentemente dal fatto che l'applicazione è in "modalità compatibilità schermo" (vale a dire targetSdkVersion < = 10 nel manifest) o non, e non voglio fare alcuna ipotesi sulla posizione, la dimensione o l'esistenza della barra di stato o qualsiasi altra decorazione dello schermo simile.


Ecco i fatti:

  1. il mio telefono (un droide 4 in esecuzione 4.1.2 Android) ha 540x960 pixel fisici, vale a dire poco colorati puntini luminosi.

  2. la dimensione dello schermo, nelle unità desiderate, dal guardare gli eventi di tocco e Visualizzare misure, è 360x640 quando l'applicazione è in modalità schermo compat, 540x960 quando l'applicazione non è in modalità schermo compat. Questi sono i numeri che ho bisogno di trovare a livello di programmazione, senza mucking con gli eventi touch o Views per trovarli, ma sto avendo estrema difficoltà a trovare qualsiasi API che restituirà questi numeri.

  3. visualizzazione e DisplayMetrics oggetti ottenuti in vari modi tutti sostengono la dimensione dello schermo è 540x960 "pixel" (siano essi in modo compat schermo o no). Per essere precisi, il seguente tutti dicono 540x960 tutto il tempo:. DisplayMetrics {larghezza, altezza} Pixel, Display.getSize(), Display.getRealSize(), Display.get {larghezza, altezza}(),

  4. Gli oggetti di configurazione ottenuti in vari modi tutti dicono schermo {Larghezza, Altezza} Dp = 360x614 (sia in modalità schermo compat o meno). Non credo che rappresenti l'intero schermo, poiché il rapporto di aspetto è sbagliato. (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 restituisce quella 640.

  5. DisplayMetrics ottenute in vari modi dicono la "densità" è 1.0f in modalità compat schermo, 1.5f quando non in modalità compat schermo.

  6. del attività getWindow().getAttributes().{width,height} non è utile in quanto contiene in genere MATCH_PARENT piuttosto che dimensioni effettive. Ma posso apparentemente ottenere la risposta desiderata di un'attività getWindow().getDecorView().getMeasured{Width,Height}() (che in realtà è sorprendente dal momento che della finestra della propria attività decorView non si guardare come sta prendendo l'intero schermo; sembra che sta prendendo lo schermo meno la barra di stato). Ma non voglio fare affidamento su questo perché se la finestra viene mai ridimensionata (viene visualizzata una tastiera morbida? Qualcuno chiama window.setAttributes()? o forse non sono in un'attività affatto), questo è chiaramente sta andando tutto storto.

Capisco la seguente formula dovrebbe contenere: pixel = dp * densità Questo sembra essere d'accordo con tutti i numeri riportati ((3), (4), (5) di cui sopra) quando non in modalità compatibilità schermo: 540x960 = 360x640 * 1,5 Ma in modalità compatibilità schermo non si sommano: 540x960! = 360x640 * 1 Quindi, qualcosa non funziona.

La spiegazione più semplice, credo, è che i metodi elencati (3) di cui sopra sono semplicemente dare la risposta sbagliata per "pixel" quando a schermo compat mode-- che è, sono stati destinati a tornare 360x640 "pixel", ma restituiscono erroneamente 540x960. Ma ci possono essere altri modi di guardarlo.

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

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

Esiste un modo migliore/più pulito per trovare la dimensione dello schermo ??

+24

+1 Grande domanda, e mostra un sacco di sforzo di ricerca. –

+1

@Don In [docs] (http://developer.android.com/guide/practices/screen-compat-mode.html), viene spiegato che la modalità di compatibilità smetterà di eseguire l'operazione "zoom su misura" nelle impostazioni precedenti. Tuttavia non è chiaramente spiegato "come funziona", dalle tue osservazioni, penso che semplicemente disattivano il ridimensionamento della densità, cioè: 1px diventa 1dp. È possibile che questo cambiamento riguardi solo la parte di rendering e 'DisplayMetrics' non viene mai aggiornato di tali modifiche. Ci sono problemi come [questo] (http://code.google.com/p/android/issues/detail?id=19921) già archiviati. –

+0

@ user117 - interessante. Bene * parte * di DisplayMetrics è stata aggiornata almeno - la densità è stata modificata in 1.0. Ma widthPixels/heightPixels non è stato modificato per corrispondere, a quanto pare. Riguardo al 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) –

risposta

7

Utilizzando DisplayMetrics è possibile ottenere altezza e larghezza dello schermo di qualsiasi dispositivo. ecco il codice.

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

Nella tua onCreate Metodo

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


height = metrics.heightPixels;  
width = metrics.widthPixels; 

Prova questa.

+1

no, come ho detto in (3), metriche. {Larghezza, altezza} Pixel * non * sta dando la risposta giusta quando si è in modalità compatibilità schermo. –

3

Se si utilizza API di livello 17 o superiore controllare il getRealMetrics e getRealSize in Display

Per livello di API 14,15 & 16 sguardo here

6

Nella tua # 6, si nota che il DecorView sembra fornire quello che vuoi, ma non pensi che sia realizzabile. Credo che sia il più vicino possibile. Secondo la documentazione per Window.getDecorView:

Recuperare l'alto livello vista arredamento finestra (che contiene la finestra cornice/decorazioni standard e contenuti del cliente all'interno di quella), che può essere aggiunto come una finestra per il window manager.

La barra di stato fa parte della decorazione della finestra menzionata qui. Tastiere software e altri overlay riceveranno la propria finestra, quindi non dovrebbero interferire con i valori pertinenti. È corretto che non siano precisamente le metriche del display, ma se l'applicazione è a schermo intero dovrebbe sempre essere la dimensione a schermo intero filtrata attraverso il traduttore di compatibilità. Altre applicazioni non avranno accesso allo Window della tua applicazione, quindi non è necessario preoccuparsi di altre app che cambiano gli attributi mentre non stai guardando.

Spero che questo aiuti.

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

Ora è in grado di misurare le dimensioni dello schermo in pixel che è un'unità di misura di meglio centimetro, perché tutti i pulsanti, textviews ecc .. sono misurati in questa unità. Quello che uso normalmente

+2

Secondo Op (punto # 3 in particolare), non sarebbe errato in modalità screen compat? – Tom

2

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 GENIOS, sapeva di programmazione smart phone di tanti anni fa: p

3

dovrei mettere questo come un commento, ma non ho il rappresentante per questo.
Questa potrebbe non essere una risposta completamente corretta ma ho ottenuto le mie dimensioni quando ho cambiato altezza e 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.

1

Io uso il metodo seguito 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; 
} 
+0

Questo metodo è obsoleto. Si prega di utilizzare il metodo displaymetrics. – Simon

0

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

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 del metodo creare output la larghezza e l'altezza come mostrato sotto

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

Download source code e testare sul proprio android studio

Problemi correlati