Detectar tablets de 7 e 10 polegadas de maneira programática

93

Existe uma maneira de descobrir programaticamente se o dispositivo em que o aplicativo está instalado é um tablet de 7 ou 10 polegadas?

Novato
fonte
Por exemplo: layout-sw600dp procura o menor tamanho de largura de 600dp.
Rookie de
Eu entendo isso, mas o que você está procurando de maneira programática?
Geobits
Eu preciso buscar esses dispositivos programaticamente .. como existem algumas propriedades que não posso definir em xml .. essas propriedades são definidas no próprio código .. então, se eu simplesmente colocar o código, ele se aplicará a todos os dispositivos .. mas Eu não quero isso ..
Rookie
@Raghav você tentou com a matriz de exibição para obter o tamanho da tela e então você pode comparar. Embora não seja uma maneira limpa, mas você pode usar.
PiyushMishra
Você pode obter as dimensões da tela e trabalhar a partir daí ... stackoverflow.com/questions/1016896/…
Raj

Respostas:

234

Você pode usar o DisplayMetricspara obter um monte de informações sobre a tela em que seu aplicativo está sendo executado.

Primeiro, criamos um DisplayMetricsobjeto metrics:

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

A partir disso, podemos obter as informações necessárias para dimensionar a tela:

int widthPixels = metrics.widthPixels;
int heightPixels = metrics.heightPixels;

Isso retornará o valor absoluto da largura e da altura em pixels, portanto, 1280x720 para o Galaxy SIII, o Galaxy Nexus etc.

Isso geralmente não é útil por si só, pois quando estamos trabalhando em dispositivos Android, geralmente preferimos trabalhar em pixels independentes de densidade.

Você obtém o densityda tela usando metricsnovamente, na forma de um fator de escala para o dispositivo, que é baseado nos Recursos de Design do Android para mdpi, hdpietc. Escalas DPI

float scaleFactor = metrics.density;

A partir desse resultado, podemos calcular a quantidade de pixels independentes de densidade que existem para uma certa altura ou largura.

float widthDp = widthPixels / scaleFactor
float heightDp = heightPixels / scaleFactor

O resultado obtido ajudará a decidir com que tipo de tela você está trabalhando em conjunto com os exemplos de configuração do Android , que fornecem o dp relativo para cada tamanho de tela:

  • 320 dp: uma tela de telefone típica (240 x 320 ldpi, 320 x 480 mdpi, 480 x 800 hdpi etc.).
  • 480dp: um tablet interpolador como o Streak (480x800 mdpi).
  • 600 dp: um tablet de 7 "(600 x 1024 mdpi).
  • 720 dp: um tablet de 10 "(720 x 1280 mdpi, 800 x 1280 mdpi etc.).

Usando as informações acima, sabemos que se a menor largura do dispositivo for maior que 600dp, o dispositivo é um tablet de 7 ", se for maior que 720dp, o dispositivo é um tablet de 10".

Podemos calcular a menor largura usando a minfunção de Mathclasse, passando o heightDpe o widthDppara retornar o smallestWidth.

float smallestWidth = Math.min(widthDp, heightDp);

if (smallestWidth > 720) {
    //Device is a 10" tablet
} 
else if (smallestWidth > 600) {
    //Device is a 7" tablet
}

No entanto, isso nem sempre fornece uma correspondência exata, especialmente ao trabalhar com tablets obscuros que podem estar apresentando sua densidade como hdpi quando não estão, ou que podem ter apenas 800 x 480 pixels, mas ainda estar em uma tela de 7 " .

Além desses métodos, se você precisar saber as dimensões exatas de um dispositivo em polegadas, poderá calcular isso também, usando o metricsmétodo de quantos pixels existem por polegada da tela.

float widthDpi = metrics.xdpi;
float heightDpi = metrics.ydpi;

Você pode usar o conhecimento de quantos pixels existem em cada polegada do dispositivo e a quantidade de pixels no total para descobrir quantas polegadas o dispositivo tem.

float widthInches = widthPixels / widthDpi;
float heightInches = heightPixels / heightDpi;

