Auto Layout e StackView no iOS9: uma comparação com Android

Ao trabalhar com layouts no Android estamos acostumados com o desafio de criá-los de forma a se adaptar ao maior número possível de telas, pois dada a diversidade de dispositivos, criar um layout que só fica bom para uma única dimensão de tela pode causar problemas para outros usuários.

Esse desafio é tão comum que o próprio Android deu uma ajudinha criando valores para usarmos nas dimensões dos nossos elementos quando queremos um comportamento mais fluido: é o caso do match_parent e wrap_content.

Então, um layout bastante familiar que deixaria um campo de inserção de texto e um botão, ambos centralizados, ocupando a largura total da tela do aparelho seria assim:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:layout_marginBotton="30dp"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Botão"
        android:background="#FF800080"
        android:textColor="#FFFFFFFF"/>
</LinearLayout>

Já no mundo o iOS as coisas são um pouquinho diferentes. Como no início desse sistema operacional, não haviam iPhones com dimensões diferentes de tela, layouts não-fluidos faziam bastante sentido. No máximo tínhamos que nos preocupar com a aparência da nossa aplicação quando o aparelho estivesse na horizontal, mas ainda assim seriam apenas dois tipos de layouts diferentes.

As coisas começaram a se complicar em 2012 com o lançamento do iPhone 5, que era o primeiro iPhone a ter uma tela de 4 polegadas, enquanto todos os outros até então tinham 3.5 polegadas. Juntamente com essa meia polegada a mais na tela, veio uma preocupação: se quiséssemos nossa aplicação bonita nos iPhones 4 e 5 teríamos que fazer até quatro layouts diferentes, considerando os aparelhos nas orientações vertical e horizontal!

No entanto, juntamente com esse novo aparelho, na Apple World Wide Conference (WWDC) de 2012 o iOS 6 foi anunciado com uma funcionalidade bastante interessante que existe até hoje: o Auto Layout, uma forma bem legal de criarmos layouts que se adaptam aos diferentes tamanhos de dispositivos!

Hoje em dia o Auto Layout está bastante integrado ao Xcode, tornando seu uso bastante simples. Vamos fazer uma tela parecida com a definida no Android, contendo um campo de texto e um botão ocupando a largura total da tela:

Como estamos focados somente no layout, podemos criar uma aplicação qualquer contendo já uma telinha para manipularmos. No Xcode, vamos escolher Single View Application:

Single View Application

Na sequência, podemos colocar um nome para a app de TesteAutoLayout:

Nome para a app

Abrindo o arquivo Main.storyboard, podemos começar a construir nosso layout! Primeiramente, vamos arrastar os dois componentes que teremos, um Text Field e Button que estão no painel no canto inferior direito da IDE:

Painel de elementos

Com o Button selecionado, vamos selecionar o Attributes Inspector e colocar um background nele para visualizarmos suas dimensões:

Attributes Inspector

Background

Ao final, teremos uma tela com essa cara no nosso storyboard:

Projeto sem Auto Layout

Porém, ao rodar essa tela num simulador qualquer (no meu caso, estou usando um simulador para o iPhone 6), olha como ela ficará:

Resultado sem Auto Layout

Além disso, as coisas ficam um pouco piores quando rotacionamos a tela. Apertando CMD + seta, temos esse layout:

Emulador rotacionado sem Auto Layout

Vamos usar o Auto Layout para que nossos componentes se adaptem a quaisquer dimensões de tela!

Para facilitar a centralização de múltiplas views em relação a um mesmo ponto, o iOS 9 possui uma funcionalidade chamada Stack View, que nos permite criar uma view que funcionará como container e manipular suas propriedades!

Vamos criar uma Stack View selecionando o Button e o Text Field e clicando em Editor -> Embed In -> Stack View

Com isso, nosso layout ficou completamente estranho:

Stack View

Com o Stack View selecionado, vamos no Attribute Inspector e colocaremos em Spacing um espaçamento entre as views filhas de 30.

Spacing

Agora, podemos usar as propriedades de centralização do Auto Layout apenas clicando no nosso Stack View, apertando o CTRL, arrastando para o lado e selecionando a opção Center Vertically in Container:

Center Vertically in Container

Vamos fazer a mesma coisa, mas agora arrastando para o lado direito e selecionando a opção Trailing Space to Container Margin:

Trailing Space to Container Margin

