Android

24 jan, 2017

Android Design: o que devemos saber

Publicidade

Então, quer dizer que você é um soldado desenvolvedor, mas só quer saber de codar e deixar a interface do usuário em segundo plano?

“’Ah, porque sou programador e não designer, então não devo me preocupar com isso’ ou ‘Ah, porque eu não tenho nenhum ganho em me preocupar com firula de layout’. Ou ainda ‘Ah, porque Tony Stark só é poderoso com a armadura’.”

Apesar da brincadeira, existem pessoas que realmente pensam assim. Porém, sendo você esta pessoa ou não, não tenha medo de ler o que está por vir.

Neste artigo, vou mostrar (e tentar clarear) um pouquinho do que devemos saber sobre quando, como e por que implementar técnicas para melhorar o resultado final de uma UI.

Ah, e se você faz parte dos amantes de comic sans, vulgo designers (brincadeira! rs), fiquem tranquilos, algumas desmistificações serão importantes para vocês também.

Vamos começar? Beleza!

Densidades

“Ah, mas eu sei o que é densidade! É uma determinada quantidade de massa sobre um  volume.”

Pois é, o mesmo conceito é aplicado na construção das nossas UIs. Vamos ver esta relação:

Tamanho da tela

Para montarmos um layout, precisamos ter noção de tamanho de tela, que é calculado pela diagonal (mais conhecida como polegada).

Densidade da tela

Densidade é um conceito bastante importante no mundo mobile. Por definição, a densidade da tela é dada pela quantidade de pixels dentro de uma área física da tela.

densidade da tela = largura da tela(ou altura) em pixels / largura da tela(ou altura) em polegadas

Então, teoricamente, uma tela com alta densidade terá mais pixel por polegada do que as com baixa densidade. Visualmente falando, um componente com medida fixa em pixels pareceria maior em telas com baixa densidade e menor nas com alta densidade.

“Ah, quanta teoria chata.”

Beleza, vamos entender melhor nos exemplos a seguir de alta e baixa densidade, respectivamente.

Density-Independent Pixel (DIP ou DP)

Assim como vimos anteriormente, um componente com determinada quantidade fixa de pixels se apresentará em telas com diferentes densidades de formas não proporcionais, ou seja, maior em algumas telas e menor em outras.

“Beleza, cara, mas como a gente deixa os elementos proporcionais?”

Boa pergunta! Eis que existe uma unidade virtual do Android que se “adapta” em telas com diferentes densidades.

“Mas como assim? Se adapta tipo mágica?”

Não! A mágica adaptação é feita a partir de uma relação de proporção. O cálculo é feito a partir de uma tela base (mdpi), cujo seu valor equivale à 160dpi.

dp = largura(em pixels) * 160 / screen density

Então, teoricamente, uma tela com densidade de 160 corresponderá à uma relação de 1dp por 1 pixel físico. Sendo assim, componentes com as unidades em dp serão redimensionados de acordo com a relação largura/densidade, tornando-os proporcionais independente dos diferentes tamanhos e densidades de tela.

“Ah, então quando eu quiser manter a proporção em todas as densidades de tela, eu devo fazer uso da unidade dp e não px, né?”

Exatamente, aspira!

Se você é um designer, provavelmente está pensando:

“Mas quando eu exporto um asset, ele tem a medida em pixel. Como ele se converteria para dp? É automático?”

Não é magia negra automático, pode-se forçar a medida no código para dp. Porém, o que vai acontecer é que em devices com alta densidade esse asset vai perder a qualidade, pois será esticado. O ideal seria que fosse exportado os assets para cada dimensão de tela.

Para fechar o assunto, vamos ver a comparação entre pixel e dp expressa pelo pai Google:

Scaleable pixels

Nós, desenvolvedores Android, quando queremos especificar um tamanho de um texto, fazemos uso da medida sp.

Mas por que devo usar a medida em sp e não em dp?

Fácil, porque a IDE fica dando aquele warning chato.”

O warning imposto pela IDE indica que dp neste momento não é a melhor escolha. De fato, a medida em sp é quase igual ao dp, por isso pode causar confusão. A única diferença é que esta medida para texto carrega uma variação a mais.

Esta variação é a preservação das configurações de fonte do sistema. Então, se o usuário alterar o tamanho de fonte padrão, na seção de acessibilidade, a fonte do seu app se adaptará à esta mudança. Tal relação pode ser expressa por:

sp = dp * escala

Curiosidade

A ponta de um dedo humano cobre uma área correspondente à 50dp, aproximadamente. Com esta noção, podemos ter uma base de como construir componentes que sejam confortáveis ao clique.

SVG

“Pô, cara, se tem o SVG, para que você está me pedindo para gerar vários assets em png? É só exportar tudo em SVG!”, disse o designer.

Gerar imagens bitmap para cada densidade de tela realmente não é algo legal de se fazer. Até mesmo para o resultado final do .apk, não é muito bom, pois ele carregará mais imagens, ficando consequentemente mais pesado.

