Customizando a Interface de Usuário no iOS 5

Adam Burkepile Adam Burkepile

Este post também está disponível em: Inglês, Japonês, Russo

UIKit Customization in iOS 5! Nota do Ray: Parabéns, pessoal, vocês conseguiram! Ajudando a divulgar  o iOS 5 Feast, vocês liberaram mais cedo o primeiro tutorial sobre iOS 5! Aproveitem!

Postado pelo membro do Time de Tutoriais iOS  Steve Baranski, fundador da komorka technology, uma provedora de serviços de consultoria e desenvolvimento iOS.

Para fazer sucesso na App Store, seu app precisa se destacar. O “look and feel” café com leite da interface provida pela Apple já não ajuda muito em um mercado tão competitivo.
A maioria dos aplicativos mais populares na App Store apresentam elementos de interface customizados:

  • O Twitter implementou uma UITabBar customizada
  • No Instagram ambas UITabBar e UINavigationBar foram customizadas
  • Já o Epicurious para iPad customizou elementos padrões da interface split-view
Create a cool custom user interface with iOS 5's new UIKit and UIAppearance APIs!

Criando uma interface legal e customizada com as novas APIs do iOS 5 para UIKit e UIAppearance!

Antes do iOS 5, muitos desenvolvedores precisavam utilizar recursos pouco convencionais para alcançar algum resultado. Embora a abordagem mais recomendada fosse sobrescrever o método drawRect:, muitos recorriam ao temido método “swizzling”.

Mas com o iOS 5, os dias de escuridão acabaram! No iOS 5 foram incluídas novas APIs que permitem a fácil customização de vários elementos do UIKit.
Para mostrar algumas dessas novas APIs, nesse tutorial vamos transformar um aplicativo sobre viagens de surf, com uma interface padrão, em um app com um tema mais “praia”.
Para aproveitar ao máximo esse tutorial, você precisa saber o básico sobre  desenvolvimento iOS. Se você é novo na área, dê uma olhada nos outros tutoriais do site.

Vamos lá!

Para começar, faça o download do projeto inicial. Eu criei um app simples para você começar, assim podemos focar no assunto principal desse tutorial – a customização do UIKit.
Uma vez aberto o projeto, dê uma olhada pelo código e nos arquivos XIBs. Você vai ver que a view principal apresenta uma lista das nossas viagens, e a view de detalhes permite adicionar informações sobre cada viagem individualmente.
Nesse contexto, execute (“Build & Run”) o aplicativo (ou Cmd-R) para ver o que temos até agora.
A basic UIKit user interface without customization
Bom, tudo funcionando, mas dificilmente representa a experiência que teríamos em uma viagem para surfar, não parece divertido. Então vamos olhar com mais calma.
Vamos começar com a view de detalhes. Tudo parece bem simples, né?
Um botão (UIBarButtonItem) com estilo simples na barra de navegação no topo (UINavigationBar), simples elementos UITabBar e as tradicionais entradas de dados, incluindo:

  • UILabels com a fonte padrão do sistema, a Helvetica
  • UITextField
  • UISlider
  • UISwitch
  • UISegmentedControl

Nesse tutorial, vamos customizar totalmente a view de detalhes usando a nova API do iOS 5. Então, com a ideia que temos em mente, vamos fazer esse aplicativo ficar diferente.

Adicionando uma imagem como background

Abrindo a pasta “Images” do projeto, você vai ver que já temos algumas imagens para usar na customização do nosso app – precisamos modificar o código para que possamos usá-las.
Dentro da pasta de imagens há um arquivo chamado “bg_sand.png”. Vamos começar colocando essa imagem como background da view de detalhes.
Abra o arquivo DetailViewController.m e crie o método viewDidLoad como abaixo:

- (void)viewDidLoad {    
    [super viewDidLoad];
 
    [[self view] setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"bg_sand"]]];    
}

Se você ficou confuso, não esquenta. É a técnica usada para colocar imagens como plano de fundo, pois é um jeito fácil de adicionar imagens como background em uma view. Não há uma propriedade “backgroundImage”, mas há uma propriedade “backgroundColor”!
Execute o projeto para ver como ficou:
Adding a custom background image to a UIView
Já dá até para sentir a areia nos pés!