Por fim, vamos arrastar para o lado esquerdo e selecionaremos a propriedade Leading Space To Container Margin.

Leading Space to Container Margin

Clicando em ambas linhas-guia azuis, vamos definir essa constante para 30 pt:

Horizontal Space constant

Por fim, vamos clicar no último botão no canto inferior direito da nossa tela (Resolve Auto Layout Issues) e, em seguida, Update Frames:

Update Frames

Com isso, temos nosso layout fluido, centralizado em qualquer tela! Faça o teste e rode a aplicação!

Resultado na vertical com Auto Layout

Resultado na horizontal com Auto Layout

Veja que conseguimos esse resultado bastante interessante com apenas com alguns cliques! E isso é apenas o começo para demonstrar o poder do Auto Layout juntamente com views agrupadas.

E você, já havia usado Auto Layout nas suas aplicações ou achava que era um bicho de sete cabeças?

7 Comentários

  1. Fernando Mantoan 09/03/2016 at 11:27 #

    Bem legal a matéria, tive um pouco de dificuldades pra me adaptar com o Auto Layout, principalmente por estar acostumado com o Android, mas com o tempo é tranquilo de usar ele com storyboards. Fica a dica para um próximo post: definir as constraints do Auto Layout via código com (ou sem) o Masonry 😀

  2. Mateus 09/03/2016 at 12:27 #

    Eu usei da seguinte forma.
    Criei um componente Webview que ocupa toda a tela, e desejava que quando a tela fosse rotacionada o componente Webview também ocupasse toda a tela.
    O problema era quando rotacionava a tela, o componente Webview ficava como em modo retrato, ocupando o lado esquerdo e deixando um espaço em branco do lado direito, e não rotacionava ocupando toda a tela como eu desejava.

    A solução foi adicionar constraints.
    1 – Selecionei o componente Webview

    2 – Cliquei no icone ‘Pin’ (localizado na barra inferior, lado esquerdo, abaixo do painel onde manipula os componentes, dos 4 incones é o segundo da direita para esquerda)

    3 – Abriu um balão com o titulo de ‘Add New Constraints’ e nele habilitei as 4 opções em ‘Spacing to nearest neighbot’ (são as 4 linhas vermelhas pontilhadas, nas 4 direções, cima, baixo, direita, esquerda. Elas possuem um cubo na extremdidade interna e um combobox para cada extremidade externa. Quando as linhas são habilitadas deixam de ser pontilhadas e ficam continuas). A opção ‘Constrain to margins’ já estava habilitada. E cliquei no botão ‘Add 4 Constraints’.

    Apareceu um icone azul com nome de Constraints abaixo do componente Webview no painel onde lista em árvore os componentes, e expandindo ele aparece as 4 opções habilitadas (.leading, .trailing, .top, .bottom).

    O Stackview também resolveria esse problema de rotacionar a tela e o componente ficar em toda a tela?

  3. Felipe Torres 09/03/2016 at 16:39 #

    Oi Fernando,

    também passei por essa dificuldade no começo. O que eu achei mais diferente é que, enquanto no Android a gente tem acesso ao XML (que é feio, mas a gente acaba acostumando), no iOS a criação de layouts é mais visual, arrastando componentes e definindo constraints.

  4. Felipe Torres 09/03/2016 at 16:47 #

    Oi Mateus,

    o StackView é indicado quando queremos agrupar elementos numa view, funcionando como um container. Com o StackView fica mais fácil controlar o comportamento de várias views ao mesmo tempo: se todas elas estiverem dentro do StackView e eu disser que meu stackView deverá ocupar toda a largura da tela, então todas as views filhas seguirão essa regra também.

    No seu caso, como você está manipulando apenas uma única view (o seu WebView), acredito que o StackView não ajudaria muito, pois você teria que fazer esses mesmos procedimentos que descreveu, só que para o StackView.

  5. Renato 10/03/2016 at 14:22 #

    Tudo é questão de costume. Mas no Android eu acho mais prático.

  6. Mateus 11/03/2016 at 08:59 #

    Oi Felipe,

    Entendi, obrigado.

  7. Felipe Torres 16/03/2016 at 03:09 #

    Oi Renato,

    concordo com você que é uma questão de costume, mas confesso também que às vezes sinto falta de manipular o XML do layout “na mão”, como fazemos no Android.

Deixe uma resposta