como obter o tamanho da tela do Android de forma programática, de uma vez por todas?


132

Como posso descobrir o tamanho da minha tela de forma programática, nas unidades usadas pelos eventos de toque e Exibir medição / layout? Em outras palavras, quero as coordenadas do canto inferior direito da tela, no sistema de coordenadas usado pelos eventos de toque ' getRawX()/getRawY()e View.getLocationOnScreen().

Eu hesito em chamar as unidades de evento / exibição desejadas como "pixels", pois, evidentemente, existem várias noções de "pixels" no meu telefone em vários modos, e elas não estão adicionando uma história consistente.

Vejo que isso foi solicitado e respondido muito no stackoverflow e em outros lugares, mas nenhuma das respostas realmente funciona no meu telefone (droid 4, android 4.1.2) em todos os modos:

(Uau!)

Isso é para código de biblioteca que precisa funcionar, independentemente de o aplicativo estar no "modo de compatibilidade de tela" (ou seja, targetSdkVersion <= 10 no manifesto) ou não, e também não quero fazer suposições sobre a posição, tamanho , ou existência da barra de status ou quaisquer outras decorações de tela semelhantes.


Aqui estão os fatos:

  1. meu telefone (um droid 4 com o Android 4.1.2) tem 540x960 pixels físicos, ou seja, pequenos pontos brilhantes coloridos.

  2. o tamanho da tela nas unidades desejadas, observando eventos de toque e Exibir medições, é 360x640 quando o aplicativo está no modo de compatibilidade de tela e 540x960 quando o aplicativo não está no modo de compatibilidade de tela. Esses são os números que preciso encontrar de forma programática, sem mexer com os eventos de toque ou as exibições para encontrá-los, mas estou com extrema dificuldade em encontrar qualquer API que retorne esses números.

  3. Os objetos Display e DisplayMetrics obtidos de várias maneiras afirmam que o tamanho da tela é de 540x960 "pixels" (no modo compatível com a tela ou não). Para ser específico, o seguinte diz 540x960 o tempo todo: DisplayMetrics. {Width, height} Pixels, Display.getSize (), Display.getRealSize (), Display.get {Width, Height} (),

  4. Objetos de configuração obtidos de várias maneiras, todos dizem tela {Largura, Altura} Dp = 360x614 (seja no modo de tela compatível ou não). Não acredito que isso represente a tela inteira, pois a proporção está errada. (Eu acho que é a tela inteira menos a barra de status; eu preciso da tela inteira.) Acho que é seguro dizer que a tela inteira tem 360 x 640 dp, embora eu não conheça nenhuma API que retorne essa 640.

  5. Os DisplayMetrics obtidos de várias maneiras dizem que a "densidade" é 1,0f quando está no modo de compatibilidade de tela, 1,5f quando não está no modo de compatibilidade de tela.

  6. A atividade getWindow().getAttributes().{width,height} não é útil, pois geralmente contém MATCH_PARENT tamanhos e não tamanhos reais. Mas aparentemente posso obter a resposta desejada de uma atividade getWindow().getDecorView().getMeasured{Width,Height}() (o que é realmente surpreendente, já que o decorView da janela da atividade não parece ocupar a tela inteira; parece estar ocupando a tela menos a barra de status). Mas não quero confiar nisso, porque se a janela for redimensionada (o teclado virtual aparecerá? Alguém chamando window.setAttributes ()? Ou talvez eu não esteja em nenhuma atividade), isso claramente será tudo errado.

Entendo que a seguinte fórmula deve conter: pixels = dp * densidade Isso parece concordar com todos os números relatados ((3), (4), (5) acima) quando não estiver no modo de compatibilidade de tela: 540x960 = 360x640 * 1,5 Mas, no modo de compatibilidade de tela, isso não ocorre: 540x960! = 360x640 * 1 Então, algo está errado.

A explicação mais simples, eu acho, é que os métodos listados em (3) acima estão simplesmente dando a resposta errada para "pixels" quando no modo de compatibilidade de tela - ou seja, eles pretendiam retornar "pixels" de 360x640, mas estão incorretamente retornando 540x960. Mas pode haver outras maneiras de ver isso.

De qualquer forma, obter os números desejados, independentemente do modo, das peças do quebra-cabeça acima, é certamente um quebra-cabeça complicado. Eu encontrei uma maneira que parece funcionar no meu telefone nos dois modos, mas é extremamente tortuosa e se baseia em duas suposições que ainda parecem bastante instáveis ​​(conforme descrito nos comentários de código abaixo).

Aqui está a minha receita:

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

Existe alguma maneira melhor / mais limpa de encontrar o tamanho da tela?


29
+1 Ótima pergunta, e mostra muito esforço de pesquisa.
Alex Gittemeier

1
@ Don Nos documentos , é explicado que o modo de compatibilidade deixará de fazer a operação "zoom to fit" em configurações mais antigas. No entanto, não está claramente explicado "como funciona". De suas observações, acho que elas simplesmente desativam o dimensionamento de densidade, ou seja: 1px torna-se 1dp. Pode ser que essa alteração esteja apenas na parte de renderização e DisplayMetricsnunca seja atualizada dessas alterações. Já existem problemas como esse .
SD