Customizando a UINavigationBar

Ainda na pasta de imagens, há duas imagens que vamos usar para customizar a barra de navegação (UINavigationBar): surf_gradient_textured_32.png e surf_gradient_textured_44.png.
Vamos repetir a imagem, da esquerda para a direita, por toda a barra de navegação. Existem dois tamanhos diferentes para a altura da imagem porque a altura da UINavigationBar varia de acordo com a posição do telefone, nesse caso, no modo landscape.
O iOS 5 oferece duas APIs para nos ajudar nessa tarefa:

  • UINavigationBar possui uma nova propriedade backgroundImage que nos ajuda a definir a imagem de fundo (background).
  • UIImage possui um novo método chamado resizableImageWithCapInsets, usado para criar imagens redimensionáveis. O método permite especificar quais partes da imagem que não serão redimensionadas, como um botão com cantos arredondados nas bordas, que não devem ser repetidos.

Poderíamos fazer isso diretamente na view de detalhes usando as novas APIs para adicionar uma imagem como background, mas aí teríamos que fazer o mesmo procedimento em todas as outras views que poderíamos ter em nosso projeto!
Obviamente isso levaria um tempo. Pensando nisso, o iOS 5 oferece uma nova funcionalidade que permite customizar elementos de interface uma única vez, substituindo todos os outros elementos dentro do mesmo nível de hierarquia.
Assim, começando pela UINavigationBar, vamos usar o conceito do “appearance proxy” para customizar alguns elementos que vão se repetir em todo o aplicativo.
Vamos dar uma olhada em como vai ficar nosso código. No arquivo SurfsUpAppDelegate.m, crie um novo método logo acima de application:didFinishLaunchingWithOptions:

- (void)customizeAppearance
{
    // Criando imagens redimensionáveis
    UIImage *gradientImage44 = [[UIImage imageNamed:@"surf_gradient_textured_44"] 
        resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
    UIImage *gradientImage32 = [[UIImage imageNamed:@"surf_gradient_textured_32"] 
        resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
 
    // Definindo a imagem de background para *todas* as UINavigationBars
    [[UINavigationBar appearance] setBackgroundImage:gradientImage44 
        forBarMetrics:UIBarMetricsDefault];
    [[UINavigationBar appearance] setBackgroundImage:gradientImage32 
        forBarMetrics:UIBarMetricsLandscapePhone];
 
    // Customizando o texto do título para *todas* as UINavigationBars
    [[UINavigationBar appearance] setTitleTextAttributes:
        [NSDictionary dictionaryWithObjectsAndKeys:
            [UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:1.0], 
            UITextAttributeTextColor, 
            [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8], 
            UITextAttributeTextShadowColor, 
            [NSValue valueWithUIOffset:UIOffsetMake(0, -1)], 
            UITextAttributeTextShadowOffset, 
            [UIFont fontWithName:@"Arial-Bold" size:0.0], 
            UITextAttributeFont, 
            nil]];
 
}

Nas duas primeiras linhas criamos uma imagem redimensionável usando o método resizableImageWithCapInsets. Note que esse método substitui stretchableImageWithLeftCapWidth:topCapHeight:, que agora é obsoleto.
No “cap insets”, você basicamente especifica uma parte fixa da imagem, nessa ordem: top, left, bottom, right (em cima, à esquerda, em baixo e à direita). O restante é redimensionado ao longo do elemento onde a imagem é aplicada. Nessa imagem em particular, queremos que tudo seja redimensionado, por isso colocamos 0 (zero) para todas as posições.
Nas duas linhas seguintes usamos o “appearance proxy”, definindo as imagens redimensionáveis como background, para as métricas indicadas da barra.
A última linha customiza o título que aparece na nossa view de detalhes. Para fazer isso, passamos um dicionário (NSDictionary) com os atributos para o texto. As chaves disponíveis são:

  • UITextAttributeFont
  • UITextAttributeTextColor
  • UITextAttributeTextShadowColor
  • UITextAttributeTextShadowOffset

Quase lá! Adicione agora apenas a linha abaixo no método application:didFinishLaunchingWithOptions, antes de qualquer código, para chamar o método de customização que criamos:

[self customizeAppearance];

Execute o aplicativo, e poderemos ver a UINavigationBar com a imagem que adicionamos, em ambas as orientações (portrait e landscape). E com o título personalizado!
Custom Navigation Bar Background Image in iOS 5

Customizando o UIBarButtonItem

Na pasta “Images”, procure pelos arquivos button_textured_24.png e button_textured_30.png. Vamos usá-las para customizar os botões que aparecem na UINavigationBar.
Vamos definir essas imagens como redimensionáveis também. É importante fazer isso porque a largura dos botões pode variar dependendo do tamanho do texto dentro dele.
Para os botões, não queremos que sejam redimensionados os primeiros 5 pixels à esquerda e os outros 5 à direita, por isso vamos definir left e right em 5. Os pixels entre eles vão ser redimensionados tanto quanto necessário para ajustar a largura do botão.
Vamos tentar! Vamos usar o “appearance proxy” para customizar os UIBarButtonItems uma só vez, como fizemos antes. Adicione o seguinte código no final do método customizeAppearance:

UIImage *button30 = [[UIImage imageNamed:@"button_textured_30"] 
    resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)];
UIImage *button24 = [[UIImage imageNamed:@"button_textured_24"] 
    resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)];
