Layouts e Resources – Tutorial Android 4

Padrão

Olá pessoal! No último post criamos a nossa primeira Activity, e entendemos um pouco sobre Intents! No post de hoje vamos entender um pouco mais sobre resources no Android e criar um layout para a nossa Activity. Preparados?

Para o tutorial de hoje, vamos trabalhar majoritariamente com a pasta res, que fica localizada no caminho app/src/main/res. É nela que ficam todos os recursos do seu projeto, que não são necessariamente código Java. O projeto, no momento, deve ter algumas pastas, como drawable (vazia), mipmap (em algumas versões com sufixos estranhos) e values.

Um projeto Android padrão costuma ter várias outras, que entraremos em mais detalhes a medida que forem necessárias. Essas pastas separam os tipos de recursos que temos em nosso projeto. Por exemplo, drawable, conterá qualquer tipo de coisa desenhável, desde formas, a imagens e seletores. A mipmap contém somente o ícone do aplicativo. A pasta values contém valores em gerais, desde inteiros, até strings, cores, dimensões, estilos e etc.

Se você abrir cada uma das pastas (mipmap-hdpimipmap-mdpimipmap-xhdpi, etc), você verá que temos o ícone do aplicativo em diferentes tamanhos. Isso ocorre porque os dispositivos Android possuem diversas configurações. Configuração diz respeito a tudo no dispositivo, desde idioma, até o que chamamos de densidade da tela. Uma maior densidade, quer dizer que aquele dispositivo tem mais pixels em uma menor área física. Exemplo: um dispositivo que tem uma tela de 4,7″ e uma resolução de 480×800 pixels tem uma densidade mais baixa (hdpi) do que um device que tem a mesma tela de 4,7″, porém uma resolução de 1080×1920 (xxhdpi). Exatamente por suportar uma diversidade grande de tamanhos de tela, é que no Android não trabalhamos com pixels, e sim com density pixels. Assim, um botão tende a ter sempre “mais ou menos o mesmo tamanho”, independente da resolução da tela. Para aprender mais sobre isso, dê uma olhada na documentação do Android (que agora também possui versão em português!).

E como essa mágica é feita? Não é mágica. Ao colocar um qualificador na pasta, o Android, na hora que estiver executando, conhece a configuração do dispositivo e usa o recurso específico para a sua configuração. Assim, não precisamos fazer várias condições em nosso código. É importante lembrar que podemos ter vários tipos de qualificadores ou mesmo adicionar pastas com mais de um qualificador. Veremos alguns casos em outros posts 😉

Assim, resumindo, Supondo que estou em dispositivo xhdpi e preciso do resource mipmap/ic_launcher, o Android automaticamente buscará em mipmap-xhdpi/ic_launcher. Caso não exista uma versão específica para a configuração, ele busca a opção mais genérica, sem nenhum sufixo.

Bom, agora que já estamos mais familiarizados com o mecanismo de resources e pastas no Android, vamos criar uma nova pasta dentro de res, chamada layout. Essa pasta, como o próprio nome sugere, guardará arquivos que representam os layouts das nossas telas. Vamos criar um arquivo chamado activity_main.xml. A grande maioria dos resources no Android utilizam a notação de XML.

Neste arquivo, primeiramente colocaremos um container, o LinearLayout. Os containers servem para organizar os elementos na tela. No caso do LinearLayout, ele organiza os elementos alinhados, um após o outro, utilizando a orientação vertical ou horizontal. Adicionando o LinearLayout, o arquivo activity_main.xml fica assim:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

</LinearLayout>

Você pode perceber que, além da orientação, também configuramos a largura (width) e a altura (height) do elemento. Para essas dimensões, podemos utilizar um valor ou as constantes match_parentwrap_contentmatch_parent indica que o elemento adotará para essa dimensão, a mesma dimensão que seu elemento pai. No caso, como o LinearLayout é o primeiro elemento da nossa hierarquia de views, ele adotará o tamanho de seu pai (algum container do Android que representa a tela). Assim, temos um LinearLayout do tamanho da tela 🙂

Vamos agora adicionar dois campos de texto e um botão ao nosso layout.