Isso retornará a altura e a largura do dispositivo em polegadas. Isso nem sempre é útil para determinar que tipo de dispositivo é, como o tamanho anunciado de um dispositivo é a diagonal, tudo o que temos é a altura e a largura.

No entanto, também sabemos que, dada a altura de um triângulo e a largura, podemos usar o teorema de Pitágoras para calcular o comprimento da hipotenusa (neste caso, o tamanho da diagonal da tela).

//a² + b² = c²

//The size of the diagonal in inches is equal to the square root of the height in inches squared plus the width in inches squared.
double diagonalInches = Math.sqrt(
    (widthInches * widthInches) 
    + (heightInches * heightInches));

A partir disso, podemos descobrir se o dispositivo é um tablet ou não:

if (diagonalInches >= 10) {
    //Device is a 10" tablet
} 
else if (diagonalInches >= 7) {
    //Device is a 7" tablet
}

E é assim que você calcula com que tipo de dispositivo está trabalhando.

Sean O'Toole
fonte
3
Dicas excelentes, Sean. Eu costumava verificar com px para tablets, mas em alguns casos há problemas (Galaxy 3, 4, Note, tem px igual ou mais que o Nexus 7). Agora também posso verificar se há polegadas. Aqui está uma lista de muitas especificações de tela de dispositivos populares: en.wikipedia.org/wiki/List_of_displays_by_pixel_density
Pelanes
8
Não use xdpi ou ydpi. Eles são opcionais e serão definidos pelo fabricante, não calculados. Freqüentemente, eles não são usados ​​ou são imprecisos.
sturrockad
2
Usando seu método para obter a largura em dpi, obtenho resultados diferentes dependendo da orientação. por exemplo, para o Nexus 7: RETRATO: smallestWidth = 600,9; PAISAGEM: smallestWidth = 552,8; Qual é o motivo disso?
Christopher Masser
3
A lógica if (smallestWidth > 600) { /* 7" */ } else if (smallestWidth > 720) { /* 10" */ }é falha: o tablet de 10 "é reconhecido como 7". Tomei a liberdade de consertar isso.
Jonik
21
Por fim, aceitei a respostaresources.getConfiguration().smallestScreenWidthDp de DeeV, que é o único método que fornece o mesmo valor tanto em retrato quanto em paisagem no meu Nexus 7 (600dp). Foi adicionado na API de nível 13.
Jonik
32

Não há nada que diga 7"ou 10"AFAIK. Existem aproximadamente duas maneiras de obter as dimensões da tela que o sistema usa ao decodificar bitmaps e outros enfeites. Ambos são encontrados no Resourcesobjeto do aplicativo encontrado noContext .

O primeiro é o Configurationobjeto que pode ser obtido por getContext().getResources().getConfiguration(). Nele você tem:

Configuration#densityDpi - A densidade da tela de destino sendo renderizada, correspondendo ao qualificador de recurso de densidade.

Configuration#screenHeightDp - A altura atual do espaço de tela disponível, em unidades de dp, correspondendo ao qualificador de recurso de altura da tela.

Configuration#screenWidthDp - A largura atual do espaço de tela disponível, em unidades de dp, correspondendo ao qualificador de recurso de largura de tela.

Configuration#smallestScreenWidthDp - O menor tamanho de tela que um aplicativo verá em operação normal, correspondendo ao qualificador de recurso de menor largura de tela.

Com isso, você pode muito bem usar as diretrizes de tela para descobrir se o seu dispositivo está puxando a partir das respectivas pastas de recursos especializados ( hdpi, xhdpi, large, xlarge, etc.).

Lembre-se, estes são alguns dos baldes:

  • telas xlarge têm pelo menos 960 dp x 720 dp
  • telas grandes têm pelo menos 640 dp x 480 dp
  • telas normais são de pelo menos 470 dp x 320 dp
  • telas pequenas têm pelo menos 426 dp x 320 dp

  • 320 dp: uma tela de telefone típica (240 x 320 ldpi, 320 x 480 mdpi, 480 x 800 hdpi etc.).

  • 480dp: um tablet interpolador como o Streak (480x800 mdpi).
  • 600 dp: um tablet de 7 "(600 x 1024 mdpi).
  • 720 dp: um tablet de 10 "(720 x 1280 mdpi, 800 x 1280 mdpi etc.).