[[UIBarButtonItem appearance] setBackgroundImage:button30 forState:UIControlStateNormal 
    barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackgroundImage:button24 forState:UIControlStateNormal 
    barMetrics:UIBarMetricsLandscapePhone];
[[UIBarButtonItem appearance] setTitleTextAttributes:
    [NSDictionary dictionaryWithObjectsAndKeys:
        [UIColor colorWithRed:220.0/255.0 green:104.0/255.0 blue:1.0/255.0 alpha:1.0], 
        UITextAttributeTextColor, 
        [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0], 
        UITextAttributeTextShadowColor, 
        [NSValue valueWithUIOffset:UIOffsetMake(0, 1)], 
        UITextAttributeTextShadowOffset, 
        [UIFont fontWithName:@"AmericanTypewriter" size:0.0], 
        UITextAttributeFont, 
        nil] 
    forState:UIControlStateNormal];

Parece familiar? Criamos imagens redimensionáveis e as definimos como background dos botões para ambas as orientações portrait e landscape. Em seguida, formatamos o texto com a fonte “typewriter-style” que vimos no começo do tutorial.
O botão “Voltar” precisa de uma customização especial, porque ele possui um estilo diferente – parecendo uma seta. Dê uma olhada nas imagens: Imagesbutton_back_textured_24.png and Imagesbutton_back_textured_30.png.
Adicione o seguinte código ao final do método customizeAppearance para alterar o botão “Voltar”:

UIImage *buttonBack30 = [[UIImage imageNamed:@"button_back_textured_30"] 
    resizableImageWithCapInsets:UIEdgeInsetsMake(0, 13, 0, 5)];
UIImage *buttonBack24 = [[UIImage imageNamed:@"button_back_textured_24"] 
    resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12, 0, 5)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:buttonBack30 
    forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:buttonBack24 
    forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone];

Note que usamos valores diferentes para o “cap inset”, porque a imagem do botão “Voltar” tem o lado esquerdo mais largo que não deve ser redimensionado. Repare também que há uma propriedade em UIBarButtonItem para “backButtonBackgroundImage”, que usamos aqui.
Execute o projeto, e você vai ver UIBarButtonItems bem legais e customizados na sua UINavigationBar!
Custom UIBarButtonItems

Customizando a UITabBar

Para customizar a UITabBar, o iOS 5 possui uma API que permite adicionar uma imagem como background da toolbar, e uma imagem que indica um item selecionado. Dê uma olhada em Imagestab_bg.png e Imagestab_select_indicator.png para ver as imagens que usaremos.
Embora queiramos apenas uma UITabBar, outras, provavelmente, terão a mesma aparência que essa. Por isso, vamos customizá-la utilizando “appearance proxy” para ter efeito em todas as UITabBar.
Adicione o seguinte código ao final do método customizeAppearance:

UIImage *tabBackground = [[UIImage imageNamed:@"tab_bg"] 
    resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[[UITabBar appearance] setBackgroundImage:tabBackground];
[[UITabBar appearance] setSelectionIndicatorImage:
        [UIImage imageNamed:@"tab_select_indicator"]];

Execute o aplicativo… Legal, né?! O background e a imagem que representa um item selecionado ficaram ótimos!!
A custom UITabBar with iOS 5
OBS: Você ainda pode especificar imagens para os comportamentos “finished” e “unfinished” se você quiser modificar a forma como as imagens de “selecionado” e “não selecionado” aparecem.

Customizando o UISlider

Dê uma olhada em Imagesslider_minimum.png, Imagesslider_maximum.png, e Imagesthumb.png para ver as imagens com as quais vamos trabalhar para customizar o UISlider.
O iOS 5 tornou ridiculamente fácil a customização do UISlider apenas definindo as propriedades “maximumTrackImage”, “minimumTrackImage”, e “thumbImage”.
Vamos lá! Adicione o seguinte código ao final do método customizeAppearance:

UIImage *minImage = [[UIImage imageNamed:@"slider_minimum.png"] 
    resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 0)];
UIImage *maxImage = [[UIImage imageNamed:@"slider_maximum.png"] 
    resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 0)];
UIImage *thumbImage = [UIImage imageNamed:@"thumb.png"];
[[UISlider appearance] setMaximumTrackImage:maxImage 
    forState:UIControlStateNormal];
[[UISlider appearance] setMinimumTrackImage:minImage 
    forState:UIControlStateNormal];
[[UISlider appearance] setThumbImage:thumbImage 
    forState:UIControlStateNormal];

Execute o aplicativo e veja como ficou nosso UISlider!
A custom UISlider with iOS 5

Customizando o UISegmentedControl

Vamos agora personalizar nosso UISegmentedControl. Agora é um pouco mais complicado, porque temos um background para o estado “selecionado” e outro para o “não selecionado”, bem como estados diferentes para as partes adjacentes (por exemplo, selecionado na esquerda, desmarcado na direita; selecionado na direita e desmarcado na esquerda; e desmarcado em ambos os lados).
Dê uma olhada nas imagens que vamos usar para entender melhor a ideia: Imagessegcontrol_sel.png, Imagessegcontrol_uns.png, Imagessegcontrol_sel-uns.png, e Imagessegcontrol_uns-uns.png.
Assim, adicione o código abaixo ao final do método customizeAppearance:

UIImage *segmentSelected = 
    [[UIImage imageNamed:@"segcontrol_sel.png"] 
        resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
UIImage *segmentUnselected = 
    [[UIImage imageNamed:@"segcontrol_uns.png"] 
        resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
UIImage *segmentSelectedUnselected = 
    [UIImage imageNamed:@"segcontrol_sel-uns.png"];
UIImage *segUnselectedSelected = 
    [UIImage imageNamed:@"segcontrol_uns-sel.png"];
UIImage *segmentUnselectedUnselected = 
    [UIImage imageNamed:@"segcontrol_uns-uns.png"];
[[UISegmentedControl appearance] setBackgroundImage:segmentUnselected 
    forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setBackgroundImage:segmentSelected 
    forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segmentUnselectedUnselected 
    forLeftSegmentState:UIControlStateNormal 
    rightSegmentState:UIControlStateNormal 
    barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segmentSelectedUnselected 
    forLeftSegmentState:UIControlStateSelected 
    rightSegmentState:UIControlStateNormal 
    barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] 
    setDividerImage:segUnselectedSelected 
    forLeftSegmentState:UIControlStateNormal 
    rightSegmentState:UIControlStateSelected 
    barMetrics:UIBarMetricsDefault];

Execute o aplicativo. Agora nosso UISegmentedControl está completamente diferente!
A custom UISegmentedControl with iOS 5

Customizando o UISwitch

Até a data deste tutorial, não há um jeito fácil de personalizar o UISwitch. No entanto (como em muitos outros controles) é extremamente fácil alterar a cor através da propriedade tintColor.
Para garantir que abordamos diferentes formas de customização, vamos definir a propriedade “onTintColor” no próprio código. Você vai ver que em DetailViewController nós já temos um IBOutlet – rentSwitch – conectado em DetailView.xib.
Então, vamos adicionar o código abaixo para definir a propriedade “onTintColor” no método viewDidLoad, em DetailViewController:

[rentSwitch setOnTintColor:[UIColor colorWithRed:0 green:175.0/255.0 blue:176.0/255.0 alpha:1.0]];

Execute o aplicativo e veja a diferença no nosso UISwitch!
A custom UISwitch with tintColor in iOS 5
Estamos quase lá, mas ainda temos algumas coisas para ver. Precisamos alterar as labels e o background do UITextField.

Customizando uma UILabel

Abra o arquivo DetailView.xib para que possamos editá-lo usando o Interface Builder. Selecione a primeira label (“Your name”) na view principal. No painel à direita, selecione a aba “Attributes Inspector” e faça as seguintes alterações:

  • Font: Custom
  • Family: American Typewriter
  • Style: Regular
  • Size: 16

Faça o mesmo para as outras duas labels: “Experience Level” e “Rent a board?”.
Execute o aplicativo. Nossas labels estão ótimas!!
A custom UILabel configured in Interface Builder

Customizando o UITextField

Nosso UITextField já foi definido para usar o estilo UITextBorderStyleLine. Aproveitando que ainda estamos no Interface Builder, vamos alterar a fonte para American Typewriter, Size 12, Regular. Olhando na aba “Identity Inspector”, veremos que o campo “Custom Class” foi definido para “UITextField – CustomTextField”. Se olharmos agora para o painel “Navigator”, à esquerda, há um grupo (diretório) chamado Custom Views, onde há uma classe do mesmo tipo.
Para adicionar o background, vamos sobrescrever o método drawRect:, como sendo outra técnica de customização.
Substitua a chamada para “super” com o seguinte código:

- (void)drawRect:(CGRect)rect
{
    UIImage *textFieldBackground = [[UIImage imageNamed:@"text_field_teal.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(15.0, 5.0, 15.0, 5.0)];
    [textFieldBackground drawInRect:[self bounds]];
}

Assim criamos uma imagem redimensionável e a desenhamos no retângulo definido pelos limites (bounds) da view (nosso UITextField). Agora vamos executar o aplicativo…
A custom UITextField by overriding drawRect
É isso, aí! Nossa página de detalhes está totalmente customizada!

Para onde ir agora?

Aqui temos o projeto de exemplo com todo o código do tutorial.
Se você quiser aprender mais sobre a customização de elementos do UIKit no iOS 5, dê uma olhada em nosso novo livro iOS 5 by Tutorials! O livro inclui um capítulo adicional em “User Interface Customization in iOS 5″, onde ensino como personalizar table views, popover controllers, e mais métodos avançados de customização.
Se você tiver algum comentário ou dúvida sobre a customização de elementos UIKit, junte-se ao nosso fórum de discussão abaixo!
Postado pelo membro do Time de Tutoriais iOS  Steve Baranski, fundador da komorka technology, uma provedora de serviços de consultoria e desenvolvimento iOS.

Adam Burkepile
Adam Burkepile

Adam Burkepile is currently a full-time Software Consultant and independent iOS developer. If he isn’t at the computer, he’s probably getting punched in the face at Krav Maga. Check out his latest app – Pocket No Agenda. You can reach him for work or just to chat at Twitter, Github, his website, or email.

User Comments

0 Comment

Other Items of Interest

Ray Newsletter Mensal

Sign up to receive a monthly newsletter with my favorite dev links, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

Hang Out With Us!

Every month, we have a free live Tech Talk - come hang out with us!


Coming up in May: Procedural Level Generation in Games with Kim Pedersen.

Sign Up - May

Coming up in June: WWDC Keynote - Podcasters React! with the podcasting team.

Sign Up - June

Vote For Our Next Book!

Help us choose the topic for our next book we write! (Choose up to three topics.)

    Carregando ... Carregando ...

Nossos livros

Our Team

Time de Tutoriais

  • Jake Gundersen

... 55 total!

Editorial Team

... 22 total!

Code Team

  • Orta Therox

... 1 total!

Equipe de Tradução

  • Jose De La Roca
  • David Xie
  • Fabio Casado

... 38 total!

Subject Matter Experts

  • Richard Casey

... 4 total!