Os campos de entrada de texto no Android são conhecidos como EditText. Além da altura e da largura, também especificamos o id e a propriedade hint. Ids no Android são identificadores, o que nos permitirá referenciar este elemento em outros lugares (seja no XML, seja nas nossas classes Java). A notação @+id indica que estamos criando este recurso caso ele não exista. Sempre que você ver a notação @ em um XML, significa que estamos referenciando um recurso. O + indica a criação e id indica que é um resource do tipo id. Já o hint indica um texto de sugestão que será exibido quando o campo estiver vazio, indicando ao usuário o que deve ser inserido. Também estamos utilizando a notação de recurso, dessa vez referenciando um recurso do tipo string (que terá um valor correspondente dentro de res/values/strings.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical"
    android:orientation="vertical">

    <EditText
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/name" />

    <EditText
        android:id="@+id/address"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/address" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/save" />

</LinearLayout>
<!-- Arquivo strings.xml -->
<resources>
    <string name="app_name">Tutorial</string>
    <string name="save">Save</string>
    <string name="address">Address</string>
    <string name="name">Name</string>
</resources>

No caso do Button, temos atributos semelhantes, com a diferença de que utilizamos a propriedade text em vez de hint. Com a propriedade text, teremos um texto no botão.

Com o arquivo de layout criado, vamos voltar a nossa classe MainActivity e definir este arquivo de layout, vinculando-o a Activity. Para isso, vamos utilizar ainda o método onCreate() que é chamado sempre que a Activity é criada. Nele, vincularemos o nosso layout XML a Activity. Fazemos isso chamando o método setContentView(). Este método pode receber um objeto do tipo View ou uma referência a um resource de layout. Note o uso da classe R. Esta classe é gerada automaticamente a cada build do projeto, e é uma referência a todos os resources que temos no projeto, para uso no nosso código Java. Vamos também, remover os Logs que adicionamos anteriormente. O método fica assim:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

Com esse XML, caso execute o aplicativo, nossa tela fica com o seguinte layout:

Para uma experiência mais agradável, poderíamos centralizar os elementos verticalmente. Para isso, podemos adicionar a propriedade gravity com o valor center_vertical. Essa propriedade indica como os filhos do container vão se comportar, conforme forem adicionados. Assim, temos a tela final:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical"
    android:orientation="vertical">

    <EditText
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/name" />

    <EditText
        android:id="@+id/address"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/address" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/save" />

</LinearLayout>

E é isso pessoal! No próximo post veremos o mecanismo de binding de views e callbacks no Android! Caso deseje baixar o projeto que desenvolvemos até agora, você pode encontrar no Github.

Até o próximo post!

Exportando Assets de um PSD para Apps (para não-designers como eu)

Padrão

E aí pessoal, beleza?

Bom, hoje fugindo um pouco de programação, vamos para um assunto de muitíssima utilidade: você pegou aquele PSD maneiro com o design do seu app, mas o designer esqueceu ou não pode te gerar os assets no momento… e agora José? Foi esse o meu caso recentemente e, como um ser rústico em se tratando de arte gráfica digital, cuja maior proeza é redimensionar uma imagem usando o Paint (sim, todas as imagens do blog são editadas no PAINT!), bate aquele desespero.

Bom, no meu caso, precisei pesquisar um bocado e, no final, até que o Photoshop faz algumas mágicas pra gente. Aqui estou usando a versão CC 14.2 do Photoshop… se não me engano, essa funcionalidade que vou mostrar apareceu na versão 14.1 (não faço ideia de como funciona em outras versões… se um designer leitor souber, fique a vontade pra entrar em contato que atualizamos o post :)).

Tendo em mãos o seu PSD, você vai abrir e, antes de mexer qualquer coisa, vai em Arquivo -> Gerar -> Recursos de imagem e certifique-se que a opção está marcada!

Captura de tela 2014-08-06 20.18.47

Feito isso, é só alegria. Agora, você pode ir até as suas camadas (ou layers) e renomeá-las, por exemplo, para imagem.png ou imagem.jpg. Existem uns padrões aí nessa nomenclatura para gerar assets de diferentes tamanhos automaticamente (por exemplo retina e normal, no caso do iOS). Um post mais detalhado sobre o assunto pode ser encontrado aqui.

Uma dica que eu, totalmente leigo não sabia, era como mesclar duas camadas pra exportá-las numa mesma imagem. É só segurar o Ctrl para selecionar as camadas que você deseja agrupar, clicar com o botão direito e selecionar a opção Grupo a partir de camadas. Depois, é só dar o nome do recurso a esse grupo que ele criou.

Complementando aqui a dica, recentemente eu descobri um conversor de resources de iOS para Android. Não sei vocês, mas a maioria dos designers que já trabalhei estão acostumados a gerar os resources para iOS, com a nomenclatura @2x para imagens retina e uma outra versão da imagem (por exemplo menu@2x.png menu.png). Para simplificar o nosso trabalho e o trabalho dos designers, achei no Github um projeto chamado ios2android, que nada mais é um script que, usando o ImageMagick, converte esses recursos para Android, redimensionando-os na proporção correta e criando as pastas drawable-hdpidrawable-mdpidrawable-ldpi, etc. Se tiver a versão pra iPad da imagem, ele converte pras dimensões de tablets Android também. Uma maravilha. O link do projeto é este.

As minhas impressões sobre esse script: como ele usa shell script, no Windows você precisa instalar o Cygwin (lembrando de adicionar o pacote do ImageMagick). No Mac, via Homebrew (conforme especificado na própria descrição do repositório), é bem simples (ele foi pensado pra rodar no Mac mesmo). Já no Linux, que tecnicamente seria de boa também, tive o problema de que as imagens ficaram com metade do tamanho que deveriam ficar. Eu não manjo quase nada de shell script… caso alguém saiba e consiga investigar o motivo disso acontecer no nosso amigo Linux, faça um pull request lá no projeto e contribua com o Open Source! 🙂

Bom pessoal, é isso! Fica a dica! 😀