Mais informações

O segundo é o DisplayMetricsobjeto obtido por getContext().getResources().getDisplayMetrics(). Nisso você tem:

DisplayMetrics#density - A densidade lógica da tela.

DisplayMetrics#densityDpi - A densidade da tela expressa em pontos por polegada.

DisplayMetrics#heightPixels - A altura absoluta da tela em pixels.

DisplayMetrics#widthPixels - A largura absoluta da tela em pixels.

DisplayMetrics#xdpi - Os pixels físicos exatos por polegada da tela na dimensão X.

DisplayMetrics#ydpi - Os pixels físicos exatos por polegada da tela na dimensão Y.

Isso é útil se você precisar da contagem exata de pixels da tela em vez de densidade. No entanto, é importante notar que são todos os pixels da tela. Não apenas aqueles disponíveis para você.

DeeV
fonte
4
+1, estou obtendo os melhores resultados com smallestScreenWidthDp. Ao contrário das outras soluções, dá o mesmo valor no meu Nexus 7 (600dp), independentemente da orientação . Como bônus, é também o código mais simples!
Jonik
1
Acho que esta continua a ser a melhor maneira porque deve corresponder à notação sw ??? dp nos caminhos de recursos. A consistência é importante.
lilbyrdie
13

coloque este método em onResume () e pode verificar.

public double tabletSize() {

     double size = 0;
        try {

            // Compute screen size

            DisplayMetrics dm = context.getResources().getDisplayMetrics();

            float screenWidth  = dm.widthPixels / dm.xdpi;

            float screenHeight = dm.heightPixels / dm.ydpi;

            size = Math.sqrt(Math.pow(screenWidth, 2) +

                                 Math.pow(screenHeight, 2));

        } catch(Throwable t) {

        }

        return size;

    }

geralmente os comprimidos começam após o tamanho de 6 polegadas.

PiyushMishra
fonte
8

Isso nem sempre funciona ao alternar entre retrato e paisagem.

Se você tem como meta a API de nível 13+, é fácil conforme descrito acima - use Configuration.smallestScreenWidthDp e teste de acordo:

resources.getConfiguration().smallestScreenWidthDp

Caso contrário, se você puder pagar por isso, use o método a seguir, que é uma abordagem muito precisa para detectar 600 dp (como 6 ") vs. 720 dp (como 10"), permitindo que o sistema diga a você:

1) Adicione ao layout-sw600dp e layout-sw720dp (e, se aplicável, sua paisagem) uma visualização invisível com o ID adequado, por exemplo:

Para 720, no layout-sw720dp:

<View android:id="@+id/sw720" android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone"/>

Para 600, no layout-sw600dp:

<View android:id="@+id/sw600" android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone"/>

2) Em seguida, no código, por exemplo, a Atividade, teste de acordo:

private void showFragment() {
    View v600 = (View) findViewById(R.id.sw600);
    View v720 = (View) findViewById(R.id.sw720);
    if (v600 != null || v720 !=null)
        albumFrag = AlbumGridViewFragment.newInstance(albumRefresh);
    else
        albumFrag = AlbumListViewFragment.newInstance(albumRefresh);
    getSupportFragmentManager()
        .beginTransaction()
        .replace(R.id.view_container, albumFrag)
        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
        .commit();
}
CEO
fonte
4
Você não precisa criar um layout separado, eu acredito que você pode apenas ter strings.xml separadas com base no tamanho, tendo diferentes pastas de valores, como valores-sw600dp, etc. Tenha uma string definida <string name = 'screensize' > 600dp </string> na pasta sw600dp, etc. Nem precisa ser uma string, pode estar em ints.xml ou dimens.xml.
ajacian81
7

