Android e configuração de largura e altura programaticamente em unidades dp

304

Estou fazendo:

button.setLayoutParams(new GridView.LayoutParams(65, 65));

De acordo com os documentos, as unidades para a largura e a altura (ambos os 65 acima) são "pixels". Como você força isso a ser pixels independentes do dispositivo ou "dp"?

SK9
fonte

Respostas:

541

Você precisará convertê-lo de dps para pixels usando o fator de escala de exibição.

final float scale = getContext().getResources().getDisplayMetrics().density;
int pixels = (int) (dps * scale + 0.5f);
Robby Pond
fonte
111
A conversão correta é (int) (dps * escala + 0.5f). Essa é a fórmula que usamos em toda a estrutura.
Romain Guy
8
A fórmula está nos documentos. Para ler mais, vá para a seção 3 de developer.android.com/guide/practices/…
SK9
34
@RomainGuy, você pode adicionar uma função de utilitário à API para converter de dppara px? Obrigado.
AlikElzin-kilaka
3
o que é dps aqui? estou recebendo o erro "dps não pode ser resolvido para uma variável"? que tipo de "dps" precisa declarar ??
precisa
5
A variável "dps" é o valor de entrada que você deseja converter.
Robby Pond
233

Sei que essa é uma pergunta antiga, mas encontrei uma maneira muito mais clara de fazer essa conversão.

Java

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 65, getResources().getDisplayMetrics());

Kotlin

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 65f, resources.displayMetrics)
drspaceboo
fonte
8
Bem feito para descobrir como fazer isso. Eu não sou fã de repetir uma fórmula em vários lugares! Obrigado.
darrenp
2
Se não, em seguida, criar função com a fórmula
Sayka
1
@ Kenobi Faz a conversão para você de DP para PX. O 65acima é o valor DP que você deseja converter para PX
drspaceboo
7
Esta deve ser a resposta aceita, não a atual, onde esses números (0,5) que vem magicamente do nada
Johny19
1
@ Johny19 O 0.5 não é mágico. É apenas como arredondar um número de ponto flutuante para o número inteiro mais próximo em vez de truncá-lo. Veja meu comentário na resposta de Robby Pond para mais detalhes.
MarredCheese
38

Analisando sua exigência, também há uma solução alternativa. Parece que você conhece as dimensões no dp em tempo de compilação, para que você possa adicionar uma entrada dimen nos recursos. Em seguida, você pode consultar a entrada dimen e ela será automaticamente convertida em pixels nesta chamada:

final float inPixels= mActivity.getResources().getDimension(R.dimen.dimen_entry_in_dp);

E seu dimens.xml terá:

<dimen name="dimen_entry_in_dp">72dp</dimen>

Estendendo essa idéia, você pode simplesmente armazenar o valor de 1dp ou 1sp como uma entrada dimen e consultar o valor e usá-lo como um multiplicador. Usando essa abordagem, você isolará o código das coisas matemáticas e dependerá da biblioteca para realizar os cálculos.

vinha
fonte
Observe que o valor de retorno é realmente um int, portanto, é convertido em um float.
precisa saber é o seguinte
Esta é uma resposta ruim, porque é dinâmica a tarifa
Johny19 /
37

A maneira mais simples (e até funciona da API 1) testada é:

getResources().getDimensionPixelSize(R.dimen.example_dimen);

Das documentações:

Recupere uma dimensão para um ID de recurso específico para uso como um tamanho em pixels brutos. É o mesmo que getDimension (int), exceto que o valor retornado é convertido em pixels inteiros para uso como tamanho. Uma conversão de tamanho envolve arredondar o valor base e garantir que um valor base diferente de zero tenha pelo menos um pixel.

Sim, arredondando o valor, mas não é muito ruim (apenas em valores ímpares nos dispositivos hdpi e ldpi precisam adicionar um pouco de valor quando o ldpi não é muito comum) Eu testei em um dispositivo xxhdpi que converte 4dp em 16 (pixels) e isso é verdade.

David
fonte