@ user117 - interessante. Bem, parte do DisplayMetrics foi atualizada pelo menos - a densidade foi alterada para 1,0. Mas widthPixels / heightPixels não foram alterados para corresponder, ao que parece. Quanto à questão citada, parece que o comportamento revertido para o comportamento 3.1 (ou seja, eu estou vendo heightPixels incluem a barra de status ... mas nas unidades erradas parece)
Don escotilha

@DonHatch Obrigado, gentilmente - eu estava realmente tentando elogiar uma pergunta pensativa que não é tão bem-vinda no StackExchange - observe como a pergunta sendo mais do que "real" não recebe nada nas respostas, falando sobre o (baixo ) qualidade do conhecimento do público sobre o tópico. Agora, eu posso ficar traumatizado por minhas próprias perguntas serem fechadas uma após a outra por serem "não reais", e o senso de humor pode estar falhando comigo, mas começa a parecer perguntas para as quais há respostas "agradáveis". o que tudo isso se torna aqui ... E, é claro, votei no seu :) #
mlvljr 27/12/2013

btw! aqui está algo parecido com minhas suspeitas: michael.richter.name/blogs/… (veja seu ponto (1), o que diz sobre respostas criadas rapidamente - na verdade, exatamente o caso com esse Q!). Feliz NY, de qualquer forma (a minha chega em 11 minutos)! :)
mlvljr

Respostas:


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

Agora você pode medir o tamanho da tela em pixels, que é uma unidade de medida melhor que centímetros, porque todos os botões, visualizações de texto etc. são medidos nesta unidade. Que o que eu uso normalmente


3
De acordo com o Op (ponto 3 especificamente), isso não seria incorreto no modo de compatibilidade de tela?
Tom

9

Ao usar o DisplayMetrics, você pode obter a altura e a largura da tela de qualquer dispositivo. Observe que a largura e a altura são sensíveis à rotação. aqui está o código

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

No seu método onCreate

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

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

Tente isso.


2
não, como eu disse em (3), métricas. {width, height} Pixels não está dando a resposta certa quando no modo de compatibilidade de tela.
quer

Também descobri: Parece métricas limitadas. A altura dos pixels pode dar a largura caso a tela seja girada e vice-versa!
JohnyTex 27/06/19

8

No seu número 6, observe que o DecorView parece fornecer o que você deseja, mas não o considera real. Eu acredito que é o mais próximo que você pode chegar. De acordo com a documentação para Window.getDecorView:

Recupere a exibição de decoração de janela de nível superior (contendo a moldura / decorações padrão da janela e o conteúdo do cliente dentro dela), que pode ser adicionado como uma janela ao gerenciador de janelas.

A barra de status faz parte da decoração da janela mencionada lá. Os teclados de software e outras sobreposições receberão sua própria janela; portanto, eles não devem interferir nos valores relevantes. É correto que não sejam precisamente as métricas de exibição, mas se o seu aplicativo estiver em tela cheia, ele deverá sempre ter o tamanho de tela inteira filtrado pelo tradutor de compatibilidade. Outros aplicativos não terão acesso ao seu aplicativo Window, portanto, não há necessidade de se preocupar com outro aplicativo alterando os atributos enquanto você não estiver procurando.

Espero que ajude.


5

Devo colocar isso como um comentário, mas não tenho o representante para isso.
Esta pode não ser uma resposta totalmente correta, mas obtive minhas dimensões quando alterei a altura e a largura no método DisplayMetrics.

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

como eu disse, isso pode não estar correto, mas não sei por que, mas funcionou para mim.


Isso ocorre porque sua tela girou, acredito.
JohnyTex 27/06/19

Não era confiar em mim.
abhyudayasrinet

3

Se você estiver usando a API nível 17 ou superior, consulte getRealMetrics e getRealSize no Display

Para os níveis 14,15 e 16 da API, veja aqui


3

Eu usei o teorema de Pitágoras para encontrar o tamanho diagonal da tela do telefone / tablet Android, o mesmo princípio pode ser aplicado à tela do iPhone ou do 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

Pitágoras deve ter sido um gênio, ele conhecia a programação de smartphones há muitos anos: p


1

Eu uso o método abaixo para obter a largura do 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;
}

Este método está obsoleto. Por favor, use o método displaymetrics.
7776 Simon

0

Eu acho que essa função irá ajudá-lo a simplesmente obter a largura e a altura do tamanho da tela do seu Android. A função retorna a largura e a altura como uma matriz de números inteiros, como mostrado abaixo

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 no seu método create crie sua largura e altura, como mostrado abaixo

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

Baixe o código-fonte e teste-o no seu estúdio android


0

Isso funciona para mim:

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

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

Usei isso para atualizar a largura dos meus itens em uma visualização horizontal do reciclador. (De acordo com minha exigência) Espero que ajude alguém!


-1

Para esta solução no Kotlin , tente o seguinte:

private fun yourFunction(){
   val metrics = DisplayMetrics()
   windowManager.defaultDisplay.getMetrics(metrics)
   val width = metrics.widthPixels
   val height = metrics.heightPixels
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.