Obs: Há maneiras de reduzir o tamanho do .apk fazendo split por densidades, mas não entrarei em detalhes neste artigo.

“Ah, moleque! Vamos usar SVG em tudo então.”

Pena que não é bem assim… Vamos entender o por quê?

De fato, o Android não aceita o formato SVG. Mas calma, não fique triste, pois recentemente o Google incluiu na sua support library um suporte nativo para imagens vetoriais, o Vector Drawable.

Este camarada compartilha algumas similaridades com o formato SVG. Assim, podemos ter a vantagem de ter imagens escaláveis em nossos apps, diminuir a quantidade massiva de bitmaps por densidades e poder animar sem ter vários bitmaps para representar cada frame. Com isso, o tempo de desenvolvimento e manutenibilidade da aplicação melhoram significatimente.

Toda regra tem uma exceção…

Os nossos amiguinhos vetoriais, se usados de forma errada, o que era pra salvar nossas vidas só vai arruiná-las.

“OMFG, e como podemos fazer um bom uso?”

Geralmente, o Vector Drawable é criado a partir de um SVG. A conversão pode ser feita pela própria toolchain do Android Studio (recomendado).

Este suporte vetorial tem uma lógica similar ao path do SVG. Tendo isso em mente, objetos com paths complexos podem comprometer o custo de renderização. Uma solução para esse tipo de problema seria simplificar o path.

Antes de um objeto vetorial ser desenhado no Android, ele passa por alguns processos, tais como a interpretação do drawable, a sua transformação para bitmap e, por fim, o upload à GPU.

Um objeto vetorial complexo poderá ocupar mais memória e/ou terá mais tempo para interpretação. Estes fatores podem causar um custo relativamente alto, já que a GPU terá que lidar com grandes números de Draw Calls, tornando o processo de upload mais lento.

Falando em memória… Imagens vetoriais muito grandes terão o mesmo custo de performance que falei anteriormente. Por esse motivo, o Google recomenda o uso dos VectorDrawables apenas para ícones e imagens simples, limitando seu tamanho em 200x200dp, no máximo.

“Ah, mas tenho muitas imagens complexas e grandes”

Então, o melhor é fazer uso de outras técnicas. Para imagens complexas, o uso de imagens raster poderá ser o ideal. O tamanho do .apk fatalmente vai aumentar, mas você não terá grandes problemas em questão de complexidade de renderização.

Para imagens simples, como backgrounds, mas com tamanho relativamente grande ou dinâmico, pode-se usar shapes, que é renderizado muito mais rápido que um VectorDrawable ou imagens raster; ou fazer uso do nine patch.

9-Patch

“O que é isso? É de comer?”

Antes de começarmos, vamos dar uma analisada na imagem:

Como você faria para criar um background que pudesse se esticar de acordo com o conteúdo dentro, sem perder qualidade? Exatamente! Você usaria o nine-patch.

“Pô, cara, simples assim? Como funciona isso?”

O nine patch é uma imagem bitmap (PNG) com flexibilidade de se esticar e manter a qualidade. Esta extensão é feita automaticamente pelo Android, mas antes você deve fazer umas marcações no 9-patch para indicar qual área da imagem será esticável.

A transformação do bitmap em um nine-patch, pode ser feita pela própria ferramenta do Android Studio, o Draw 9-patch tool.

As marcações LEFT-TOP são para indicar a área na qual será esticada. Já as RIGHT-BOTTOM têm como objetivo dar padding no conteúdo de dentro.

Atenção

“Ah, já que o 9-patch se expande automaticamente, eu não preciso então criar um desses para cada dimensão né?!”

Isso depende. Quando fizer as marcações você indicará apenas a área que deverá ser esticada. Sendo assim, a área que não foi marcada continuará a mesma. Vamos ver um exemplo:

Nesta imagem foi demarcado apenas o centro como esticável. Se você perceber bem, as bordas arredondadas ficarão intactas quando houver a expansão. Então, como é um .png e sua medida é em pixels, em devices com outras densidades parecerá que a borda está maior ou menor. Assim como vimos lá no começo sobre densidades, o ideal seria criar um 9-patch para cada dimensão de tela.

E isso é tudo pessoal!

Por fim, podemos concluir que não há uma técnica chave que vai resolver todos os problemas. É preciso conhecer um pouco de cada uma, como ela funciona por “debaixo dos panos” e saber quando usar. Afinal, cada técnica tem sua peculiaridade, e usar uma errada no momento errado pode comprometer todo seu desenvolvimento.

Espero que o artigo tenha contribuído no seu aprendizado. Qualquer dúvida ou sugestão, não deixe de comentar. Se gostou, não tenha medo de deixar um like, esta forma de reconhecimento vai me motivar a escrever mais.

Até a próxima!

***

Artigo publicado originalmente em: http://www.concretesolutions.com.br/2017/01/16/android-design-o-que-devemos-saber/