Ótima informação, exatamente o que eu estava procurando! No entanto, depois de tentar fazer isso, descobri que, ao usar as métricas mencionadas aqui, o Nexus 7 (modelo de 2012) reporta ter dimensões de 1280x736. Eu também tenho um Motorola Xoom executando Jelly Bean e ele informa incorretamente uma resolução de 1280x752. Me deparei com este post aqui que confirma isso. Basicamente, no ICS / JB os cálculos usando as métricas mencionadas acima parecem excluir as dimensões da Barra de Navegação. Mais algumas pesquisas me levaram à resposta de Frank Nguyen aqui, que usa métodos diferentes que fornecerão as dimensões de pixel brutas (ou reais) da tela. Meu teste inicial mostrou que o código a seguir de Frank relata corretamente as dimensões do Nexus 7 (modelo 2012 executando JB) e meu Motorola Xoom executando JB:

int width = 0, height = 0;
final DisplayMetrics metrics = new DisplayMetrics();
Display display = getWindowManager().getDefaultDisplay();
Method mGetRawH = null, mGetRawW = null;

try {
    // For JellyBeans and onward
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
        display.getRealMetrics(metrics);

        width = metrics.widthPixels;
        height = metrics.heightPixels;
    } else {
        mGetRawH = Display.class.getMethod("getRawHeight");
        mGetRawW = Display.class.getMethod("getRawWidth");

        try {
            width = (Integer) mGetRawW.invoke(display);
            height = (Integer) mGetRawH.invoke(display);
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
} catch (NoSuchMethodException e3) {
    e3.printStackTrace();
}
Jason
fonte
3

Tenho dois dispositivos Android com a mesma resolução

Dispositivo1 -> resolução 480x800 tamanho de tela diagonal -> 4,7 polegadas

Dispositivo2 -> resolução 480x800 tamanho de tela diagonal -> 4,0 polegadas

Ele dá ao dispositivo um tamanho de tela diagonal -> 5,8

a solução para o seu problema é ..

DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width=dm.widthPixels;
int height=dm.heightPixels;
int dens=dm.densityDpi;
double wi=(double)width/(double)dens;
double hi=(double)height/(double)dens;
double x = Math.pow(wi,2);
double y = Math.pow(hi,2);
double screenInches = Math.sqrt(x+y);

veja detalhes aqui ..

AndroidGeek
fonte
2

Eles maneira que o Android especifica tamanhos de tela é através de quatro tamanhos generalizadas: pequeno , normais , grande e xlarge .

Embora a documentação do Android afirme que os grupos de tamanho estão obsoletos

... esses grupos de tamanho foram descontinuados em favor de uma nova técnica para gerenciar tamanhos de tela com base na largura de tela disponível. Se você estiver desenvolvendo para Android 3.2 e superior, consulte [Declarando layouts de tablet para Android 3.2] (hdpi (alta) ~ 240dpi) para obter mais informações.

Geralmente, o qualificador de tamanho grande especifica um tablet de 7 ". E um qualificador de tamanho xlarge especifica um tablet de 10":

insira a descrição da imagem aqui

O bom sobre o acionamento no qualificador de tamanho é que você pode garantir que seus ativos e código estão de acordo sobre qual ativo usar ou caminho de código para ativar.

Para recuperar o qualificador de tamanho no código, faça as seguintes chamadas:

int sizeLarge = SCREENLAYOUT_SIZE_LARGE // For 7" tablet
boolean is7InchTablet = context.getResources().getConfiguration()
    .isLayoutSizeAtLeast(sizeLarge);

int sizeXLarge = SCREENLAYOUT_SIZE_XLARGE // For 10" tablet
boolean is10InchTablet = context.getResources().getConfiguration()
    .isLayoutSizeAtLeast(sizeXLarge);
Benjamin
fonte
2

Você pode usar o método abaixo para obter o tamanho da tela em polegadas, baseando-se nisso simplesmente você pode verificar em qual tablet ou telefone o dispositivo está.

private static double checkDimension(Context context) {

    WindowManager windowManager = ((Activity)context).getWindowManager();
    Display display = windowManager.getDefaultDisplay();
    DisplayMetrics displayMetrics = new DisplayMetrics();
    display.getMetrics(displayMetrics);

    // since SDK_INT = 1;
    int mWidthPixels = displayMetrics.widthPixels;
    int mHeightPixels = displayMetrics.heightPixels;

    // includes window decorations (statusbar bar/menu bar)
    try
    {
        Point realSize = new Point();
        Display.class.getMethod("getRealSize", Point.class).invoke(display, realSize);
        mWidthPixels = realSize.x;
        mHeightPixels = realSize.y;
    }
    catch (Exception ignored) {}

    DisplayMetrics dm = new DisplayMetrics();
    windowManager.getDefaultDisplay().getMetrics(dm);
    double x = Math.pow(mWidthPixels/dm.xdpi,2);
    double y = Math.pow(mHeightPixels/dm.ydpi,2);
    double screenInches = Math.sqrt(x+y);
    Log.d("debug","Screen inches : " + screenInches);
    return screenInches;
}
Ashish Rajvanshi
fonte
2

Eu estava armazenando um valor na pasta de valores que me dá uma tela de 7 polegadas ou 10 inc, mas podemos fazer isso para qualquer dispositivo usando a pasta de valores.

como criar uma pasta de 2 valores diferentes para 2 dispositivos diferentes. Mas isso depende do requisito.

sharma_kunal
fonte
1

Você terá que fazer alguns cálculos usando os dados fornecidos pela classe DisplayMetrics .

Você tem heightPixel e widthPixels (a resolução da tela em pixels)

Você precisa da diagonal, pois o 'tamanho da tela em polegadas' sempre descreve o comprimento diagonal. Você pode obter a diagonal da tela em pixels (usando o pythagore)

diagonalPixel = √ (heightPixel² + widthPixels²)

então você pode converter o valor do pixel em polegadas, graças ao valor de densidade DPI:

inchDiag = diagonalPixel / densidadeDPI.

Espero não ter cometido erros aqui, esteja ciente de que os valores que você obtém da classe DisplayMetrics são fornecidos pelo construtor, parece (em casos muito raros) que eles não estão bem definidos de acordo com o material físico ...

Isso fornecerá o tamanho físico da tela, mas provavelmente não é a melhor maneira de gerenciar vários layouts. Mais sobre este assunto

Guian
fonte
1

Outra maneira:

  • Crie mais 2 pastas: valores-grande + valores-xlarge

  • Coloque: <string name="screentype">LARGE</string>na pasta values-large (strings.xml)

  • Coloque: <string name="screentype">XLARGE</string>na pasta values-xlarge (strings.xml)

  • Em código:

    String mType = getString (R.string.screentype);

    if (mType! = null && mType.equals ("LARGE") {

    // de 4 ~ 7 polegadas

    } else if (mType! = null && mType.equals ("XLARGE") {

    // de 7 a 10 polegadas

    }

Frank Nguyen
fonte
1

Voila! 😀 Isso é tudo que você precisa para distinguir tablets de telefones

1. Função auxiliar para obter a largura da tela:

private float getScreenWidth() {
    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);
    return Math.min(metrics.widthPixels, metrics.heightPixels) / metrics.density;
}

2. Função para descobrir se um dispositivo é um tablet

boolean isTablet() {
    return getScreenWidth() >= 600;
}

3. Finalmente, se você deseja realizar diferentes operações para diferentes tamanhos de dispositivos:

boolean is7InchTablet() {
    return getScreenWidth() >= 600 && getScreenWidth() < 720;
}

boolean is10InchTablet() {
    return getScreenWidth() >= 720;
}
Sagar
fonte
0

Aqui estão algumas extensões úteis do kotlin:


    fun DisplayMetrics.isTablet(): Boolean {
        return screenWith() >= 600
    }

    fun DisplayMetrics.is7InchTablet(): Boolean {
        return screenWith() >= 600 && screenWith() < 720
    }

    fun DisplayMetrics.is10InchTablet(): Boolean {
        return screenWith() >= 720
    }

    fun DisplayMetrics.screenWith(): Float {
        return widthPixels.coerceAtMost(heightPixels) / density
    }
Danimado
fonte
Isso funciona! Mas você deve usar DisplayMetrics adequado, por exemplo de Resourcesem Context: resources.displayMetrics.isTablet() ou de WindowManagerqual armazenado em Activity: val displayMetrics = DisplayMetrics() windowManager.defaultDisplay.getMetrics(displayMetrics) displayMetrics.isTablet()
Akbolat SSS