Eu tive alguns problemas com o tamanho dos objetos customizados no android utilizando a API do Java em telas com densidades diferentes, e vou demonstrar como resolver esse problema, uma vez que o Java utiliza pixels como unidade de medida e não dp. Mas antes vou falar um pouco de tamanho de tela (screen size).
Essa medida refere-se ao tamanho físico da tela, medida na diagonal. O Android atualmente separa os tamanhos físicos de tela em quatro diferentes categorias, que são: tela pequena small, tela normal normal, tela grande large, tela extragrande xlarge.
Vou dar um exemplo mais claro de cada nomenclatura com aparelhos reais.
small: Sony Ericsson, Xperia Mini, que possuem uma pequena tela QVGA de 240 x 320 pixels
normal: HTC G1, HTC Magic , Motorola DEXT, possuem uma tela HVGA média 320 x 480 pixels. Nesse grupo também se encontram os celulares um pouco maiores como o Nexus One, Sony Xperia X10, Mororola Milestone, Samsung Galaxy S, que possuem telas WVGA que varia entre 480 x 800 e 480 x 854 pixels.
large: O tablet Samsung Galaxy Tab de 7", que possui tela WVGA de 1024 x 600 pixels
xlarge: Os novos tablets com Andoids 3.x, com tela WXGA de 1280 x 800 pixels
Obs: Essas medidas de tela são aproximadas e podem ter variações.
A resolução da tela é expressa em pixels, por exemplo, 320 x 480 px. Diferente do Iphone, no Android temos diversos celulares ,com resoluções diferentes, o que torna a vida do desenvolvedor android mais emocionante ( Risos ). Assim, no desenvolvimento dos aplicativos devemos evitar utilizar essa notação para definir os tamanhos das views, valores de margens, espaçamentos e qualquer outro parâmetro. No Android nunca trabalhamos diretamente com pixels, e sim com dp (density-independent pixel).
Densidade da tela é basicamente a relação entre a quantidade de pixels existentes na tela com a sua largura e altura. Quanto maior a densidade, maior será a quantidade de pixels espalhados pela tela.
Bem, agora é fácil, é só eu usar dp ao invés de px que todos os meus problemas estão resolvidos.
Mas e se você criar uma view customizada com o Canvas ao invés do xml por exemplo ?
Como eu havia explicado anteriormente, o Java utiliza a notação de pixels para definir valores.
Então chega de falar e vamos ao código.
Digamos que estamos criando uma view customizada e precisamos desenhar um quadrado na tela. Para isso precisamos utilizar a API de desenho. Vamos lá.
1 - Crie um projeto android no eclipse.
2 - Crie uma classe TesteView para API de desenho.
print do projeto.
O código da Activity é simples, vamos apenas alterar o setContentView();
public class ExemploConverPixelDP extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new TesteView(this));
}
}
Segue o código da classe TesteView.
public class TesteView extends View {
private Paint paint;
public TesteView(Context context) {
super(context);
paint = new Paint();
paint.setColor(Color.LTGRAY);
paint.setStyle(Style.FILL);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(0, 0, 320 / 2, 480 / 2, paint);
}
}
Nós sabemos que existem telas HVGA de 320 x 480 pixels e, portanto o quadrado vai ocupar a metade do tamanho da tela. Mas o que acontece se executarmos o mesmo exemplo em uma tela de maior densidade, como uma WVGA de 480 x 800 pixels.
Segue o print do exemplo executado no virtual divice com a tela HVGA de 320 x 480 pixels a esquerda, e a direita a tela WVGA de 480 x 800 pixels.
Como podemos verificar, na tela HVGA, o exemplo funcionou como o esperado, e nosso quadrado que (na verdade é um retângulo) preenche exatamente a metade da tela. Isso porque colocamos o valor fixo em pixels no método de desenho. Mas ao executarmos o mesmo exemplo em um aparelho de densidade mais alta o resultado foi diferente. O "quadrado" foi reduzido, pois a quantidade de pixels é maior nessa tela. E agora, o que fazemos ?
A solução é pensar que esses valores de 320 x 480 pixels na verdade estão em dp ( density-independent pixel) e fazer a conversão do valor de dp para pixels. Se fosse um arquivo XML de layout bastava colocar a notação em (dp) que tudo ficava lindo, mas em Java teremos que fazer a conversão manualmente.
Método que converte os valores:
public float toPixel(Context context, float dip) {
Resources r = context.getResources();
float densidade = r.getDisplayMetrics().density;
int px = (int) (dip * densidade + 0.5f);
return px;
}
Segue o código completo:
public class TesteView extends View {
private Paint paint;
public TesteView(Context context) {
super(context);
paint = new Paint();
paint.setColor(Color.LTGRAY);
paint.setStyle(Style.FILL);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// valores em dp
float larguraDP = 320;
float alturaDP = 480;
// convertendo para pixels
float larguraPX = toPixel(getContext(), larguraDP);
float alturaPX = toPixel(getContext(), alturaDP);
// desenha o quadrado
canvas.drawRect(0, 0, larguraPX / 2, alturaPX / 2, paint);
}
// converte de DP para Pixels
public float toPixel(Context context, float dip) {
Resources r = context.getResources();
float densidade = r.getDisplayMetrics().density;
int px = (int) (dip * densidade + 0.5f);
return px;
}
}
Agora rode e olhe o resultado.
O nosso quadrado (retângulo) agora ocupa o mesmo espaço, nas duas talas com diferentes densidades.
print do virtual device:
Eu esqueci de mencionar !!!
tela QVGA retorna a densidade de 0.75
tela HVGA retorna a densidade de 1.0
tela WVGA retorna a densidade de 1.5
Problema resolvido.
Até mais !
Nenhum comentário:
Postar um comentário