Você está na página 1de 1018

gnu:

Google

Aprenda a criar aplicaes para dispositivos mveis


com o Android SDK

|'iOVa'EC Ricardo R. Lecheta


Conhea tambm
do mesmo autor

A Amazon Web Services (AWS)


possui uma plataforma de
computao em nuvem, repleta
de servios para auxiliar a criao
de aplicaes com alta
disponibilidade e escalabilidade.
O objetivo deste livro
apresentar os principais servios
da AWS, desde o bsico ao
avanado, em uma metodologia
passo a passo e de forma prtica.
Voc vai aprender a criar
servidores virtuais na nuvem para
hospedar seu prprio site, utilizar
balanceadores de carga,
escalonamento automtico,
monitoramento de servios,
bancos de dados na nuvem I
armazenamento de arquivos,
entrega de contedo esttico e
dinmico, controle de permisses
e segurana, servio de e-mails,
servio de la para mensagens
assncronas, mobile push,
controle de custos etc.
DROI
Aprenda a criar aplicaes para dispositivos mveis
com o Android SDK

41 Edio

Ricardo R. Lecheta

Novatec
. ~ . _ . ~ )2/1998.
Copyright ? 2009, 2010. ZOIS. 2015 da Ntwatu l.liIOIl lldl
~ , . t _ pj ~ mt 'idos ela Let 9.610 ele I9/( l _ , ` ` _ _
'ludus txs LIIITIIUS n\t.t`\ lt .\`( P ` P pk' Or m|qu.- P|'0Q$$(), Scm prvll klUIUl'IZ:Igl0. POI' LSLFIIO,
pmibida ii reproduo desta obra. mesmo parul . P CI
do autor e da liditora.

Editor: Rubens Prates


Assistente editorial: Priscila A. Yoshimatsu
Reviso gramatical: Viviane Oshima
Editorao eletrnica: Carolina Kuwabata
Capa: Victor Bittow

ISBN: 978-85-757.2-440-3

Histrico de impresses:

Agosto/2015 Primeira reimpresso


junho/2015 Quarta edio (ISBN: 978-85-7522-440-3)
Outubro/2014 Quarta reimpresso
Abril/2014 Terceira reimpresso
janeiro/2014 Segunda reimpresso
Setembro/2013 Primeira reimpresso
Maro/2013 Terceira edio (ISBN: 978-85-7522-344-4)
junho/2010 Segunda edio (ISBN: 978-85-7522-244-7)
Maro/2009 Primeira edio (ISBN: 85-7522-186-O)
Novatec Editora Ltda.
Rua Lus Antnio dos Santos IIO
02460-000 - So Paulo. SP - Brasil
Tel.: +55 ll 2959-6529
Email: novatec@novatee.com.br
Site: novatec.eom.br
Twitter: twitrer.com/novateeeditora
Facebook: facebookcom/novatec
LinkedIn: Iinledin.com/in/novatec
OG20l50729
Este livro dedicado a toda a minha familia e principalmente aos meus pais,
Pedro e Maria Luisa, por terem me dado todo o carinho e a melhor educao
possvel, e por serem um grande exemplo de boas pessoas.
Em especial, este livro dedicado a Paty, que uma pessoa muito especial
em minha vida e que sempre esteve ao meu lado me apoiando em todos os
momentos. Paty, voc sabe que s co completo quando estamos juntos e voc
a dona do meu corao. Te amo.
H
Sumrio

Agradecimentos ........

Sobre o autor .........

Prefcio ...... . ................... .... . ...........

Captulo 1 - Introduo ao Android ..................


1.1 Introduo ..............................................
1.2 Open Handset Alliance e o Android ........
13 Sistema operacional Linux ................
1.4 Cdigo aberto e livre ..............................
15 Mquina virtual Dalvik .................................
1.6 Mquina virtual ART (Android Runtime) ...........
1.7 Conhecendo um pouco mais sobre o Android ....
1.8 Android Developer Challenge ...........................
1.9 Google Play ...............................
1.10 T-Mobile G1 ....................................................
1.11 Google Nexus ...................................................
1.2 Um pouco sobre a histria e verses do Android
1.13 Android 15 (Cupcake) ......................................
1.14 Android 1.6 (Donut) ............................. . ..
1.15 Android 2.0 e 2.1 (Eclair) ........
1.16 Android 2.2 (Froyo) ...............
1.17 Android 23 (Gingerbread) ...............
1.18 Android 3.0 (Honeycomb) ..................
1.19 Android 4.0 (Ice Cream Sandwich) ......
1.20 Android 4.1 (]elly Bean) ...................
1.21 Android 4.4 (KitKat) .....................................
1.22 Android 5.0 (Lollipop) ....................................
1.23 Google I/O 2015 e o anncio do Android M .....

Captulo 2 I Congurao do ambiente de desenvolvimento.


2.1 Android SDK .....................................................
2.2 Requisitos de software e sistema .......
8 ..... ..43
23 Plataforma (verso do Android) ...... _______44
Google Android - 4 Ed

2.4Android Studio ............. ......... .MN47


2.5 Instalando os pacotes pe o _ ......... AXMLI... I'-USO
2.6 Intel Hardware Accelerated Execut1on_Man8ef (H 51
2.7 Criando um projeto no Android Studio ..................... W-S
2.8 Criando um oemulador
2.9 Executando (AVD)
projeto no emu a ........................
or ....... . .......... UHWO
. ....... 61
2,10 Algumas janelas importantes do Android Studio ........ HHW3
2.11 Aplicaes na tela principal (Home) -----~- --~~~ ''' 6 4
2.12 Entendendo um pouco mais sobre o emulador ....... ....... 6 6
2.13 ADB (Android Debug Bridge) .................................... ....... 6 8
2.14 Informaes bsicas sobre a resoluo do emulador ....... ....... 7 O
2.15 Como fazer o download dos exemplos do livro .......... ------

Capitulo 3 1 Conceitos bsicos do Android ............... ~------- 7 2


3.1 Estrutura do projeto no Android Studio ....... ------- 7 2
3.2 Arquivo AndroidManifest.xml ............... ------- 7
33 Classe MainActivity ............................... --~---- 7 8
3.4 Arquivo de layout activity_main.xml ......... ----~-- 8 0
3.5 Arquivo strings.xml ............................................................. ....... 83
3.6 Classe R ................................................................................. ....... 83
3.7 Informaes sobre como acessar recursos de texto e imagem ....... ....... 84
3.8 Arquivo build.gradle .............................................................. ....... 86
3.9 LogCat - Escrevendo mensagens de log ........ 88
3.10 Tratamento de eventos ............................ 90

Captulo 4 n Activity ..........

4.1 Activity ................................................................. 96


4.2 Classes FragmentActivity e AppCompatActivity ......................... 97
43 Ciclo de vida de uma activity ...................................................... 99
4.4 Ciclo de vida avanado - o que acontece ao rotacionar o celular? 105
4.5 Navegao entre telas e inicializao de uma nova activity . 106
4.6 Mais detalhes sobre a classe Bundle e como assar ^
O bsico sobre _ b P p3I'8lfl'l[I`OS ...... ......
action ar e como voltar para tela ameno r ........... ,,___,
1.14
115
4.8 Links teis ..................... -ooo..-ouooo..-.~--zsz. .
117

Caltulo 5 u Action Bar e temas ........


118
5.1 Introduo Action Bar ...................
5.2 Temas Holo e Material ........... 118

I Ong (alwa _ ...........


53 Projeto de exemplo sobre actil- .,..... .................... . _. 119
opoes de Visualizao dos action butt .................................... 124
127
5.5 Template de icones para os botes da action bar Ys, never, ifRoom) ............
128
Sumrio 9
5.6 Classe android.app.ActionBar ...... ...... 2 9
5.7 SearchView .............................. ....... 13 1
5.8 Action provider ........ ...... 13 3
5.9 Split action bar ............................ ...... 13 5
5.10 Up navigation ............................................................................... ...... 13 7
5.11 Navegao por tabs na action bar ............................................................ 138
5.12 ActionBarCompat - a biblioteca de compatibilidade da action bar ............ 141
5.13 Links teis .................................................................................... ...... 1 46

Captulo 6 I Interface grca - gerenciadores de layout ....... ....... ' 47


6.1 View ............................................................... ....... 1 47
6.2 Classe ViewGroup .......................................................... ....... 1 47
63 Congurando a altura e largura de uma view ..................... ...... 1 48
6.4 Entendendo as constantes wrap_content e match_parent ........ ...... 1 49
6.5 FrameLayout .................................................................... ...... 1 55
6.6 LinearLayout .................................................................... ...... 1 57
6.7 LinearLayout - controle do alinhamento layout_gravity ....... ...... 1 58
6.8 LinearLayout - controle do peso ........................................ ...... 1 59
6.9 TableLayout - uso de uma tabela com linhas e colunas ....... ...... 1 63
6.10 TableLayout e shrinl<Columns - contrao de colunas ...... ...... 1 64
6.11 TableLayout e strechColumns - expanso de colunas ...... ...... 1 65
6.12 TableLayout - criando um formulrio ...................... ...... 1 67
6.13 GridLayout ............................................. ...... 1 68
6.14 RelativeLayout ..................................... 170
6.15 AbsoluteLayout (deprecated) ............................................ ...... 1 73
6.16 Utilizando layouts aninhados para criar telas complexas ...... ...... 1 73
6.17 Criao de um layout pela API- LinearLayout ............... ....... 1 74
6.18 Criao de um layout pela API -TableLayout ............. ...... 1 76
6.19 ScrollView .................................................................... ...... 1 78
6.20 Alguns detalhes sobre a ActionBar e o up navigation ...... ...... 1 79
6.21 Layoutlnflater - inando arquivos XML ........................ ...... 1 80
6.22 Links teis ............................................. ................. ....... 1 8 1

Captulo 7 I Interface grca - View .......... ........ ' 82


71 Arquivo / res/ values/ strings.xml ....... ...... 1 82
7.2 Arquivo XML com as cores .................... ...... 1 83
73 Arquivo XML para criar um estilo CSS ......... ...... ...... ...... 1 8 4
74 Exemplo completo com estilos ................................................. ...... 1 85
75 View - A classe responsvel por desenhar elementos na tela .......... ...... 1 87
76 TextView e EditText - campo de texto para digitar informaes ........ ...... 1 88
77 AutoCompleteTextView ........................................................... ...... 1 89
78 Button e ImageButton ......... ................... _ .. 191
Google Android - 4 @d
10
193
79 CheclBox c ToggleButton ...... ._____ _ 196
71O RadioButton ................................... mm_2OO
7l Spinner ................................................ 202
7_f_2 ?rogressDialog -janela de progresso ........ HHMZOS
713 ProgressBar - barra de pr0grSS0 -~'''''' ___._._ ZQ8
7.4 'oast - alertas rpidos ................. . ........................ 209
75 AlertDialog - alertas para o usurio conrmar ......... .... 2 do
716 Layoutlnater - inflando um arquivo XML ........ ....... 2 io
7l7 List\/iew ............................... _ ......................... ....... 2 L4
7.18 .istView com adapter customizado ............. ........ 2 -8
71.9 GridView ..........................................
7.20 Gallery .......................................... 223
721
7.22 ViewPager
ViewPager ...............
+ TitleStr1p . .................
ou TabStrip . .......
....... .......
---~--2 28
723 ImageSwitcher .................................. ...... ------- 23 O
724 WebVieW ................................................................... ..-~.-- 23 2
725 Movimentando uma imagem pela tela com touch ....... ...-.-~ 23 5
7.26 Desenho manual com a classe Canvas .................. ..----- 23 3
727 Nunca utilize pixels ................................ ..----~ 2 40
Captulo 8 u Fragments ........................................................................... ........ 2 42
8.1 Como surgiram os fragments no Android 3.0 Honeycomb ......... ....... 2 42
8.2 Fragments muito mais do que dividir a tela em duas partes ....... ....... 2 44
83 API de Fragments ................................................................. ....... 2 49
8.4 Hello World fragment ..................................................... ....... 25 O
85 Utilizando fragments com action bar + tabs ....................... ....... 25 5
8.6 Utilizando fragments com action bar + tabs + ViewPager ....... ....... 25 8
8.7 Ciclo de vida de um fragment ............................................ ....... 2 61
8.8 Migrando um projeto que utiliza activity para fragments ....... ....... 2 64
8.9 Criando um layout dividido em partes nos tablets .............. ___.___ 2 72
8.10 Exemplos da API dos fragments ........................... 275
8.11 Back stack ............................................................ 278
8.12 Adicionando botes na action bar pelo fragment ...... 279
8.13 Salvando o estado de um fragment ................. 7
8.14 Vantagens de utilizar os fragments ....... .'..''' 781
8.15 Links teis ........................................ ```````
(aPtuIo 9 u Animaes .........
9.1 Drawable Animation ........ WW284
9.2 Classe Animation ...... '''~~ 2 84
93 View Animation ........ '~----- 2 85
94 AlphaAnimation ........ ~------ 2 87
.......287
Sumrio 11

9.5 RotateAnimation ...... 289


9.6 ScaleAnimation ........... .291
9.7 TranslateAnimation ........ 293
9.8 AnimationSet .............. 296
9.9 AnimationListener .......... ................... 298
9.10 Interpolator .................................................................. 298
9.11 O problema com a API de animaes no Android 2.x ...... 299
9.12 Property Animations ............................................... 30
9.13 Classe ValueAnimator ...................................... .301
9.14 Classe ObjectAnimator ....................................... 303LJ

9.15 ObjectAnimator - animao fade_in/fade_out ......... S15

9.16 ObjectAnimator - animao de movimento ......... 30 16


9.17 ObjectAnimator - animao de rotao ............ 307
9.18 ObjectAnimator - animao de escala ..................... 31"U '8

9.19 AnimatorSet - criando um conjunto de animaes ...... 340 18
9.20 AnimatorListener ...................................................... 31"U F9
4
9.21 ViewPropertyAnimator - animao do jeito fcil ......... -O
9.22 Classe ValueAnimator - outro exemplo ................... 311
9.23 Aplicando animaes no layout ........................ .......3_1
9.24 Aplicando animaes nos fragments ........................... .......312
9.25 Aplicando animaes ao navegar entre activities ............. .......3]_3
9.26 NineOldAndroids - animaes com compatibilidade ........ .......318
9.27 Linl<s teis ................................................................... .......3]9

Eaptulo 10 n Threads, Handler e AsyncTask ........ 321

10.1 Introduo ................................. .......321


10.2 Mtodo sendMessage(msg) .............. .... 324
_0_3 Mtodo post(runnable) ................................. 327
_>.4 Atualizando a view dentro de uma thread ...... ............ 328
z

4
10.5 Agendando tarefas contnuas na activity ..................................... ...... 333
'i121.6 Implementao de um tela Splash Screen para sua aplicao ........ ...... 335
10.7 AsyncTasl< ............................................................................. ...... 337
10.8 Download de imagens com a biblioteca Picasso ...... 342
0.9 Links teis ..........................................................
.

344

(aptulo 11 I Material Design .........


345
11.1 Introduo ................. 345
11.2 Tema Material ......... 346
11.3 Paleta de cores ..................... 347
11.4 Elevao de views .................... 349
11.5 Ripple -feedback ao toque ............ 352
11.6 Floating Action Button (FAB) ......... 355
Google Android - 4' 0d
112
......357
. ....... 371
.7 (;ird\/iew ...................................
RecyclerView ...................... ` ............. ..
.xg ~c0 -Qvgjgt) (Reveal Effect) ................................
.lO lixtraindo as cores de uma gura .................... g ...... ....... . 372
......3o
......39

1.11 Animaes com item compartilhado entre duas activities ...... ..... 3 78
.12 Cmpatibilidade com verses anteriores ........................... ...... 78
7.13 Links teis .............................................. ................... ----
........380
Captulo 12 | Toolbar ................ ---
12.1 Introduo Toolbar ...................................... ---~-- :
12.2 Utilizando a Toolbar como a action bar ................ ...... 8 6
12.3 Utilizando a API da Toolbar (modo standalone) ....... ------ 3
12.4 Links teis ............................_................._......... ...... 3 88

Captulo 13 n Navigation Drawer .......... ....... .... .------- 3 3 9


13.1 Criando o projeto ................................................. ...... 3 89
13.2 Customizando as cores do tema Material ........................ ....... 3 91
133 Criando a activity e o fragment base para o projeto ............... ...... 3 92
13.4 Classe Application - armazenando informaes globais ......... ...... 3 94
23.5 Biblioteca android-utils ..................................................... ...... 3 96
2.3.6 Como 0 Cradle encontrou a biblioteca android-utils ....... ...... 3 97
13.7 Congurando a Toolbar .............................................. ...... 3 98
3.8 Navigation Drawer ................................... __,__, 4 OO
3.9 Criando 0 menu overflow ........................... ,_,_,, 4 10
3.1.0 Navigation Drawer com Material Design ....... ___,___ 4 11
I3.11 Material Design no Navigation Drawer ....... ______ 4 15

.................
}3.12 Criando os fragments do projeto ............. _____,_ 4 18
_3_3 Links teis ...................................... _______ 4 21

24.1 Fragment com WebView .............. ....... 4 22


:4.2 Swipe to Refresh ...................................... 424
:43 Interceptando requisies no WebView ....... . 426
:4.4 Mostrando alertas com o Fragmentljialog .............
,_4.5 1:xecutandoJavaScript ................... 427
;IOmu'Ca9 <10JavaScripr
I ' .osmlndp COd'80 HTML no com a classe
WebView Android
............ 1
-,4.8 Links uteis .................................. ``````......433
433
oouooonunnnuonouz
Sumrio

Captulo 15 - RecycIerView e tabs ............


15.1 Criando as casses de domnio ........
15.2 Criando a lista de carros .............
153 Tabs e VieWPager .............
15.4 Navegao de telas ......
15.5 Links teis ...............

Captulo 16 I Parser de XML, JSON e testes unitrios .......


16.1 Lendo um arquivo local da pasta / res/ raw .......
16.2 Parser de XML .........................................
163 Parser de JSON .....................
16.4 Testes unitrios no Android ......
16.5 Mais informaes .................

Captulo 17 I Web services ........ ....... .......


171 Introduo .........................................................
172 Requisio HTTP para consultar o web service ......
173 Utilizando a classe AsyncTask ...................................
17.4 Biblioteca simples para encapsular a AsyncTask .........
17.5 Atualizao por Pull to Refresh .................. ...........
17.6 Vericando se existe conexo disponvel .......
177 Requisies HTTP com Get e Post ............
17.8 Web services com WSDL .......................
179 Links teis ......................

Captulo 18 - Persistncia .....................................................................................


18.1 Salvando as preferncias do usurio com a classe SharedPreferences
18.2 Activity de configuraes ..............................................................
183 Lendo e salvando arquivos ...........................................................
18.4 Trabalhando com arquivos na memria interna .........................
18.5 Trabalhando com arquivos na memria externa (SD card) .........
18.6 Outros mtodos da classe Context .....................................
18.7 Brincando de fazer cache .............................................
18.8 Banco de dados SQLite ..................................................
18.9 Criao de um banco de dados diretamente com a API ......
18.10 Insero de registros no banco de dados ........................
18.11 Atualizao de registros no banco de dados .......
18.12 Excluso de registros do banco de dados .......
18.13 Busca de registros no banco de dados .........
18.14 Mtodos da classe Cursor .................
18.15 Continuando o projeto dos carros ........
Google Android - 4' Ed5
14
._ . ~ zzdl ............. ....... _ 519
'81o \'isualizando o banco de dados com .i iu rlln:_I :c __,_,_ 520
. 521
18:17 \*isualizando o banco de dados com mn c ici c _ . ---- -~ 523
8.18 Banco de dados versus web service ....... ..... ~ ----- -~-- --~--- - - '
525
18.19 Adicionando ages na action bar .......... ---~
28.20 Editando o nome do carro ..................... sw
1.8.21 Excluindo um carro do banco de dados ...... ` ........ ...... . s;
`.8.22 Atualizando a lista com dados do web service ...... ------ ~
28.23 Modo de execuo da activity launch Mode ..... ------ S #6
28.24 Fazendo backup na nuvem .......................... ...... . O
28.25 Fazendo backup de um arquivo ..... ~--~~-~ 5
iaz 1_n1 mais ..............._............__. ..... . . ~--~-- 541
Captulo 19 u Action bar de contexto e compartilhamento ....... ...---.- 5 42
19.1 Introduo .............................................................. ...... 5 42
19.2 Detectando toques longos - OnLong(IlickListener ....... ...... 5 43
19.3 Ativando o ActionMode na action bar .................... ...... 5 44
19.4 Removendo os carros selecionados ............ ...... 5 51
l9.5 Compartilhando os carros selecionados ................. ...... 5 52
L9. Compartilhando as fotos dos carros selecionados ...... ...... 5 55
19.7 Links teis ............................................................ ...... 5 59

Captulo 20 u Intents ........................................................... ........ S 60


20.1 Intent - envio de uma mensagem ao Android ....... __.___ 5 (-,O
20.2 lntents explcitas e implcitas ........................ ______ 5 (31
20.3 Exemplos de intents nativas ....... '_____ ` 562
20.4 Permisses .............................................................................. ...... 5 68
20.5
20.6Retomando resultados
1ntentFilter de uma intent - startActivityForResult .... ...... S70
....................................................................... 5 68
20.7 Por que a MainActivity declara um <intent-lter>? .. . `577
20.8 Exemplo completo com intent customizada ..... . H `57_
20.9 Vericando se uma intent ser encontrada .'.`.' i 2
20,10 Interceptando aplicaes nativas .... ``'`' 580
20.11 Lendo cdigo de barras ............... `'`'' 581
20.12 Nomenclatura das intents ...... i ``````` S 83
20.13 Links teis ......................... '''~ 5585
85
Cliltulo 21 n Multimdia - udio, vdeo e cmera ____,_

ayer ....................
%;;*2.;f;*.1;;;*..:* e `'''''~
~~~8

;;gf1z~m.zizy@..i......z _..._._... iiziiiw" ~~ Sw
- uma
21.5 intent
do fico eYo cvieonativo
plzVideo\/iew
Cm 0 Cl21SSC er (1 . ........
'd.....
"'`''''.593
_.5 89 . 595
1
600
604
607
610
.612
.62
12 Links teis .................................... . 614

615
22.1 Introduo ............................................. 615
22.2 Google Maps Android API - Verso 2 ........ 616
223 Google Play Services .............................. 616
22.4 Gerando a chave de acesso dos mapas ....... . 617

22.5 Congurando o projeto ............................... 620


22.6 Adicionando o mapa no projeto dos carros ...... 624
22.7 Classe GoogleMap ......................................... 628
22.8 Localizao do mapa -latitude e longitude ........ ....... 629
22.9 CameraPosition - zoom .................................. 630
22.10 Gongurando o tipo do mapa ............... ........631
22.11 Colocando os conceitos em prticas ...... 632
22.12 CameraPosition ................................ 635
22.13 CameraPosition - bearing rotao .... .. 636
22.14 GameraPosition - tilt inclinao 637
22.15 Monitorando os eventos do mapa ......... 638
22.16 Marcadores ...................................................
22.17 Polyline - desenhando uma linha no mapa .....
oo neona 644 639

22.18 Links teis ................................................. 645

.........646
Captulo 23 I Google Play Services e localizao .......
646
23.1 Introduo .........................................
647
23.2 My Location ...................................................
233 Monitorando o GPS ( moda antiga) ................ 647
23.4 Monitorando o GPS (Fused Location Provider) . 649
65 0
23.5 Conectando-se ao Google Play Services ............
. 651
23.6 Obtendo a ltima localizao de forma eciente
655
23.7 API de localizao do Google Play Ser* ices .......
659
23.8 Desenhando uma rota entre dois pontos ....... 661
ouuo

23.9 Buscando um endereo .........................


23.10 Links teis .................... ......
661
Google Android - 4* ed|5
16
......662
Captulo 24 | Broadcastllecelver ....... M )
_!-LI lrurotlugw ~---~---~-~---- --~-~-~-~~'' 1 '''''''`` ' 'I `''''' ,_,,_ f uol
24.2 (`onliur;nulo u|u receiver le lorma t'F~il.l^ll`il ---'- Hom
2-l. t Lonlignrantlo um receiver' tle lorrna Llllllflllgil N37
_z__..
). ` 55 -Q|U urillilar
|,,| mat t';lSl nim` l`L'ml\'L'l`
ll\illl` :':l;lI|t't
----~---~'' '''''`''' ou_' Illtlllllt
'''`'`''''''' ' . .... . M1168
iitieiiati tle um reeeiver ao inieialivar sistema >l`'*""'"'I ''''' '''''
_!-L7 u|t~reepta|\tl tlllll II\&`l1H\l-ZN" SMS ''''^''''''' '''''''''`''''' ``'`'`''' ''''' ( ) 7 O
24,8 (fielo tlt' vltlal ...-~--~~-~---~---~- ---~-~---'--' I '~'''''' ''''' 7
2-l.l(lJelelamlo
2-W Mosrrantlo o traballio Para u|u SCl`VILL'...:.-I
urna noulieaeo para o usuario .......-.-. '''' ' 'ml
----~ _
2-l.|l links uteis ................-.z.--~~--------~ -----~~~~-~-~-'~~'' '```` l 2 /2

Captulo 25 1 Notlcatlon ................................................................................ ...... 6 73


25.1 Porque usar uma notilieaeao para se eomuniear com o ttsuario ..... ..... ( w73
25.2 (riantlo utna nt'ilita;l simples .................-.--~---~~---------------- ----- 74
25.3 *Ieatls-up tuitilieatious ................. ..... .... .-.- --~ 3
25.4 Notilieaies na tela de lwloqueio ........................................ ..... 6 82
255 lelriantlo uma zzz~t~zzzi grande (big view uoriliearions) ...... ..... 84
25.6 (Iriantlo uma notiiea`io com aes ............................... ..... (5 86
25.7 4~Il1t`t'l:tlltl uma notilieago ............._,_.,_,_,,_,_._.,. _,___ 6 88
25.8 Mais informaes sobre a elasse Pentlinglntent ...... _,_,, 6 88
25.9 -ixernplo com noril'ieao e BroatleastReceiver ........ ,,_,_ (w 81)
25.10 Mostrando uma barra de progresso na ntilit'aao _,_,_ ____, 5 )_z
lili l.inls uteis ..._,.,__,__,________,_`_____ ________',__________._'____'_. '`_._ L B

(PllI|0 26 I Il|armManagef ,,_,____,__,__,___________ ________._____________ _ _ 694


2(o.l Por que utilizar um alarme (agendar uma tarefa) _,,__, 694
292- Mmdl-l dll CllSSL' ^llll`lllM\l]|gL'|' _____,_______ ..__'_.'__ iiiii ( u
26.3 ^lzZC|l(llllLl(> um alarmf ,_.,_ _ ``''` ,S
2--4 RCPCl'lI1Ll0 0 alarm ,,,_, i iiliiii '''`` h 97
26.5 (llSSt' (alcnd;|~ _|__`__.___'___ '''''' 7m
26.6 Quando utilizar ou nao urn z.|zz.~z{z'-W" '````` ml
26.7 l.lIll<S fcig ____'''______ iiiili ---~- 7
Cililtulo 27 n Service e Joblnfo ........
llll|`()LlU;\() ______''__._' '_'.. ''' 7 O 4
{enu.ls ut 5fv<,S _'_________ ____ ...__ 704
F(::;));l:|Ulir.'c` Plfifll' LI [1] Srvju '___._ . ---
27:S lit--if E) Pi* WP iiiiiiiii .'''''''' '''`''''` ''''''''' ''~'-- -----..... . iiiii 7 ( ) 6
z z strvigo caxeeutantlo dr.-pois do ,,-
i tela de mm ''''` ''''' 7 (27
......7l.Z
Sumrio

216 Entendendo o ciclo de vida de um servio ........


217 A classe IntentService ....................................
218 Criando um player mp3 ...................................
219 Mtodo bindService(intent,con,ags) ...................................................
2110 Qual mtodo utilizar para iniciar um servio? ......................................
2111 Um servio em execuo contnua no consome muito processamento?
27.12 foblnfo - a nova API do Lollipop ........................................................
2113 Links teis ..................................... ....
Captu o 28 I GCM - Google Cloud Messaging ......... ....
28.1 O que push? ................................... ____
28.2 Como funciona o GCM ....................... ___,
283 Gerando a chave de acesso do GCM ........ ____
28.4 Obtendo o Project Number .............. ....
28.5 Executando o projeto de exemplo ........... ____
28.6 Enviando a mensagem de push .................. .......
28.7 Criando o projeto Android passo a passo ...... ....
28.8 Classe GoogleCloudMessaging ............................ ....
28.9 Congurando o projeto Android ................................ ....
28.10 Criando a activity para fazer o registro no GCM ........ ....
28.11 Links teis ............................................................ .......

Captulo 29 n Salvando o estado da aplicao ....................... ....


29.1 Troca de conguraes - conguration changes ........................... ....
29.2 Salvando o estado com o mtodo onSaveInstanceState(bundle) ...... ....
293 Salvando o estado com o mtodo setRetainInstance(boolean) ......... ....
29.4 A importncia de reter a instncia do fragment ........................... .......
29.5 Manter uma thread executando durante a troca de orientao ........ ....
29.6 Como bloquear a troca de orientao ...................................................
29.7 Dispositivos com teclado ......................................................................
29.8 Configurao android:congChanges e o mtodo onCongurationChanged
29.9 Salvando o estado no projeto dos carros ...............................................
29.10 Links teis ............................................... ..............

Captulo 30 lSUpOfI1d0 diferentes tamanhos de telas ....... ....


30.1 Unidades de medida ..................................
30.2 Tamanho de tela (screen size) ........
303 Proporo da tela (aspect ratio) ........
30.4 Resoluo e densidade da tela .............
30.5 O problema de utilizar pixels .................
30.6 DIP ou DP (density-independent pixel) ..... ....
30.7 Tabela de densidade dos dispositivos ...... .... O
Google Android - 4' 0dl
18 774
a densidade da tela ...... .--- ~ 775
308 Customizando as imagens conforme`
30.9 'I`ralmlhand com a unidade dp no Canvas ....................... 777
_3U.l0'lll1111I1l10 da tela ein dp .....................--z 777
30.11. Dimenses (dimen) ................................ 780
30.12 Qualicadores de recursos para tablets .... ........781
30.13 Links teis ............................................
783
Captulo 31 z Threads avanado - AsyncTask e Loader ....... 783
31.1 O problema com o ProgressDialog ............................... .... ..-.. 788
31.2 Conrrolando a troca de orientaao ao executar uma tas ...... ....-- 793
313 Executando a Async1ask de forma serial ou paralela .......... ....-- 794
31.4 Loader .......................................................................... ..-..-
.......808
31.5 Opinio do autor ........ .......809
31.6 Links teis ..............
Captulo 32 1 Agenda de contatos e content provider ......................................... ......... 8 10

32.2 URI- Immutable URI reference ...............................


323 Exemplos de provedores de contedo nativos ...........
32.4 Lendo os contatos da agenda ...................................
32.5 Como ler todos os telefones e a foto de um contato
32.6 Mostrando os contatos em um ListView ...................
816
32.1 Por que utilizar a classe ContentProvider provedor de contedo ............. 810

.. ........ 814
........821
812

32.7 Utilizando um CursorAdapter ........................... .......824


32.8 Utilizando um CursorLoader ............................... .......827
32.9 Monitorando a fonte de dados com um loader .......... .......828
32.10 Criando um provedor de contedo customizado ..... .......83O
32.11 Classe ContentProvider .......................................... ........831
32.12 Classe esttica Carros ......... .......838
32.13 Links teis ...................... .......84O

Captulo 33 1 SMS ..................................................

33.2 Criando um BroadcastRec ` -- ....... 841


33.1 Enviando SMS por intent ou pela API ____,____
845
333 Links teis ...................... werpara receber um SMS"""" '''''

(3PtuIo 34 n Gestos ................ 849


34.1 Introduo .........................
.......849
34.2 Reconhecendo gestos previamente .......849
343 Detectando gestos comuns, como scroll late of .......857
34.4 Detectando gesto de pinch (Zoom) ra .........
345 Ltnks teis ......................... 861
.......866
19
Sumrio

Captulo 35 I Sensores e Google Fit ................................


867
35.1 Como obter a lista de sensores disponveis ......... 867
35.2 Testando os sensores ................................... 871
353 Sensor de luminosidade ....... .... 876
35.4 Sensor de temperatura ...... 878
35.5 Sensor de proximidade ........................................ 878
35.6 Sensor de acelermetro ........................................... 879
35.7 Movendo uma view pela tela com o acelermetro ......... 886
35.8 Google Fit ........................................................... 889
35.9 Links teis ........ 898

..........899
Captulo 36 - Bluetooth ........................................................
36.1 Vericando se o dispositivo suporta Bluetooth ...... 899
36.2 Ativando o Bluetooth por programao ............. 900
363 Listando os dispositivos pareados ........................ 902
36.4 Buscar novos dispositivos Bluetooth ........................ ........ 902
36.5 Deixando o Bluetooth visvel para ser encontrado ........ ........ 906
36.6 Criando um BluetoothDevice pelo endereo ......... 907
36.7 Chat em Bluetooth ........................................... 908

36.8 Conectando-se ao Bluetooth pela serial .......... .9_8
36.9 Links teis .......................................... .9L9

..........920
Captulo 37 u Reconhecimento de voz ............
920
371 Introduo .....................................................
372 Hello TTS - faa seu Android falar .................... .........921
373 Vericando o idioma e falando em portugus ........ 927
929
37.4 Reconhecimento de voz por intent ..................
932
375 Reconhecimento de voz por um listener ......
376 Links teis .............................................. 935

..........936
Captulo 38 u Gradle ........
936
38.1 Introduo ..............................
937
38.2 Gerenciando dependncias ........
383 Trabalhando com mdulos ........ 938
38.4 Trabalhando com bibliotecas .................................. ........ 941
........946
38.5 Criando uma biblioteca ................................................. ........ 941
38.6 Configurando um servidor Maven Sonatype Nexus
38.7 Publicando no Maven Central .................................... ........ 9 46
38.8 Flavors ................................... ........947
38.9 Classe BuildCong ....... .........951
20
. ............... 953
38.10 Assinando o aplicativo para o build release ...... .. 955
Google Android - 4 ed

38.11 Links teis ...................................................


957
Captulo 39 1 Android Wear .......... 957
39.1 Introduo ............................................... ....... 9 59
39.2 Hello World Wear ............................................. ....... 9 63
393 Conectando o smartphone no Android Wear ........ ------ 965
39.4 Conectando o smartphone no relgio fsico ....... ------ 966
39.5 Noticaes no wear ......................... ; ............ ------ 967
39.6 Noticaes com vrias pginas .................. ------ 968
39.7 Noticaes empilhadas ................... ------
39.8 Noticaes com comandos de voz ....... ------ 970
39.9 Google Play Services e Wearable API ........ ------ 972
39.10 Node API ........................................... ------ 973
39.11 Message API ....................................... ......... ....... 974
39.12 Data API .................................................................. ....... 9 75
39.13 Enviando mensagens entre o smartphone e o Wear ....... ....... 9 76
39.14 Enviando uma foto tirada pela cmera para o wear ....... ....... 9 86
39.15 Criando views e layouts para Wear .......................... ....... 9 89
39.16 Criando cards (cartes) ....................................... ....... 9 90
39.17 Criando listas ............................................ _______ 9 95
39.18 Criando pginas (ViewPager) ........................ _______ 9 97
39.19 Criando pginas em grid (GridViewPager) ....... ,___,_____ 9 99
39.20 Aplicativos em tela cheia (Full-Screen) ........... ________ 1 003
39.21 Animao de conrmao .......................... ________ 1 005
39.22 Alertas de sucesso e erro ........................... 1007
39.23 Interceptando eventos em background ....... 1008
39.24 Localizao e sensores ............................ 1009
39.25 Links teis ................... 1010
Captulo 40 - Google Play ................................... 101 1
o projeto
Assinando O aplicativo el Acorretamente
1Ol4
40.1 Controle da verso de sua aplicao .............
Compilando d d. ..........................
40.4 publicando no Google 518;-.n rol Studio/Gradle ....... ...... 1 013
405 Monetizao com annCiOSmm:.:: .............................. ______ 1 Ol3
40.6 Links teis ........................... '
1016
Agradecimentos

Este livro no teria acontecido sem a ajuda de diversas pessoas, algumas pela
contribuio tcnica e outras pela motivao.
Agradeo a todo o pessoal da Wasys,Tivit e Livetouch pelos incrveis projetos de
mobilidade, e a todo o pessoal tcnico da equipe pelas ideias e sugestes.
Agradeo a toda a comunidade Android pelo feedback e incentivo para continuar
escrevendo e lanar esta nova edio.
Em especial, agradeo ao Rubens Prates, editor da Novatec, por toda a calma e
orientao em todas as etapas da produo deste livro. Seus conselhos foram
fundamentais para tudo isso acontecer.
Agradeo Ana Carolina Prates, da Novatec, por todo o apoio de sempre.
Por ltimo, agradeo a voc pelo interesse em ler esta obra. Espero que a leitura
seja simples e empolgante.

21
Sobre o autor

Ricardo R. Lecheta formado em Cincia da Computao e ps-graduado em


d Sa un,
Gesto do Desenvolvimento de Software pela PUCPR. Tem certificaes
IBM e Rational, entre elas SCMAD (JZME) e SCEA (Arquiteto).
j desenvolveu projetos em JEE e .Net, alm de mobile, para grandes empresas
como Ambev HSBC, Ita, Rede, Renault, Nissan, Coca-Cola, Unimed, Botic
rio, Banco Bonsucesso, Bovespa, UOL, Globo, Mondial, Agncia Estado, Cosan,
Metalfrio, Polcia Federal, entre outras, e nos ltimos anos vem se especializando
na integrao de sistemas legados com a plataforma mobile.
Atualmente trabalha com desenvolvimento e consultoria de tecnologias mobile
para diversas plataformas e pode ser contatado pelo email rlecheta@gmaiI.com e
no facebook.com/ricardolecheta.

22
Prefcio

Assim que a primeira verso do SDK (ambiente de desenvolvimento) do Android


foi lanada, diversos sites da internet sobre tecnologia da informao j anuncia
ram que o Google estava lanando uma nova plataforma completa e totalmente
aberta para dispositivos mveis. A notcia percorreu o mundo, e era s o que se
comentava em todos os lugares. Todos discutiam se o Android ocuparia seu es
pao no mercado e quais seriam suas vantagens sobre os concorrentes. O fato de
ser lanado pelo Google, o gigante da internet, causou ainda mais curiosidade e
expectativa de todos os lados, atraindo a ateno de muita gente, desde usurios
comuns a grandes empresas e desenvolvedores em geral.
Anos depois do lanamento, podemos constatar que realmente o Android veio
para car e vem constantemente revolucionando o mercado de mobilidade. Atu
almente o Android est disponvel para diversas plataformas, como smartphones
e tablets, TV (Google TV), relgios (Android Wear), culos (Google Glass), carros
(Android Auto) etc., e o sistema operacional mvel mais utilizado no mundo.
O objetivo deste livro apresentar ao leitor este novo e fascinante mundo do
Android, que est revolucionando o desenvolvimento de aplicaes para celulares.
Para ler esta obra, recomendado um bom entendimento da linguagem Java e
experincia com o desenvolvimento de aplicaes em geral. Cada captulo do livro
tem um projeto de exemplo, que est disponvel para download gratuitamente
no site wwu/.livroandroid.com.br.

Os captulos 1, 2 e 3 deste livro so introdutrios sobre a arquitetura bsica do


Android e explicam como instalar o SDK e configurar o ambiente de desenvol
vimento no Android Studio. Os captulos 4 a 12 explicam recursos importantes
disponveis na plataforma, fornecendo uma base slida sobre a estrutura de uma
aplicao Android.
Do captulo 13 em diante vamos estudar diversos conceitos de forma prtica, de
senvolvendo o aplicativo dos carros passo a passo. O objetivo que voc aprenda
na prtica por meio de exemplos, variando do bsico ao avanado. O livro tambm
est atualizado para a ltima verso do Android e padres do Material Design.

23
24 Google Android - 4' edio
No nal ainda temos captulos especficos stwbre o novo sistema de builds do
Android (Cradle). desenvolvimento de aplicativos para relogios (Android Wear)
e corno publicar um aplicativo no Google Play
Espero que a leitura deste livro seja simples e ao mesmo tempo empolgante, que
os exemplos e explicaes possam l ief *er uma base slida para desenvolver
ornee
timas aplicaes e que voc possa aproveitar ao mximo o mercado de mobile,
que no para de crescer e est sempre procura de bons prossionais.

Ricardo Lecheta
http://facebook.com/ricardolecheta
https://pl us. googl c. com/ +RicardoLecheta
https://twitter com/rlecheta
` cAPruLo
Introduo ao Android
\___

1.1 Introduo
Nos dias de hoje, ningum consegue car longe de um celular, seja para mandar
um email, tirar uma foto, assistir um vdeo, conversar com os amigos, navegar
na internet, acompanhar as redes sociais etc. Portanto, os smartphones e tablets
atualmente so objetos praticamente inseparveis da maioria das pessoas.
Segundo pesquisas, mais de 3 bilhes de pessoas tm um telefone celular, e o
mercado de aplicativos virou uma febre, rendendo bilhes todos os anos.
Nesse mercado competitivo, temos vrios lados da moeda. Os usurios comuns
buscam um celular com um visual elegante, moderno, de fcil navegao, assim
como uma innidade de aplicativos e recursos. Tanto as empresas quanto os desen
volvedores buscam uma plataforma moderna e gil para desenvolver aplicativos.
Os fabricantes (LG, Motorola, Samsung, HTC, Intel, Sony etc.) precisam de uma
plataforma robusta e rica em funcionalidades para lanar no mercado os seus
produtos. E aqui onde o Android se encaixa, pois ele perfeito para todos os casos.
O Android o sistema operacional mvel do Google e atualmente lder mundial
nesse segmento. No entanto, o sucesso do Android no se deve apenas fora do
Google - por trs do desenvolvimento de toda a plataforma esto gigantes do
mercado de mobilidade, como fabricantes de celulares e operadoras. Esse grupo
que ajuda no desenvolvimento da plataforma chamado de OI-IA (Open Handset
Alliance) e conta com nomes de peso como Intel, Samsung, LG, Motorola, Sony
Ericsson, HTC, Sprint Nextel, ASUS, Acer, Dell, Garmin etc. Existe todo um
ecossistema interessado no desenvolvimento de uma plataforma mvel poderosa e
flexvel, de cdigo-aberto e que atenda s necessidades de todos. Embora o Google
represente grande parte da fora do Android, com certeza a plataforma est hoje
onde est devido ajuda de outras potncias do mercado mvel.

25
Google Android - 4 d

26
' d' vel vara diversas plataformas, como smarfplwnes
Atualmente oAndroid esta 1SPon } _ ~ , . 1 S (Goflgle Glass), carros
6 tablezg, TV (Google TV), relogios (Android,Wear),.ocu
mais utilizado no mundo.

. . zi '- _ 0
eracional movel

aseusseu
(Android Auto) e o sistema op ' bm est ca da vez mais utilizando 0
Vale lembrar que o mercado corporativo tam 0 rca es mveis
mobile, tanto que diversas empresas esto buscando incorpoflf ali l ,veis com

sis e - - _
da a dia ara agilizar seus negocios e integrar as ap ICHOS m
` t mas d) back end Empresas obviamente ortante
visam oespao
lucro; por
em isso, tar1IO
um mund0
05 smartphones quanto os tablets ocupam um imp u
em que a palavra mobilidade est cada vez mais conhecida.
Dentro desse contexto, estamos diante de uma excelente oportunidade, pois o mobile
um grande pilar na rea de tecnologiaisso
e segundo pesquisas
voc no e uma
pode car foradas areas que
dessa.
mais vai crescer nos prximos anos, por
O objetivo deste livro explicar o desenvolvimento de aplicativos para Android,
do bsico ao avanado, com diversos exemplos prticos e dicas de que voce vai
precisar no dia a dia.

A._7
1.2 Open Handset Alliance e o Android
A Open Handset Alliance (OHA) um grupo formado por gigantes do merca
do de telefonia de celulares liderados pelo Google. Entre alguns integrantes do
grupo esto nomes consagrados como Intel, HTC, LG, Motorola, Samsung, Sony
Ericsson, Toshiba, HTC, Huawei, Sprint Nextel, China Mobile, T-Mobile, ASUS,
Acer, Dell, Garmin e muito mais.
Quando 651 livro f0i SCfif0, O grupo era formado por 84 integrantes de peso
e voce pode verificar a lista completa e atualizada em: wwwopenhandsetalliance.

No st ' ' ' - ~ , _


com/oha__members.html.

1 e da OHA existe uma otima descriao do que e essa aliana. O texrg ggt

um d - .
em ingls e vou apenas traduzir uma breve citao aqui. Hoje, existem 1,5 bilho
de aparelhos de televiso em uso em todo o mundo e 1 bilho de pessoas tm
lar tornando o a arelho One Ce u
acesso internet. No entanto, quase 3 bilhes de pessoas tm um telef 1

- , construir um aparelho cel l ' . ,

, . or ' '
mllndo Dessa folma .OS produtos de consumo mais bem-sucedidos do
pessoas
de inmeras u arem
superior
ecno o ` ' - _
todo melhoraria
o mu . a vida
formado por empresas lderes emt ndp. A Open Handset Alliance um grupo
para muar xpaC er..movel
iencia . , gldemovel
todos osque compartilham essa viso
consumidores
Assim, o objetivo do grupo denir uma lataf
lares para deixar os consumidores mais s-
is eiftos
_ ma unica
com e abertanal.
o produto paraOutrg
celu
Captulo 1 i Introduo ao Android 27
objetivo principal dessa aliana criar uma plataforma moderna e exvel para
o desenvolvimento de aplicaes coorporativas. O resultado dessa unio, como
voc j deve saber, foi o nascimento do Android.
Todos acabam se beneficiando com os avanos alcanados pelo grupo OHA e a
plataforma do Android: os fabricantes de celulares, os usurios comuns e, claro,
as empresas em geral e os desenvolvedores de aplicaes.
Os usurios de celulares so extremamente favorecidos com tudo isso. Hoje em
dia, todos querem um celular com um bom visual, de fcil usabilidade, com
tela touch screen, cmera, msicas, jogos, GPS, acesso internet e muito mais,
e o celular cada vez mais ocupa um espao importante na vida das pessoas. O
Android foi criado justamente para agradar esses usurios, possibilitando que
encontrem todos os recursos esperados em apenas um aparelho. O mundo da
tecnologia est sempre em evoluo, e a OHA tem como objetivo principal manter
uma plataforma-padro na qual todas as novas tendncias do mercado estejam
englobadas em uma nica soluo.
Para os fabricantes de celulares, o fato de existir uma plataforma nica e consoli
dada uma grande vantagem para criar novos aparelhos. A grande vantagem para
eles que a plataforma tambm livre e de cdigo aberto. A licena do Android
flexvel e permite que cada fabricante possa realizar alteraes no cdigo-fonte
para customizar seus produtos, e, o melhor de tudo, sem necessidade de com
partilhar essas alteraes com ningum. O Android tambm free' portanto, os
fabricantes podem usar e abusar dele sem precisar pagar por isso.
O fato de o Android ser de cdigo aberto contribui muito para seu aperfeioamen
to, uma vez que desenvolvedores de todos os lugares do mundo podem contribuir
para seu cdigo-fonte, adicionando novas funcionalidades ou simplesmente
corrigindo falhas.
j os desenvolvedores de aplicaes podem desfrutar de uma plataforma de de
senvolvimento moderna com diversos recursos incrveis, com tudo o que h de
mais moderno. Este o tema deste livro: o desenvolvimento de aplicaes com o
Android. E aqui voc vai entender o porqu de toda essa revoluo.

1.3 Sistema operational Linux


O sistema operacional do Android baseado no kernel do Linux, que respon
svel por gerenciar a memria, os processos, threads, segurana dos arquivos e
pastas, alm de redes e drivers.
28
_ ~operaCl0
- - ocesso no sistema ' nal. Google Android - 4 2d

Al uns deles
~ - 'bir odem
uma te a para 0cxi
uSU_ .A_.
Cada aplicativo no Android disparq um novo primo e Outros podem car em
.g- qo em gundo plano por tempo indeterminado. Diversos processos eapll
Uicwg P AL
cativos os simultaneamente,
podem ser executade o kernel
I _do sistema operacional
o responsvel por realilf odo o controle de mem0fl21
, . z - decidir encerrar al um
Caso necessario, o proprio sistema oper8Cl0U3l Pf>d<{ _ _ g O

. _ , z - a vez
processo para libera r memria e recursos, e talvez ate reiniciar o mesmo proCeSS
d situa
posteriormente quan o a o
estiver controlada.
Toda a segurana do Android baseada na segurana do Linux. No Android,
cada aplicaao e executada em um unico processoe cada processo porlsu .
contm um a thread dedicada. Para cada aplicao instalada no celular e criado
um usurio no sistema operacional para ter acesso a sua estrutura de diretrios.
Dessa forma, nenhum outro usurio pode ter acesso a essa aplicaao.

1.4 Cdigo aberto e livre

O Android a primeira plataforma para aplicaes mveis completamente livre


e de cdigo aberto (open source), o que representa uma grande vantagem com
petitiva para sua evoluo, uma vez que diversas empresas e desenvolvedores do
mundo podem contribuir para melhorar a plataforma.

Para os fabricantes de celulares, isso tambm uma grande vantagem, uma vez que
e possivel utilizar o sistema operacional do Android em seus celulares sem ter de
pagar por isso. Alm disso, a licena Apache Software Foundation (ASF) permite
que alteraes sejam efetuadas no cdigo-fonte para criar produtos customizados
sem precisar compartilhar as alteraes com ningum.

Voce pode obtermaisinformaes e at fazer o download do cdigo-fonte do


Android no seguinte site: http://sourcaandroid.com/.

S ,
-,.m _ .
1.5 Mquina virtual Dalvik
Provavelmente voc '
J abs que
aplicaes para o Android. 3 lmgugem Java e utilizada para construir as
O fato
uma mquina virtualjava
. a verdade o ueUVM)
e que em seu sistema operacionalN
temos u ' '5' E
no exi t
chamada Dalvik que e otimizada , ~ q . . _ a maquma vlrtual
para XPCUGO em dispositivos mveis.

eAotodos
desenvolver as aplicaes para o Android voc v - .l. _
os seus recursos 2norm
m 1 ' _al uu lzar 3 linguagem Java
ente, mas depois que o bytecode (.c1ass)
Captulo 1 in Introduo ao Android 29
compilado ele convertido para o formato .dex (Dalvik Executable), que representa
a aplicao do Android compilada.
Depois disso, os arquivos .dex e outros recursos como imagens so compactados
em um nico arquivo com a extenso .apk (Android Package File), que representa
a aplicao final, pronta para ser distribuda e instalada. Ao utilizar o ambiente de
desenvolvimento do Android Studio, toda essa compilao e gerao do arquivo
.aple ocorre automaticamente, portanto, no preciso se preocupar com isso.
Atualmente, o sistema de build utilizado o Gradle, o qual independente do
Android Studio e pode ser executado separadamente. Portanto, voc pode com
pilar todo o cdigo por linha de comando se necessrio.

1.6 Mquina virtual ART (Android Runtime)


A partir do Android 4.4 (KitKat) foi criada a mquina virtual ART (Android
Runtime) com o objetivo de substituir a Dalvik, e naquela poca o ART podia
ser ativado opcionalmente nas configuraes. Quando foi lanado o Android 5.0
(Lollipop), o ART se tornou a mquina virtual padro, substituindo a Dalvik.
Uma das melhorias do ART a compilao Ahead-of-time (AOT), que tem o obje
tivo de otimizar o cdigo ao mximo para melhorar o desempenho do aplicativo.
O ART tambm tem um melhor funcionamento do Garbage Collector (GC) e
apresenta melhorias no suporte ao debug de aplicativos.
Na prtica os desenvolvedores ou usurios no so afetados se o sistema est
utilizando a Dalvik ou ART, mas o Google afirma que o ART apresenta um de
sempenho muito melhor.

1.7 Conhecendo um pouco mais sobre o Android


Todo celular tem uma tela inicial com alguns cones e um menu, certo? Todo ce
lular tambm tem uma agenda de contatos e uma tela para fazer a ligao, no ?
Agora, voc j pensou em trocar algumas dessas telas por uma tela customizada
desenvolvida por voc? Com o Android isso possvel. Sua arquitetura muito
flexvel e voc pode integrar aplicaes nativas com sua aplicao, ou at mesmo
substituir qualquer aplicao nativa existente por uma que voc mesmo criou.
isso que muitos fabricantes e operadores fazem ao customizar os aparelhos.
possvel integrar aplicaes de uma forma simples, sejam elas desenvolvidas
por voc, sejam aplicaes nativas. Por exemplo, imagine que sua aplicao
Google Androld - 4 d
30

precise consultar a agenda de contatos para selecioinpr dcte1;l:iI:1;l<>a2ll;;: (


Whats/\PP). e lol dPl5 Visuahzar O cndercgo ce ld d l bem, mas
existe a agenda de contatos e o Google MHP5 O Andrf io fila Sa qm Sm;
ser que possivel utiliza-los e integra-los em nossas apllC3%05- l;5P~ ft um;
jmcgmo uma das palavras-chaves em aplicaoes coorporativas, c a arqui c
do Android foi criada justamente pensando nisso.

, - ~ ' ~ ~ ' ' re


Nota: o Android tem muitos diferenciais in
(I`SSl'lS G Uml ll'qLlll[Ul'Ll

realmente flexivel focada na integraao de aplicaoes. Nao existe diferena em


uma aplicao nativa e uma desenvolvida por voce.

Falando em integrao, existe uma classe que o corao do Android, chamada


de Intent, a qual vamos estudar no livro. Essa classe nada mais e do que uma men
sagem enviada ao sistema operacional informando nossa inteno de realizar
determinada tarefa.
Ento, no sistema operacional do Android, mensagens so disparadas para todos
os lados, identificadas pela classe Intent. Conforme o contedo da mensagem,
ela pode ser interceptada por qualquer aplicao interessada a m de realizar a
tarefa que for necessria. Por exemplo, se voc deseja abrir uma aplicao nativa
como o browser ou abrir uma nova tela de sua aplicao, a nica coisa que voc
precisa fazer criar esse objeto Intent e congurar o contedo de sua mensagem
corretamente para ser interpretado pelo sistema operacional.
Outro ponto forte do Android que seu sistema operacional baseado no Linux, o
qual se encarrega de gerenciar a memria e os processos. Isso permite que diversas
aplicaes possam ser executadas ao mesmo tempo, de forma que as aplicaes

claro ` . _
em segundo plano consigam executar sem atrapalhar a atividade do usurio
enquanto ele est acessando a internet ou atendendo uma ligao. 3
_ I qfl 020 podemos nos esquecer dos recursos visuais e todas as APIs
_ er abertoque
e totalmente customizado
disponiveis, mas o fato de o Android s '
diferencial vale a pena ressaltar 6 um

1.8 Android Developer Challenge


Agora vamos falar L . un ouco da h' ' ' ~ _ .
. u , Oog ecome `ou in ~ ' ..
verde. Para PromoveroPl)ndroid o Glstmlla do Slsttma Operacional do mbozinho
3 lI'uueira verso do SDK foi lzulgatlu tambmgf ` vwtlnd pcddo e* asslm que
Android Develoher (hallen 3
vt; /Al) ` t u .ol mais
A ('l\Ul1l ammuad O 10
de U$ f=1m<>S<>
milhes CUCUTSOem prmios.
Captulo 1 I Introduo ao Android 31
Apenas por curiosidade, eu j trabalhava com mobile desde 2001 e foi nesse
momento que me encantei com o Android e comecei a escrever a 13 edio deste
livro, que ficou pronta em 2009, pouco depois da la fase deste concurso terminar.
O prazo para enviar as aplicaes do ADC era 14 de abril de 2008, e o concurso
foi dividido em duas fases. Na primeira fase, as 50 melhores aplicaes recebiam
US$ 25 mil e, na segunda, mais 20 das melhores aplicaes seriam selecionadas
para receber US$ 275 mil, e algumas US$ 100 mil.
Na primeira etapa, as aplicaes foram testadas no prprio emulador do Android,
porque na poca nenhum celular com o Android tinha sido lanado. Isso foi uma
grande sacada do Google para melhorar a plataforma e ajudar a test-la, sendo
que desenvolvedores de todo o mundo estavam interessados em desenvolver as
aplicaes para talvez faturar uma bolada. Esse concurso literalmente agitou o
mundo todo, com isso o Google conseguiu testar o SDK e consolidar seu produto.
A segunda parte do concurso foi anunciada para acontecer somente depois que
o primeiro celular com o Android fosse lanado, dessa vez as aplicaes seriam
testadas em um aparelho real e no mais em um emulador.

1.9 Google Play


Para auxiliar a distribuio das aplicaes do Android, alm da divulgao de
sua nova plataforma, foi criado o site Google Play (https://playgoogle.com), que
inicialmente se chamava Android Market. O objetivo do site fornecer aos desen
volvedores de aplicativos um lugar comum para disponibilizar suas aplicaes.
Para publicar uma aplicao, o desenvolvedor precisa pagar a taxa de US$ 25 (o
pagamento feito uma nica vez por meio de um carto de crdito internacional)
e concordar com os termos de uso. Depois disso, o aplicativo j pode ser publi
cado e instalado pelos usurios. Existem aplicativos que so gratuitos, enquanto
outros so pagos. Uma boa notcia para os desenvolvedores que 70% dos lucros
com os aplicativos vendidos sero repassados para quem os construiu. Para mais
informaes, visite o site do console do desenvolvedor no seguinte endereo.
https://playgoogle.com/apps/publish/

1.10 T-Mobile G1
O T-Mobile G1 desenvolvido pela HTC foi o primeiro celular lanado com a
plataforma do Android e, como esperado, agitou o mercado. A notcia_de seu
\CI
Google Android - 4 d
32
. _ - ~ s ex vectativas de vendas da
lanamento causou um grande impacto e superll 21 1 ddos de pr
HTC: mesmo antes de seu lanamento, todo o estoque para os p
-venda j havia sido esgotad.
a ser vendidos nos Estados UnidoS
Os primeiros celularesS$HTC G1 comearam , _
179. Um fato interessante e que eu termml
no dia 22 de outubro de 2008 por U
G1 l n ado e fiz todos meus estudos
a 1" ediao deste livro antes mesmo de o ser a _ ' _
1 curso de Android que 11lSU`l
somente utilizando o emulador. Lembro que no
alguns alunos tinham comprado o G1 e vieram mf! ITIOSUQC F01 @m0C10"3me'

1.11 Google Nexus


Desde o HTC G1 at os dias de hoje, o Android no parou de evoluir, e na po
ca em que este livro estava sendo escrito o Google havia acabado de lanar seu
smartphone Nexus 6, com Android 5.0 Lollipop, tela Quad HD de 6 polegadas
com 2560 x 144Opx e um processador quad core de 2.7 Ghz; o mais rpido de
todos os smartphones Android j lanados at o momento.
Recentemente, tambm foram lanados os tablets Nexus 7 e Nexus 10 do Google,
com telas de 7 e 10 polegadas. No site da linha Nexus, voc pode encontrar sem
pre os modelos mais atualizados dos smartphones e tablets ociais do Google.
Uma das vantagens de ter um smartphone Nexus porque eles so chamados de
Android puros, ou seja, no contm customizaes. E por serem gerenciados pelo
Google sempre recebem a atualizao de novas verses do sistema operacional de
forma rpida. Para mais informaes sobre a linha Nexus, e uma tima explicao
dos recursos do Android, visite 0 site:
http://www.goog1e.com.br/nexus/.

-._~1e
1.12 Um pouco sobre a histria e verses do Android

A verso 1.0 do Android chegou no mercado em 2008 com o famoso 'l` Mob`l

. - ~ ersao
c.,._ea e `
Gl, 6 depois o Android nao parou mais de evoluir,

Algo interessante e engraado sobre 0 Android que cada nova v ` ' 1


:inda
. pecarmhosamene com
ativa e especu o nome
a to de um
no mer ' doce. Isso gera sempre uma grziandle
, z 9 _oado
sera novoP015 t0d0s do
sabor ficam tentando adivinhar
Android * qu?-1I
Na1edi*
-_
Qdozestedlivro
quer 'expli
o 'que era o A ' . . , _
01 L osisttm. -~..
Pouco d1ferente,P0is o Andr ` 1 1 - ndri)ld` mas agora 3 hlstorm 9 Um
1 Operacional movel mais utilizado no
Captulo 1 il Introduo ao Android 33
mundo; por essa razo, acho conveniente explicar um pouco de sua histria, e o
que cada verso trouxe de novidades para a plataforma.

1.13 Android 1.5 (Cupcake)


Lanado em abril de 2009, o Cupcake (Figura 1.1) trouxe na poca diversas me
lhorias para o sistema operacional, como na parte de cmera, GPS, upload de
fotos e vdeos para o YouTube e Picasa etc.

Figura 1.1 -Android 1.5 (Cupcake).

A principal novidade, porm, foi o lanamento do primeiro Android (HTC Magic)


com apenas o touch screen e o teclado virtual. Foi no Cupcake que nasceram os
widgets, que so miniaplicativos que podem executar na tela inicial.
Fontes:

http://developer android. com/about/versions/android-1.5. html

http://developer android.com/about/versions/android-1.5-highlights.html

1.14 Android 1.6 (Donut)


Lanado em setembro de 2009, o Donut (Figura 1.2) inovou e fez o Android falar
e escutar.

Converter texto em voz o que chamamos de Text-To-Speech (TTS), e o contrrio,


converter voz em texto, chamamos de Speech-To-Text (STT). Com o auxlio das
pesquisas de voz, a home do Android ganhou mais funcionalidades e o usurio
poderia pesquisar na agenda de contatos, na galeria de msicas e na web com a voz.
Google Android - 4 0d
34

~_I. -1
, 'mw ~f

, ~ ' e an o Figura 1.2 -Android 1.6 (Donut).

No Android 1.6 foram criadas as medidas de densidade (ldpi, mdpi, WCP) que Vamos
estudar ao longo do livro, pois foi quando o Android passou a ser utillilzadodpo;
dispositivos de diversas resoluoes e tamanhos de tela. O Android estava c g rcado.
um novo patamar e comeando a ser amplamente utilizado e adotado pelo f1'l
Fontes:

http://developer android.com/about/versions/android-1.6.html

http://developer android.com/about/versions/android-1.6-highlights. html

1.15 Android 2.0 e 2.1 (Eclair)


Lanado em outubro de 2009 e depois atualizado em janeiro de 2010, o Eclair
(Figura 13) trouxe uma interface de usurio diferenciada e adicionou os Live
Wallpapers (plano de fundos animados na tela inicial).

`unt ` - . Figura 1.3 - Android 2.1 (Eclair).

No Eclair foi lanado o suporte a mltiplas contas do Google e sincronizao


(J o com aAPI), assim como diversas melhorias em todo o sistema operacional
como nas cameras, mapas e o suporte ao HTML5
3

Fontes:

hPf//developerandroid.com/about/versions/android2_O_ html

http://developerandroid.com/about/versions/android-2.0-highligh[5 hzml
'1P=//dfvelpfrandfoid. com/about/versions/android-2.1. html
Captulo 1 I Introduo ao Android 35
1.16 Android 2.2 (Froyo)

5
Lanado em maio de 2010, o Froyo (Figura 1.4) trouxe diversas melhorias de de
sempenho para o sistema operacional, como o compilador JIT Uust In Time) e
uma engine de JavaScript mais rpida.

` ,.'' 'i

Figura 14 - Android 2.2 (Froyo).

Nessa verso foram adicionados recursos clssicos como o USB Tethering e Wi~Fi
Hotspot, assim como o suporte ao Flash.
Fontes:

http://developer: aridroid.com/about/versions/android-2.2. html

http://developer aridroid.com/about/versions/android-2.2-highlights.html

1.17 Android 2.3 (Gingerbread)


Lanado em dezembro de 2010, o Gingerbread (Figura 1.5) trouxe novidades na
cmera, pois era possvel alternar entre a cmera frontal e traseira. Tivemos me
lhorias na funcionalidade de copy-paste, pois era possvel tocar o texto e depois
arrastar para controlar a seleo.

Figura 1.5 - Android 2.3 (Gingerbread).


36
_ e ir
. ~1 (- oo
_ .Ile,
. rfoi~ nessa
` = 3versao
um que
glande ganho com
tivemos Urela0
i _ 80
Skgunm ( ' 5 . z , . . 2 1(N *z Field C(_)I`ITlLll1lC8l()n5)
gerenciamento da bateria e surgiu o supor tc ao Nl (
Fontes:
Google Android - 4 Ed

ht tp://clevc1pcn android. com/ahout/versions/android-2.3. html

hit p://de vel open aridmid. ;om/ahut/ versions/and roid-2.3 -hi ghli ghts. html

1.18 Android 3.0 (Honeycomb)


Lanado em fevereiro de 2011, o Honeycomb (Figura 1.6) trouxe um sistema opera
cional totalmente focado nos tablets, com uma experincia de usuario totalmente
diferenciada para telas grandes.
Como Honeycomb, o Android deixou de ter botes fsicos, e os botes de voltar e incio
(home) passaram a fazer parte da barra de navegao dentro da tela com touch screen.
Foi nesta verso que tambm foi criada a action bar, que 0 padro de navegao mais
utilizado nos aplicativos para Android atualmente, e tambm a API de fragments, que
permite criar componentes reutilizveis de cdigo. Ambas as APIs so fundamentais
no desenvolvimento de aplicativos e por isso vamos estud-las em detalhes neste livro.
Fontes:

http://developer:android.com/about/versions/android-3.0. html

hl tp://developen android. com/about/versions/android-3.0highligh ts. html

Figura 1.6 - Android 3.0 (Honeycomb).

1.19 Android 4.0 (Ice Cream Sandwich)


Lanado em outubro de 2Oll o Ice Cream Sand . 1
tafmma de deSenvOlvimcnt,emr Sn1 iones
mpi wicie [figura
ta eisl.7)- unicou
~
r , permitindo eom
21 Pia
que
Captulo 1 1 Introduo ao Android 37
aplicativos para smartphones fossem criados com a action bar e fragments. Com
o ICS, o mesmo sistema operacional agora executava em tablets e smartphones.

Figura 1.7 - Android 4.0 (ICS).

AAPI de fragments utilizada para criar componentes reutilizveis de cdigo, por


isso ela tem muita importncia ao reaproveitar o cdigo de um aplicativo entre
as verses para tablet e smartphone.
Fontes:

http://developer android.com/about/versions/android-4.0. html

http://developer android.com/about/versions/android-4.0-highlights.html

1.20 Android 4.1 (Jelly Bean)


Lanado em junho de 2012, ojelly Bean (Figura 1.8) voltou a trazer ganhos signicatvos

i,. E
'\\
com relao ao desempenho do sistema, e todo o sistema operacional ganhou me

V\'~
'
lhorias no suporte s animaes, deixando a interface mais sensvel ao toque e fluida.
`= ..,`J .` ''
' ie.
~. ;?``
p, -...,., * g._5 _.
.x;._4_ -zzigg . ,Y-,.z,_

=. W
Q f ;>~,~E~<f
_ ifz -*
~:> -z.
EQ*
`~'
.,.. ,,. _ _,
' .;'- fff .~

Figura 1.8 - Android 4.1 (lelly Bean).


33 z - . ~ nter . __ ..azSU
_ , . l wassaiam
As notificaes que so tamosas no Androic 1
~ aisricasw
m
Google Android - 4 edi0

muitos detalhes.
Hmtc

Iztf['//d'v1]er:mdroid.umr/about/vcrsin5/cuybcan'html

1.21 Android 4.4


- . (KIKl
xe oAn roid para
d I Odm
e*
. - , . ~ z z* na ines ~ ~
~
Lanado em Outubro de 2013, O KHKM (hgulra 1.9ti1:(fLrl1 dispositivos com menos
pois conseguiu executaro sistemaoperacio _ _ 8 es
d 512MB de RAM devido s diversas melhorias de desempenho e ot1mlZ
feitas no sistema operacional.

Figura 1.9 - Android 4.4 (KitKat).

O KitKat trouxe aperfeioamentos no Bluetooth, NFC, Print Framework, senso


res, e foi criada a API de Transitions, que possibilitou aos desenvolvedores, no
s criarem interfaces visuais em cenas, como tambm animar a transio entre
uma cena e outra.

Na verdade, a plataforma do Android evolui to rpido, que para um resumo


completo recomendado olhar a documentao ocial.
Fonte:

http://developerandroid.com/about/versions/kitkat. html

1.22 Android 5.0 (Lollipop)


Lanado em novembro d ' '
na int, f ' d z . 6 2Vf<>L01l1pp<Figufz 1.1O) foi o maior release focado
U ace C u5ua Usabllldad, animaes e experincia do usurio.
Captulo 1 I Introduo ao Android 39
1.
L 1 /f
vi ff, j

lc'
Figura 1.10 - Android 5.0 (Lollipop).

Nasceu ento o Material Design, que um guia completo sobre como implementar
o visual, animaes e a interao entre os componentes de um layout, levando
em considerao que o Android se tornou uma plataforma comum para vrios
dispositivos, como smartphones, tablets (Android), Wearables (Android Wear),
culos (Google Glass), TVs (Android TV) e carros (Android Auto).
Isso o mais importante, uma vez que as tcnicas do Material Design no precisam
ser implementadas somente nos smartphones e tablets, pois o Google criou um
padro de design consistente entre vrias plataformas, como mobile, Web, Wear etc.
Dentre outras melhorias, tivemos as noticaes, que agora tambm aparecem
na tela de bloqueio (Lock Screen), e as head~up notications, que aparecem no
topo da tela com alta prioridade. Um exemplo de head~up notications a ligao
que permite atender ou rejeitar uma ligao telefnica diretamente na noticao.
Antigamente, esse recurso no existia e a aplicao da ligao mostrava uma tela
cheia para o usurio decidir se atende ou no a ligao.
Outra novidade interessante foi o projeto Volta, que trouxe ferramentas para
auxiliar a anlise do uso da bateria nos aplicativos. Tambm foi modicada a tela
de aplicativos recentes (Overview Screen), que mostra as ltimas tarefas que esto
sendo executadas, sendo que um aplicativo pode conter uma ou mais tarefas. Foi
criada uma API para os desenvolvedores controlarem esse comportamento. O
Lollipop tambm suporta a OpenGL ES 3.1, trazendo um desempenho superior
nos jogos 2D e 3D.
A plataforma do Android est chegando a outro patamar, e o Google TV tambm
recebeu um grande release. Foi criada a API Leanback para criar interfaces ricas
para TV e o TIF (Android TV Input Framework).
Novamente, so tantas as novidades que recomendo olhar a documentao oficial.
Fonte: http://developer android.com/about/versions/lollipop.html
Google Android - 4 edi

_ , , _ ve
40

1.23 Google I/O 2015 e o anncio do Android M

No Google i/o 2015 foi anunciado o Android M, qlj @_ 21 Pfffvla ]P1faleif';le O


dores da nova verso do Android. A letra M da sequencia 3 letra 6 O ypvgso

. . . - ze
_ z ' e outros.
Google est seguindo essa nomenclatura agora. Porem, oficialmente a nowa mo
do Android deve ser lanada entre outubro e novembro de O15, e somente 6
o esta versao comea com a letra
saberemos qual o novo sabor do Android. Com
M, algumas das suspeitas sao os famosos doces MGIM S, MCHIOS, dmf
Dentre as melhorias j anunciadas f r
no Android M, temos um leitor de imprSS0
digital com sensor biometrico e o Android Pa); uma plataforma aberta para 2
pagamentos por meio de cartes, internet e NFC.
Uma das funcionalidades que achei mais interessante o novo sistema de con
trole de permisses dos aplicativos, o qual possibilitar que 0 usurio conceda a
permisso individualmente. Ser possvel optar por dar acesso cmera enquanto
nega-se a permisso para acessar o GPS, por exemplo.
Outra funcionalidade do Android M muito comentada so os App Links, que
permitem que determinados aplicativos sejam escolhidos como padro ao abrir
links de determinado domnio. Exemplos clssicos so os apps do Tvvitter, Google
+ e Drive, e nesse caso qualquer link desses domnios pode ser aberto diretamente
em seus respectivos aplicativos sem a necessidade de perguntar ao usurio qual
aplicativo deve ser escolhido.

O Google Now tambm recebeu atualizaes e agora ele pode ser chamado
diretamente da tela de bloqueio, pela opo no canto esquerdo inferior da tela.
Enm, agora esperar pela nova verso do Android. No entanto, como desenvol
vedor, voc vai perceber que no Android SDK possvel baixar a verso prvia do
Android M e j ir brincando com o emulador.

Neste livro, vamos aprender a criar aplicativos para Android. Na maioria das
vezes, vou tentar manter a compatibilidade com as vers es antigas, at porque 0

bilidad ~ - . . P
que iremos estudar so os conceitos principais do Android

Felizmente o Google vem fazendo um excelente trabalho no suporte com ati


e com versoes 3m18S, C podemos utilizar novas funcionalidades por meio
de bibliotecas de compatibilidade. U
m exemplo disso a biblioteca de com ati
bilidade V7 que traz 30 AYO 2-1 (EClair) a funcionalidade da action barp
foi criada apenas no Android 3.0 (I-Ioneycombj que
Captulo 1 n Introduo ao Android 41
No livro, sero exploradas diversas APIs de desenvolvimento, do bsico ao avan
ado. Vamos focar boa parte em boas prticas de programao e interface de usu
rio, seguindo sempre as recomendaes (guidelines) do Google. Para isso, ser
desenvolvido, passo a passo durante a leitura, o aplicativo dos carros, explorando
muitos conceitos do Material Design.
Tenho certeza de que voc, ao ler este livro, vai adquirir uma base slida referente
a todos os conceitos do Android, desde o bsico ao avanado. Naturalmente, a
plataforma no para de evoluir, mas estou certo de que no nal da leitura voc
estar apto a acompanhar essa evoluo.
cAPiruLo 2
(ongufao do ambiente
ri
l
J .de desenvolvimento
V #7 _ _.,

_ - ~ ` ' essrio ins


Para iniciar o desenvolvimento de aplicaoes para o Android, e nec, .
talar o SDK que contm o emulador e todas as ferramentas necessarias para O
3

desenvolvimento.
Este captulo aborda a instalao do SDK e a congurao do ambiente de
desenvolvimento no Android Studio. Para validar a configuraao do ambiente,
criaremos um simples projeto para testar o emulador.

2.1 Android SDK

O Android SDK o software utilizado para desenvolver aplicaes no Android,


que tem um emulador para simular o dispositivo, ferramentas utilitrias e uma
API completa para a linguagem Java, com todas as classes necessrias para de
senvolver as aplicaes.

O Android SDK pode ser encontrado neste endereo: http://developer android com/sdk/.

Neste livro vamos utilizar o Android Studio para desenvolver aplicaes para
Android. No se .preocupe com o SDK neste momento, pois vamos baixar o
Android Studio e ele j contm o SDK.

O Android S ` " . .
2.2 Requisitos de software e sistema

tudio e SDK sao suportados nos seguintes sistemas operacionais:


Windows XP, Vista, 7 ou 8 (32 ou 64-bit)
Mac OS X 10.85 ou posterior (somente x8)
Linux (testado no Linux Ubuntu)
42
Captulo 2 I Congurao do ambiente de desenvolvimento 43
A seguir, veja as informaes sobre os ambientes de desenvolvimento suportados:
No mnimo 4GB de memria recomendvel. Minha experincia de que
necessrio no mnimo 8GB de memria.
Pelo menos 1GB livre no disco para instalar o Android SDK, emulador,
imagens de sistema, ferramentas e cache.
JDK 7 (apenas a JRE no o suciente). Caso a mquina j tenha um JDK
inferior instalado, como por exemplo o JDK 1.4, verique se as congura
es da varivel de ambiente PATH e JAVA_HOME do sistema operacional esto
utilizando as verses corretas.

Nota: ao instalar o Java, congure a varivel de ambiente JAVA_HOME do sistema


operacional para apontar para a pasta na qual o Java JDK est instalado.

2.3 Plataforma (verso do Android)


Antes de comearmos a brincar com o Android, importante entendermos o
que API Level. Como existem vrios dispositivos com Android no mercado,
possvel que cada um deles tenha uma verso diferente do sistema operacional.
Por exemplo, o primeiro smartphone Android, o HTC G1, tinha a verso 1.1, e os
novos smartphones esto saindo com as verses mais recentes.
No Android, uma verso do sistema operacional conhecida como plataforma.
Podemos dizer ento que existem diversas plataformas diferentes do Android (1.1,
1.5, 1.6, 2.x, 3.x, 4.x, 5.x etc.).

Cada plataforma tem um cdigo identicador, chamado de API Level. A lista a


seguir mostra a relao entre o cdigo API Level e cada plataforma:
AP _eve 1 - Corresponde plataforma do Android 1.0.
AP _eve 2 - Corresponde plataforma do Android 1.1.
AP _eve 3 - Corresponde plataforma do Android 1.5 (Cupcake).
AP _eve 4 - Corresponde plataforma do Android 1.6 (Donut).
AP _eve 5 - Corresponde plataforma do Android 2.0.
AP _eve 6 - Corresponde plataforma do Android 2.0.1.
AP _eve 7 - Corresponde plataforma do Android 2.1 (Eclair).
Google Androd - 4 @d
44 ' 7 'Fro o).
. ._ . Android 2-~ A Y
` - , 'ddo23 (Cingerbread)
- AP Leve' s ~ (im-rsi1 11 i*\="*' A
~ ~ - latalorma Androi
. ~ . . ' 'd 2.3.3.
. AP Leve 9 -- Corresponde A P
. AP -eve 10 - Corresponde a plataforma do Andfl
- AP
-eve ~ z ~ * Plataforma
11 Corresbonde * " do Android 3.0 (H0YCmb)'
~ AP eve 12 - Corresponde plataforma do Android 3-1
- AP -eve 13 - Corresponde plataforma do Android 3.2.
AP eve 14 - Corresponde plataforma do Android 4.0 (ICC Cfaln Sandwich).
. AP _@ve 15 - Corresponde pataforma do Android 4.0.3.
AP -eve 16 -Corresponde p`_ataforma do Android 4.1 Uelly Bean)
AP -eve 17 -Corresponde pataforma do Android 4.2 Uelly Bean)
AP -eve 18 - Corresponde pataforma do Android 43 Uelly Bean)
AP -eve 19 - Corresponde pataforma do Android 4.4 (KitKat).
AP -eve 20 - Corresponde plataforma do Android 4.4W (KitKat para
wearables).
API Level 21 - Corresponde plataforma do Android 5.0 (Lollipop).
API Level 22 - Corresponde plataforma do Android 5.1 (Lollipop MRI).
API LeveIX - Novas verses do Android vo continuar a contagem...
AAPI Level um nmero identicador valioso para aplicaes Android, uma vez
que, ao desenvolver aplicaes, necessrio denir quais sero os dispositivos
alvos. Dessa forma, se voc sabe que utilizar uma nova API que existe apenas
em smartphones Android 4.x ou superior, ser necessrio denir no projeto que
a API Level mnima suportada a 14 - compatvel com o Android 4.0 ICS.
Para obter a lista atualizada de API Level, visite este site:

http://developenrzndroid.com/guide/topics/manifcst/uses-sdla-clemcnt. html#ApiLevcls

2.4 Android Studio

_ nci G 1 , . . ,
Neste livro vamos adotar o Android Studio, que a IDE oficial de dcsenvolv`
para Android. O Android Studio foi anu ` d .I z lmemo
no Imelhj [DEA da JetBminS' a o no oog e I/O 2013 L c baseado
~ . ~ portantes se com 'ir A - ~
O Android
5111410 apresenta alguns diferenciais im
ECIIPSC, que antigamente era a ferramenta ocial pt ado do
Captulo 2 n Congurao do ambiente de desenvolvimento 45
1. Editor visual mais uido e com mais opes.
2. Sistema de build mais moderno baseado em Gradle (gradlaorg).
3. Diversas utilidades e facilidades ao desenvolver para Android, sendo muito
integrado ao Android SDK.
4. Templates de projetos para smartphones, tablets, relgios etc.
5. Atualizaes e melhorias frequentes.
Uma grande diferena entre o Eclipse e o Android Studio o processo de com
pilao dos projetos. No Eclipse cada projeto compilado do jeito clssico, como
qualquer projeto java dentro do Eclipse. Mas no Android Studio a compilao
feita pelo Gradle, que um moderno sistema de builds. Segundo o site oficial do
Cradle (gradlenorg), ele denido com a seguinte frase: Gradle combina o poder
e a flexibilidade do Ant com o gerenciamento de dependncia e convenes do
Maven, em uma maneira mais ecaz
Se voc no est acostumado com gerenciamento de dependncias, pode achar o
Gradle complicado no incio, mas que tranquilo que durante a leitura do livro
vamos praticar bastante. Com a prtica do dia a dia, voc vai se acostumar com
ele e aos poucos vai perceber suas vantagens.
Agora vamos colocar a mo na massa e baixar o Android Studio; acesse a seguinte
pgina, conforme a figura 2.1.
http://developer android.com/sdle/

Deve|0per5 - Design Develop Distribute Q 5


Training Apr Guides Reference T :mia Google Services Samples

NDK j

P g/:J
d dS d
K

Hip

E ld y
Spp tLb y
Fi

ADK
. .,,_..._.....e._,............. zz zi
Eclipse With ADT ' ~ Other Do.~.=nlrad Options
. Migralmg to Android Sludl
T ke a Survev

Figura 2.1 - Download do Android Studio.


46 _ _ _. - ..~ .` - -'rg ltaiuatr
r\ndroid tudio ~ _ _ 5Dl\
Google Android - 4' ed5

"-. ~.' \-'\ *i`&\I`0'\l1LI`DIeIllll.


_ Sm; -~* c o Android
Durante ;l ll\5f~lSl dtmm A hu I fl . . ~ mi vndido deixar o Android SDK
erioinstaladus. No\vi;.n'd de il1Sl@1l1*)L nu lt rnii 'io io b-ii\~ir'itu~iliza
~*`_
na msm do mimo Pam mo tcrmm Piiiiiismti iakestruturq dc Pastas como
C5 mz Dl\. Depois de tnst ll r ` l' i. 'un tcms 3 pasm dc instalagao
a exibida na figura 1.2. Na parte CSQULTK J L J l ^
o Android SDK foi instalado.
do Android Studio e na direita. onde

OStC:i AI'QUivosdeP'r09fam\s ' Andmid > Android Studio F


|~

Nome

giadie
I lib
K license
L DWQW
tuiic|.m
uceusem
E uoricem
Q unmstallexe

Figura 2.2 - Pasta de instalao Android Studio.


Ao executar 0 Android Studio voc vera um wizard inicial (Figura 23). Na poca em
que este livro estaxa sendo escrito o Android Studio estam na verso LOJ, mas voc ver
que so lanadas novas verses com frequncia, pois a ferramenta est em constante
evolugilo e sempre recebe melhorias. A vantagem que o processo de atualizao
automtico e voc receber uma alerta sempre que existir uma atualizao

\:\/elcoine to Android Studio


hmPa,zm
UI
_
_?-. '- ' Q
Q ~ o|'~t1:|e\n`wetnv'\=w*=ui3-$.tsu. Y; \. ,Q
..~ 2-. um
'3'$"1
r`. .\ _
l. c '
ms..
rw
I ; v' _, .
l...
\H\

(fg ` .\ _` `
.UM

, I?
. ..

gif [gq Y

*\'r~.nn'w..z1e;z'._.,\,m E 'W ' Ff\t1'z'u

Figura2.3-P' ._ .
rirnuru 'xiua do Android Studio
Captulo 2 I Congurao do ambiente de desenvolvimento 47
Antes de criar um projeto, recomendo clicar no boto (ongure do Wizard para
fazer o download e a instalao das plataformas (verses) do Android, embora o
Android Studio j venha com vrios itens pr-instalados. O wizard com as opes
de configuraes pode ser visto na gura 2.4. Nessa pgina do Wizard, clique no
link SDK Manager para abrir o utilitrio de instalao do Android SDK, a explicao
de como continuar est no prximo tpico.

Nota: o Android Studio contm o Android SDK, mas recomendado atualiz


lo utilizando o SDK Manager. Outra maneira de abrir o SDK Manager pelo menu
Tools > Android > SDK Manager caso o Android Studio esteja aberto.

Android Studio -- _
Welcome to Android Studio
Recentlrojects _, C fg
`lffDl' H H V S
An drordUtils _
4% Settings

E,
~...
Plugins

% Import Settings

[ Export Settings

i Project Default:

". .Den St _ 1 "'. ud 25.$64'l36. Chtbifdfpdilti.

Figura 2.4 - Conguraes.

2.5 Instalando os pacotes pelo SDK Manager


Para iniciar o desenvolvimento, necessrio baixar as plataformas do Android,
com o objetivo de criar os emuladores para cada verso do sistema operacional.
Essa instalao feita pelo SDK Manager. Aqui podemos baixar todas as platafor
mas do Android e suas respectivas documentaes, o driver USB do Google para
conectar um dispositivo na USB, as bibliotecas de compatibilidade, biblioteca do
Google Play Services, o acelerador de emulador da Intel (HAXM) etc. '
Google Android - 4' edi0

48 ` tl io tln $Dl' ;Il)CI'fu C Cult] il P.ln.[L:


.~\ natura .2.55.0.1
forma do Android
mostra o utilitzirio
instaladlf
estou mostrando, =1P*`"*lf
.L\:t;c ter uma base. 111115 WW qm No L `
instalados no meu Cvlimmdor Pam
_ _ HU
vrios outros itens _ ~5Dl\ .m1\usp.ll.ll
' _~d"'p . ~ -- instalaao.

Figura 2.5 - SDK Manager


" ___ _ _____.__-__..__ ._. _- --- f

d. z l ` " , ' ~ _ . izam


Nota: quando voc for fazer a instalao, baixe a ltima verso que estiver
ispomve . Os emuladores ARM sao mais lentos Os emuladores Intel 86 util
o acelerador da Intel (ver proximo tpico) e so mais rpidos.

. z get e sim
Instalar verses da plataforma do Android e bibliotecas pelo QDK Mana ' `
ples:voc entender
basta selecionar
queosprecisa
oestar
pacotes ' 'instalado.
desejados e clicar cm Install packages. O importante
Para comear, sempre importante
_ . ua izat os. que so
manteros trs primeiros itens at l` l
referentes ao SDK Tools, pois isso influencia diretamente na com
Android SDK Tools - Ferramenta pilao do cdigo.
s do SDK, como o emulador.

Android SDK Platform-tools - Ferramentas da plataforma do Android.


Captulo 2 (ongurao do ambiente de desenvolvimento 49
Android SDK Build-tools - Ferramenta de compilao. Ele extremamente im
portante, pois a verso que voc baixar aqui ser utilizada para compilar
o projeto com o Gradle. No arquivo buildgradle do projeto especificado
o cdigo da verso do build-tools que utilizado para fazer a compilao.
Na gura 2.5 podemos ver que, abaixo do item 5.1.1 (API Level 22), foram insta
lados vrios componentes:
Documentation for Android SDK - Documentao do SDK.

SDK Platform - Esse o item mais importante, pois a plataforma dessa verso
do Android. No diretrio do SDK ele ser instalado na pasta /sdk/platforms,
a qual contm as classes e APIs dessa verso do Android.
Samples for SDK - Documentao do SDK.
EABI v7a System Image - Imagem do emulador do Android. Voc pode baixar
a verso da Intel X86 ou ARM.
Android TV System Image - Imagem para criar o emulador do Android TV Voc
pode baixar a verso da Intel x86 ou ARM.
Android Wear System Image -Imagem para criar o emulador do Android Wear.
Voc pode baixar a verso da Intel ou ARM. 1
Google APIs System Image - Esse item idntico imagem do emulador conven
cional, mas ainda contm as APIs do Google. Recomenda-se sempre criar
o emulador com o Google APIs.
Mais abaixo na pasta Extras deixei instaladas as seguintes bibliotecas.
Android Support Repository - Repositrio utilizado pelo sistema de build do
Android Studio (Gradle).
Android Support Library - Biblioteca de compatibilidade com suporte s verses
mais antigas do Android. Contm vrias classes que permitem criar aplica
tivos que funcionem de forma coerente em todas as verses do Android.
Google Play Services - Bibliotecas adicionais do Google como Mapas V2, Lo
calizao, Google Fit, Google Drive, GCM (Push) etc.
Google Repository- Repositrio interno utilizado pelo Google.
Google USB Driver - Driver para os smartphones e tablets da linha Nexus do
Google. Esse item necessrio apenas no Windows.
Intel x86 EmulatorAccelerator(HAXM instaIler) - Esse item um acelerador de veloci
dade do emulador para Windows. Depois de baix-lo, necessrio instal-lo.
Com isso possvel criar os emuladores x86 que so mais rpidos.
so Google Android - 4 ed
r(HAXMl
2.6 Intel Hardware Accelerated Execution Manage
A l ` l -
O emulador .do'pornc
' lentido
r'lceUSB
n' z _ . Y ou
mitos descnvolvedorCS
c lunoso sua
` ` ~- I' n.:m/).
optam por desenvolver diretamente com um dispositivo ical plugado na
instalar emuladores de tcrceii'oS.C0l11> 0 (.CHym0fl<> (l1llP>-//WWWKf'")'""l 'I

Para solucionar esse problema de lentido do emulador, a Intel criou um acelerador


para o emulador. Isso e possvel graas ao Intel Hardware Accelcrated hxecution
Manager (HAXM). Com a tecnologia de virtualizaao, o emulador do Androt
consegue executar instrues a cerca de 80% da velocidade nativa do processador
host, o que signica na prtica um emulador cerca de cinco vezes mais rpido. O
Intel HAXM pode ser baixado pelo SDK Manager e tem suporte para os princi
pais sistemas operacionais: Windows, Mac OS e Linux. Depois de baix-lo, voce

r nte!
precisar entrar na pasta /sdk/extras/intel e instalar o software (Figura 2.6), pois e
leito apenas o download do instalador.

1 1 ` `
_ ` Welcome to the |ntet(R) Hardware Accelcrated Exeeutlon Mana er Installer
I' l*"~i~ UL' UL r^'~~1l1'^P^~',*'`H^f-l*^>'z"<=^v-~vto|~~,t.:tIntaIfz-)HAXM- '~ .
Introduction
11!A1Ill1I1l1 ,\
wullliztlo
, _ `v_ 1.
Fl
i 5 ,. r>~.-z~.zz~re
Iptti\

KI

Figura 2.6 -Instalando o acelerador do emulador da Im1_


Vale lembrar u eoHAX '~ .f t
, .. .
tualizao com asiafaz
QIntel
M e compativel
podera izarasima
T-X Caso
um I , x gf
V comcoi~..~~
processadores
`~ .
Intel e suporta vir
86er a instalacao com sucesso, voc

.x~-,.
TvdaInte
1 ~, que
gensx docmuladordoAndroid,/\ndroidWeareGooglc
aparecem no SDK Manager.
x86 Atom System8Ima
0fS, chamados de ~
Fsses emulad
que
sao os itens com o nome Intel

POIS utmzam O ` 86, sao muito mais rapidos que 1 e


emu' ~' . _ Clt' ' .visite
~a ,or
seuEnm
l d Processador ~ o s' `
se ' PUU1
e a memria
cn1pua{O. do ~ _or
accom ost
dpara
L ARM
Vamo
executar Q
noticia. Para mais informaes sobre O H;1Slal12lnte
doda
HAXM,
Intel: uma tima
Captulo 2 I Congurao do ambiente de desenvolvimento 51
https://software.intel.com/pt-br/blogs/2012/O6/25/decole-com-seu-emulador-android
https://soLware.im:el.com/pt-br/android/articles/intel-hardware-acceleratedexecution-manager

2.7 Criando um projeto no Android Studio


Depois de instalar os pacotes do SDK e baixar a verso do Android desejada,
vamos continuar e criar um projeto.
Abra o Android Studio e clique no link New Project do wizard. Feito isso, preencha o
formulrio com o nome do projeto, conforme a gura 21 O campo Application Name
o nome do projeto e o campo Company Domain o domnio de sua empresa. Eu usei
o site do livro como domnio. O item Package name derivado dos campos nome do
projeto e domnio, que nesse caso cou brcomlivroandroid.helloandroidstudio. O
pacote quem identifica o aplicativo no dispositivo e precisa ser nico, pois no
possvel publicar dois aplicativos com o mesmo pacote no Google Play
T?? Create New Project

Configure yaur new project

Application name HelleAndroidSudio Z j


Qompany Domain: j_lijroandroifc5om.bW 4% *ij
Package name: bnccm.l.re:md=:*id.he%!eandroz ci Edit
Project Iocaticru R:\temp\l~lellofndroiclStudio V _ _ O

z 1 f*=*==~* S

Figura 2.7 - Criando um projeto.

Por padro, o Android Studio vai criar os projetos na pasta do usurio no sistema
operacional, no subdiretrio AndroidStudioProjects. Eu particularmente costumo
mudar esse local para outra pasta.
Clique em Next para continuar. Na prxima pgina do wizard, selecione o item
Phone andTabIet para criar um projeto compatvel com smartphones e tablets (Figura
2.8), em seguida selecione no campo Minimum SDK a API Level 21 (Android 5.0), ou a
maior verso que existir na poca que voc estiver lendo o livro. _
S2 u
i f . voz
_ L `_` .,`.) t\-\ V .{< ..
|w_'_` .L Y., .__ zw aew. :-\
_ -.z.;=-\l\W -' '
Google Androld - 4 d5

z-- <'*

. . _ . - x -~ - 1)`l`
Figmu 2.8 - (riando um H'Ol<`fU

Observe que no vvtzard tamlwem reinos opcoes para ttiat pro]LIU> W111 *UI * 1 *
ao Google 'l`\'. Android \\'ear treiogiosi e Google (iias \UL`Ui0S)

Importante: ao criar seu primeiro pioieto .f\ndnid. escolha a maior versao dispomvel
no campo Minimum SDK. assim os exemplos explicados nos proximos topicos vao
funcionar. Se voc selecionar alguma versao antiga do Android. o proieto sera
criado com a biblioteca de compatiiilidade. tuas isso cstudaremos somente depois.

Na proxima pagina do wizard, voc pode selecionar um dos templates disponi


veis. Selecione o template BIanliActivity para criar mu pnojeto vazio com uma activity
simples (Figura 19). Uma activity e tuna classe que vai exibir tuna teia para o
usuario e controlar os eventos. sendo que esse wizard vai criar uma simples tela
com uma mensagem de hello xvorld.

Na proxima pgina do xvivard


.. ` .(Fit1ur~i
_. ~ r7 ~lili'evoti du 1' o
t tratar nome da classe
da activity Digite HainActtvity no campo Attivity Name e os demais campos sero
preenchidos automaticamentc. O campo Layout Name e telerente ao ;u-quim XM{
do layout da activity que sera gerado O campo Title o titulo que sua aplica *io
os itens de menu tu ~ f `- ' - i `
vai ter ao executar no emulador. O campo Menu Resourte Name e o XML que conira
l K M mo inse ridos na action bar.
Captulo 2 Congurao do ambiente de desenvolvimento 53
Q Create New Project
Add an activity to Mobilo

Ada No Activitys
r
{'" ` W "
i

I.. ._ .__ .. ...

Blllt V Blank Activity with Ffagmerrt

Fullscreen Activity Google Maps Activity Google Play Services Activity

Figura 2.9 - Denindo o template do projeto.


Create New Projeat sl
Choose options for your now fik

Croata a nen bknc activity wban action bar.

MW NM L"'*l'"ll: aaaa ____..s_,_L..-L l


LW N~~= lwrzfl ;. L
Tila: liaznmiy
Menukesourcehlame lmenu_m|n _ l

sunzazvuy

Figura 2.10 - Denindo o template do projeto.

Para os arquivos em XML, importante seguir o padro da converso de nomes.


Por exemplo, se sua activity se chamar LognActtvty.java, o arquivo XML vai se
chamar activity_login.xml, sempre comeando com a palavra activity, e o item de
menu se chamar menu_login.xrnl. Como teremos vrios tipos de XML no projeto,
essa conveno facilita encontrar e identicar os arquivos. '
54

1)) ._ z.-. _ -I__zrwtueoro*


'x'ir\ `um
' ` Wok
~*
_ - . ;` inish C a fuardc. l..g>
. .,u _ avrmc
Para finalizar o wizard e criar O Pl.lUO` Lhqm Im- hm IU; fa -tro esta
1 .`..~. '` - -
~ r~
dcpms dc Cnm- O projeto. voce vera uma iancla mlormm it I] .ld [5 J l 1 im
' L t'
sendo compiladopclo(iradlc (l`1gLlI`l2.1l),L]lIL t o sistema eq l Ico
vez t ue voce utilizar o Android tudio esse processo pode L Lm0f t l d *
pois o (iradle vai baixar seus pacotes c dependencias. l ()Ifzll11O, ccrtih 1
que voc possui uma conexo com a mtcrnct.

~ fadlfaurf
gumgmg 'H.ondroidS!udzo' Gradle project mic
Google Android - 4 @d

Cancel

Figura 2.11 - Derzindo o template do projeto.

Aqui exatamente o momento em que um bom computador pode fazer a diferena,


pois o sistema de build do Cradle pode apresentar certa lentido em mquinas
com baixas configuraes. Em meus testes um disco SSD faz bastante diferena
na velocidade de compilao, e claro que, quanto mais memria, melhor.
Depois de criar o projeto, a estrutura de diretrios deve ser como a gura 2.12,
que mostra o editor aberto no arquivo /res/layout/actii/ity_main.xm1_

' .".. .. 430


. LJ. ,\.__L
/
- xv-^ 'p.zz~. -, ....,. , ,. M 9 ,_, .

I " ' |'.=zz.~


*W ` H w- '<.-
.
UP ~'* :fuer un Iv-au um _ -,z . 0 * z- M... VL

.,..f
:-..
.~z.
zw A
"" mig ,n-un-

ez-
.. _.M
,:,,

F1 '

N. ' 1 -_ a-.:,a..1.~_ . . '_~'`A`


Fi u 2.12 - ' - ~
~ a.._fz ,L

8 f Projeto trzado e aberto no editor visual.


a gura eu destaquei com uma seta na es
'ti

. , _. _ ivose asta d ' "


Ira utiliza
qual mostra
querda um item de menu ue
customizar a forma de visualizao
a estrutura 'real
do ro. I Q permite
- de_arquPP Sjeto oa qualroestaeto.
marcada C
como-_ . .
Projeq
r muito a visualizaao Android, que mostra de arm um O tempo VOC
21 enxuta e agrupada os
Captulo 2 I (ongurao do ambiente de desenvolvimento 55
itens do projeto. Veja que tambm destaquei na barra de ferramentas do Android
Studio as principais opes que voc ir trabalhar no dia a dia, que so o boto
de Run/Debug, botes para abrir o SDK Manager e AVD Manager etc. Tambm
destaquei o arquivo app/buildgradle, que onde voc ir configurar informaes
sobre a verso do aplicativo e tambm declarar as dependncias.
Para executar o projeto, clique no boto Run conforme mostra a gura 2.13. Na
gura o combo mostra o valor app, referente ao mdulo app do projeto, pois um
projeto no Android Studio composto de vrios mdulos. Por exemplo, caso voc
crie um projeto com suporte ao Android Wear, existir a opo para executar a
verso mobile ou Wear do projeto.

zzzzz l af: ii. a


eo ~

Figura 2.13 - Barra de ferramentas para executar o projeto.

A gura 2.14 mostra o wizard para escolher o dispositivo que deve executar o pro
jeto. Neste caso ela est mostrando um smartphone Nexus 5 que est conectado
na USB. Agora basta clicar o boto OK para executar o projeto direto no dispositivo.
,Q Choose Device
__hoose a running device

_ _ _ Device __ __ _ eriaINumbe _ State Com atbie


, se Nem: 5 t z .mid 4.4.4u_ . 5f3;saob1iofa_ _

aun:h emulator

z [none]
:ame device for future launches

M
Figura 2.14 - Selecione 0 dispositivo ou emulador

Dica: para depurar em um dispositivo real conectado na USB, necessrio


habilitar nas configuraes a opo Se(urity> Unknown Sources (Segurana > Fontes
desconhecidas) e a opo Deve|0per0pti0n$ > USB Debugging (Opes do desenvolvedor
> Depurao USB). Vale alertar que o menu Developer Options no aparece'por
Google Android ~ 4 d

56
' ~ *f -f habilita-lo,\
f . ' . ~ , " _;
- - ' - ~~ tisoselccionai 1
I Q , `, mwP'
, ~ ' `( ` ' ) ` .
_ _ ~. 2 ,U;nerioi.laia ,
Numbe
P*l no Amlumlfi ( 3 sl c clicar sete vezes seguidas na oP%ao B QC um
_ _ _\ , (1mLI1S.1 L
About phone nas conllill" * ,, . ~ 1m informando qu 21210171 W
AO tum. IML Wu MMM um 0 tions eistar habilitado.
LiL`SL`ll\'UiVCLi()l` c o inenu Developer P *
_. Hello World..N05
._ , . gm a, ,mensagem
f se
Ylcxecutei
_ . . o,proieto
z dis ositivo concc
O iltado pode ser visto na gull 2-13 _ . . , tado na USB,
diretamente no P
m0lm Qu 3 d , Tizr e instalar a aplicao no emulador.
mas no prximo tpico vamos aprcn U I Q

Hello world'

Figura 2.15 - Projeto executando no dispositivo.

Nota: para executar o projeto diretamente no dispositivo, basta conecta-lo na


USB e ativar a opo USB Debugging nas configuraes do dispositivo. Se o driver
for reconhecido, o Android Studio vai permitir executar 0 projeto normalmente.
Dependendo do fabricante, pode ser necessrio instalar algum software para
reconhecer o driver do dispositivo.

dsistem *' ~`. fc~ ~~ , O


2.8 Criando um emulador (AVD)

~ _ < A evice (AVD), ou simpl5_


No Android o emulador chamado de Android Virtual D

e um smartphone oucomtablet Android ~ 6


mente conguraao virtual de um dispositivo. O emulador simula 't congura ~Q
exatamente a mesma plataforma d
a operacional, resoluao de tcla e outras configuraes.
S
Captulo 2 'I Congurao do ambiente de desenvolvimento 57
Para criar um emulador, execute o aplicativo AVD Manager pelo menu Tools >Android >
AVD Manager conforme a figura 2.16.

ng vc; indaw Help A A _

rg.
Isks&Conteds U 6 ,;,
, , Generate Javaoc... 'i`""i'i"""f'f'f" l'`'
f' i; Save Project as Template...
Manage Project Templates...
1, Groovy Console...
-fr *fr "WW" f<f*'
O ooagiz cima Tools 5 Sm Project warn amam Fes
I Open Terminal... '' wi DE/C! M0nt0r A
E Avo Malaga
SDK Manager
Enable non imzgmion

Figura 2.16 - Abrindo 0 AVD Manager


Na primeira vez que voc abrir o AVD Manager, a lista de emuladores estar vazia
(Figura 2.17). Para criar um novo emulador, clique no boto Createavirtualdevite.
AVD Manager

To
Vuhnldevicesailowyouttestyowappcutinnwithouttuvingta
ownthephysicildevicsz

` whefeyouangetup-to~dteinform.ionm
which devcesareactivent|\eAndrodndGnogIePlayeosyst|m.

Ee-Mil
Figura 2.17 - Android Virtual Device Manager

Na primeira pgina do wizard (Figura 2.18), selecione o tipo do dispositivo para


criar o emulador, que pode ser Phone, Tablet, Wear ou TV Veja que voc pode
escolher o tipo do dispositivo e o tamanho de tela que deseja simular; por exem
plo, eu escolhi um Nexus S com a tela de 480x800.
Google Android - 4 0d
S8 Ii.,
ii- _. .||._n

.ii-i--__ _
S__.-.__... -..~--~
-l [ Nexus 3

wa
,,,, Nau; onz_N_s. 3. T' wm mp. Sun nmll
Run WW
Nul FW 0" lr .hm mp. Oomkv Mv!

n NEM 6 536 H|0|2$60 S60dP 000m

Nami `g5' HHQJO uhr

Num 7- 768x1Z) IMP*

,,y Nau, 4 65 720:IZ!> ihdpl

Android Wal Sq... Y5' Zxhzw hdpi

ndmtd Wen no Los' 320630 hdpi

t..
1 QZQ.
Figura 2.18 - Selecionando o tipo do dispositivo.

Na prxima pgina do wizard, selecione a imagem de sistema para criar o emu


lador do Android. Somente sero exibidas na lista as imagens de que voc fez 0
dovimload pelo SDK Manager. A gura 2.19 mostra a imagem do Android 5.0 API
Level 21 do qual z o download. Note que a verso com o Google APIs idntica
imagem padro, mas contm as bibliotecas do Google, portanto recomenda-se
criar o emulador com o Google APIs.
Q' vr
Virtual Device Configuration 'f..,

'~PP 21 ofmubi-v7| Amw mx Lollipop

r 21
i ` ix Ari tem

i ^r:I
*' 5.0.1

O urmubl-vh Google Inc.


vhm wap

ima dvuionduuyagir
'""9" , '7 ~ Su documontwon toi MGOG 5 AH;

l
Figura 2-19 - Criando um AVI).
(aptulo 2 I (ongurao do ambiente de desenvolvimento 59

Dica: o emulador ARM do Android bastante lento, por isso se puder crie
o emulador x86, que tem o acelerador da Intel. Caso seu computador no
suporte a tecnologia de virtualizao da Intel, recomendo instalar o emulador
do Genymotion (genymotioncom).

Na ltima pgina do wizard (Figura 2.20) digite um nome para o emulador e clique
em Finish. Opcionalmente verique as opes avanadas no item ShowAdvanced Settings.
Virtual Device Configuration '

r.. _. _ _
^' ""' U'5**..**''--_. -..W ..ss .. 2 2 lss. _ _ ---W --. ... Avn mm.
] uzzozs 4.o-aoozsoompa cnznglf..
Stmup size
and Sul: A_t
H I l TYIO IIBITIO ol U'|lS VD.

, ' Lollipop Google API; (Google In:.) umubu-v7a Change...

orientmon

ffnumfd
Perforrnance
Qi uzz Host seu
l:I Stovea snapshot for fasterst rt p
'i au na efther me Host GPU p h t

;"z.....".......iii"`;.....,.i`*i ':

z . l..5r+s..l
Figura 2.20 - Criando um AVD.

Depois de criar o AVD o resultado ser como a gura 2.21, que mostra a lista dos
emuladores criados. Para iniciar o emulador, basta selecion-lo na lista e clicar
no boto Run que um tringulo verde. Nessa lista voc tambm pode editar as
conguraes do emulador e at exclui-lo. Para criar mais um emulador com
outra congurao, utilize o boto (reateVirtuaI Device.
Google Android - 43 edi0
60
Avn Mzmaer i

AH M run:l''^"'i Ill MM
; uzwzsmai oooohvi Z' `9l'm 650
M8, .7Y

Figura 2.21 - AVD criado com sucesso.

A gura 2.22 mostra o emulador executando no emulador.

. 5g,54N.,;AP|,21

Figura 2.22 - Emulador do Android.

2.9 Executando o projeto no emulador

tado na USB ou em um emulid '


Ao executar o projeto, possvel instalar o aplicativo em um dispositivo conec
. z or. Para executar o projeto no emulador siga os
seguintes passos:
Captulo 2 I (ongurao do ambiente de desenvolvimento 61
Caso o emulador esteja fechado, selecione o item Launch emulator (Figura 2.23) e
a seguir selecione o emulador desejado. Caso o emulador esteja aberto, ele vai
aparecer na lista abaixo do item (hoosea running device.
E; Choose Device
O Qhooe a running device

* Launch emulator l K V " " l"` "l


nafziatzzauzlazazz _f1wf,S,_~F>_g1 pp pp __
l:i Use same device for future lunches

@~<=*

Figura 2.23 - Executando 0 projeto no emulador

2.10 Algumas janelas importantes do Android Studio


Uma das coisas mais importantes ao estudar uma nova tecnologia aprender
mais detalhes sobre o ambiente de desenvolvimento, que neste caso o Android
Studio. Quanto mais familiaridade voc tiver com as opes da ferramenta, melhor,
mas isso vai depender muito de voc, pois s usando e fuando que se aprende.
Uma janela importante que mostra as mensagens ao executar o projeto no
emulador a 4:Run, conforme mostra a gura 2.24. O nmero 4 do atalho para
utilizar com o Alt+Nmero ou (md+Numero (Mac). Na gura podemos ver os logs que
mostram o aplicativo sendo instalado no emulador. importante aprender a ler
as mensagens desses logs, pois se acontecer algum erro ao executar o projeto esta
janela vai mostrar detalhes importantes.
Outra janela importante a 6:Android (Figura 2.25), a qual mostra os logs do emu
lador ou dispositivo conectado na USB. No Android todos os logs so contro
lados pela ferramenta LogCat. Depois vamos aprender a criar esses logs dentro
do cdigo-fonte, para ajudar a depurar o cdigo. O LogCat mostra todos os logs
do sistema operacional ou apenas do processo ou tag que voc especificar, o que
permite depurar apenas as mensagens que lhe interessam. .
Google Android - 4' 0
62

Figura 2.24 - Logs da execuo do projeto.

Em caso de erro da aplicao, verique os erros e excees na janela do LogCat,


pois tudo que se refere execuo da sua aplicao logado aqui. Por exemplo,
se o aplicativo lanar uma exceo a stack trace com o erro detalhado, ela ser
exibida nestes logs (Figura 2.?_5):

Figura 2.25 - Logs do emulador (LogCat).


Outra janela importante,que
amoGradle
t Console
Cradle (Figura 226). s ra as mensagens do build do
~ . za
Graal: Comolo
_ **)a'-.- I ,gw
.` 'WHY L 2 4 v-ni :ir Z-\.z
Q ~ ;;

M3 WV-I" .z i zizif'
.,W...,,,, J H MF
-l ~I`Y ..^"`'}'\^\Q,. nf- 7 H
a'_~,q 4,1-=[,,.,z`JY_' J
'l`Y"\' J `"'i*1.:_; *' '1; my
n~:ri~ xJ'i'\'~l '11 Y li
`UL~2f! l\if2~iz,, w; ,TP

1 ni i 5-;~_zz,
`l 1 1..

"* *"** *W Gmea; Qgmgk

Figura 216 " [085 do console do Gradle.


Capitulo 2 -.Congurao do ambiente de desenvolvimento 63
E para turbinar o seu desenvolvimento recomendo olhar as dicas do Android
Studio abrindo o wizard Help >Tip ofthe Day. Aqui voc vai encontrar dicas e teclas
de atalhos que vo tornar o desenvolvimento do cdigo muito mais produtivo. A
figura 2.27 mostra uma dica da tecla de atalho (trl+N que facilita encontrar e abrir
qualquer classe Java do projeto.
Tip of the Day A
Did you know ... ?
To open any class in the editor quickly, press Ctr1+N (Navigate 1 Class) and
start typing the name of the class. Choose the dass from a drop-down list
that appears.

Enter class name: _ pf include non-project classes (NN) Y /


i.Q..Q.;;f;;. . .,.,.... 2 ._ s . -J
lnmal (Animal..lilan\nalial -V AMYPTOJEC '
c* z. HetersToInchesConverter MyPro3e~:t lf
You can open any le in your project in a similar way by using Ctr`l+Shift+N `
(Navigate l File)

Cl Show Tips an Startup

l.. f-~=_.;__fl li t il

Figura 2.27 - Dicas do dia.

2.11 Aplicaes na tela principal (Home)


Ao clicar no icone Home, o emulador volta para a tela principal. Nessa tela, todas
as aplicaes instaladas podem ser visualizadas. Por padro o cone do aplicativo
um bonequinho do Android, conforme a gura 2.28.

Figura 2.28 - Tela Home do Android.


Google Android - 4 d
64
ra cada den
Esse cone dcnido no arquivo /fS/mPl"1aP'fxx/C-l""ChenZgfefr esse cone 6
Sd3d (mdpi, hdpi,xl'1dpi,xxl1dpi ctc.). Fique a vonta e para
inserir uma imagem customizada para SCU Pf0Jet0~

ma as co g _ d la
2.12 Entendendo um pouco mais sobre o emulador
l 'mula completamf
U d isas le ais do emulador do Android que e e si
o sistema operacional real, e possvel acessar a estrutura de arquivos o emu
dor. Dessa forma, podemos visualizar os arquivos apks das aplicaes instaladas,
mulador. Toda essa estrutura de
alm de excluir, enviar e recuperar arquivos do e '
diretrios do emulador pode ser visualizada pelo Android Studio ou por ml0
de um prompt de comandos.
Demonstraremos primeiro como acessar o console do Android pelo prompt de
comandos. Para isso, digite os seguintes comandos em um prompt (o emulador
precisa estar aberto):
C:\android-studio\sdk\piatforn-too1s>adb devices
List of devices attached
1 enuiator-5554 device

Ao digitar o comando adb devices no prompt, exibida a lista dos emuladores


ativos ou dispositivos conectados, ou nada, se nenhum emulador estiver aberto
no momento. Nessa lista o cdigo (id) retornado pode ser utilizado se mais de

tm emulador
eseja acessar oestiver aberto
console. para
Nesse escolher
caso em qual
como temos a instncia do emulador voc

do _ . . .
A0 f3Zf1550 Um prompt ser aberto, permitindo navegar nos arquivos e pastas
. emulador. No exemplo a seguir, foi digitado o comando ls do Linux para
visualizar a estrutura de diretrios:
a.
basta digitar adb shell para acessar o ,console do pri:;)Sei1nnul:trd1d1rli(1(lisberto,

C:\android-studio\sdk\p1atform-tools>adb shell
#15
cache
init
etc
var
data
system
tmp
root
dev
Captulo 2 1 Congurao do ambiente de desenvolvimento 55
Observe que o sistema operacional do Android Linux. Dessa forma, ao entrar
no console do emulador, necessrio utilizar comandos do Linux, mesmo se
voc estiver desenvolvendo suas aplicaes no Windows. As aplicaes instaladas
cam na pasta /data/app. Vamos entrar nessa pasta para visualizar nossa primeira
aplicao desenvolvida.
# cd /data/app
# ls
br.livroandroid.helloandroidstudio-1.apk
#

O arquivo brlivroandroid.helloandroidstudio-1.apk corresponde aplicao nal do


projeto HelloAndrodStudio criado anteriormente. Outra forma de visualizar a estru
tura de diretrios do emulador abrir a ferramenta Android Device Monitor pelo menu
Tools > Android > Android Device Monitor do Android Studio. Nessa ferramenta a janela File
Explorer mostra a estrutura de diretrios do emulador, conforme mostra a gura 2.29.
*ff Android Device Monitor - U
f Sun gznw gelo
Qu.c<A.rc5s E3 _ ' f ' 'Q
i _ Name Size Date_ Hi'-'=
iltlfJEiz''fV`f T IT
Deves 5 -. ihreacisv. Heap Allocaii., lxietwor.- File Ex.. I; iimuiat.. * Systemm

1 E! ^.:usje'T1ulatcz'~5554} Online Nexus I-t.- ~ V df-acct 2014-D9-05 15

z; )
:cz,an::o~dfamrhe: 551 8600 ~;>ca:he 2014-09-05 15
'e*:_ar,.:c kemail 1817 8602 Y z -config 2014439-05 15
:\:rn_af1drc.:l_$yStemu 442 32303 ...Y cf 2014439-05
arczd Dfmdi 414 86044 87...
nf.1.'.r:afafcz_h-oancirmd , 4 data
855 8505 anr2014-09433
2014439-031-$(
'CO'Ll'l&(DCl.3l'C1VCl8fC1lEf' 922 8605 K app* _* H W _ K V rf M 2G'I$_~U9-U5
z<.zf..zf..<:f<z<1.f.zz.g5 ras aos cz tzfifvzan1r<f.izi.zzzamuzzs-tape jsa zowolo 'is
a.m1ez:.pro:ess.cor 585 86139 C1 timwmandrcnd.heiIoan'drozdsiudioiest-1.ao U O 7 O 25160 201409-d
ccmaP.drod.iputmemod Ie 525 3610 v app-asec 21314-D9-63
core,amdrozrJ,ca!e*:ar 979 SEU z app-lib 2314-09-G5
com ridridieychazn 1059 8512 .if app-private 2B*f=4=Q9-03
:r:'nam:l'o.d.rnms 951 8614 ~ cz: ar1run-tests 2814-Di-17
*c~man13ro.ddcsi<cicck 1000 8616 '~ za backup 2014439-3
l .~ .nz:1fe.zi.phonzz 5413 8618 ___, tiugrepmts 201i5^;~fJ3
i, ceasz 390 8521 . dalvk;ache ZUH-W-U5
fzIL=:.r'~f Z " ' _
ZU9? 8601 .;~ dara 314B9'iI3 V
'- ........|.-,. tl :RA hu Il.:
Y" pf Java regexes, Wex mrii prai: app;t text: lrrzit scope. vecbcrse V H A
PID TID Application Tag Text ^
.. _..
'A_.. ......,_,.
` 'WT C": fz--*xr V *s_~_ -.r Iz7x:i.r. : r i ;l":' 'x"2 r '
~
. _ ~. .'_ -..-'I
1" _ .__ ~z.z- ._, ..

ow of 492.M

Figura 2.29 - Android Device Monitor - File Explorer

No Android Device Monitor tambm podemos visualizar os logs Android, consumo de


memria, threads etc. Uma das janelas mais interessantes a Devices, que mostra
todos os dispositivos conectados na USB ou at mesmo o emulador. Nessa janela
podemos ver os processos que esto executando no Android, depur-lo, mat-lo,
66 | Log(at Google Android - 4 d

_, , . . ueas 1ntlisF|le
.z ~' Exporer
einclusiv tirar um screenshot da ttla.\/ale lunbritq `_ f cleimmduImjmcln
(lggg) Q as outras vo mostrar as in lormaoes do .lisP5'V* *
Devices, caso exista mais de Um
. _ . . ,. .. . ' cvicc Monitor'
.- n roit tu to com ~s 1
. , ane a.
Dica: no Windows tive problemas para uiccutrso /tlndroid Dpcnnigso d
somente funcionou ao executar o A, Adav c.Io:Gin
administrador. Essa ferramenta tambem pode Scr executa P
C:\androd-studo\sdk\too1s\monitor.bat.

Para remover uma aplicao pelo File Explorer basta selecionar o arquivo .aplc descjal
e clicar no icone com um trao - vermelho no canto direito superior da Jr
Observe que nessa janela tambm existem cones para enviar arquivos para O
emulador e para baixar os arquivos que esto no emulador para seu computad0r.
Note que toda a segurana do Android baseada na segurana do Linux. No
Android cada aplicao executada em um nico processo, com uma thread
dedicada. Para cada aplicao criado um usurio no sistema operacional para
ter acesso a sua estrutura de diretrios. Dessa forma nenhum outro usurio pode
ter acesso a essa aplicao. Por isso, se um dispositivo real estivesse conectado
na porta USB do seu computador, a janela File Explorer tambm funcionaria, mas
provavelmente no exibiria nenhuma aplicao por motivos de segurana. No
emulador como se o desenvolvedor tivesse acesso total (root) ao dispositivo.

2.13 ADB (Android Debug Bridge)

A ferramenta adb (Android Debug Bridge) permite gerenciar e controlar o emu

O8''r'
lador; Inclusive j estudamos o comando adb shell para entrar na estrutura de
diretorios do Android.

db consiste em uma aplicaao cliente-servidor que fica em execuo na m


adb.ee em sua m uina ' ` - . S0
quina. Ao iniciar o Android Studio e o emulador, observe que existe um pmges
Cl ,que e Justamente o servidor. Esse aplicativo executando

mais d , , . 8 ~u. e
em segundo plano controla as portas de cada emulador

Ao iniciar um emulador, sua porta-padro 5554 e a porta de deb 5555 5


ou e um emulador for aberto, os proximos emuladores usaro as prxim
apdbe
,as sequencialmente.
possivel acessarPor exemplo: 5556/.5557,
a estrut d , '5558/5559
- ' 1 O etc Con l ~ as
wmandfl
ura e dirctorios do emulador da m f
e depoisP ISUZI
o IslZ1l'
ara85 v` \lC
l' 3. 0 comando adb shell,
usando ajanela File Explorer. Para isso, abra um prompt C ci ft Sma Qrma que
pz|5[a5_
Captulo 2 I Congurao do ambiente de desenvolvimento 67
C:\android-studio\sdk\platforn-tools>adb shell
# ls
. . . // voc vai ver as pastas aqui
sdcard

Feito isso, possvel navegar na estrutura de diretrios do emulador normalmente.


Veja nos comandos a seguir onde acessamos a pasta /sdcard para visualizar os
arquivos do carto de memria.
# cd sdcard
# ls
linkin_park1.mp3 // Exemplos de arquivos
linkin_park2.mp3
linkin_park3.mp3
# exit
C:\>

Para sair do prompt, digite exit. At aqui tudo foi simples, mas se existir mais de
um emulador aberto? Nesse caso o adb vai exibir uma mensagem de erro, pois ele
no sabe qual emulador deve acessar:
C:\android-studio\sdk\platform-tools>adb shell
error: more than one device and enulator

Ento, preciso ajud-lo. Para isso, precisamos conhecer o identicador de cada


emulador; digite ento o comando adb devices.
C:\android-studio\sdk\platform-tools>adb devices
List of devices attached
enulator-5554 device
emulator-5556 device

Esse comando listar os emuladores abertos, exibindo seu identificador, que con
tem a palavra emulator mais o nmero da porta em que ele est aberto, por exemplo,
emulator-5554. Saiba que a notao pode mudar conforme o emulador; portanto,
o importante voc entender o conceito. Para acessar um emulador especco,
podemos utilizar o comando adb shell novamente e informar o parmetro -s com
o id da instncia do emulador que desejamos.
C:\android-studio\sdk\platform-tools>adb -s emulator-5554 shell

O argumento -s pode ser utilizado para todos os comandos da ferramenta adb sem
pre que existir mais de um emulador aberto e for necessrio informar a instncia
correta. Por exemplo, digamos que voc deseje enviar um arquivo para o emulador.
Para isso, poder utilizar o comando adb push, conforme mostrado a seguir: _
63 1/tw
aa vv .

C:\androd-studio\sdk\p1atform-too1sadb s emuiator
0 KB/s (0 bytes in 7.000s)
Google Android - 4 @da

' t /data/1068
_ -5554 push c=\t@D\fQU1V-Ui

A sintaxe do comando adb DU5h


' te o
. . 11 ara fazer Justame
adb push [camnho_arquivo_local] [P05.de5f"-emulador]

Da mesma forma, podemos utilizar o comando adbemu a


pu lpdor.
contrrio: o download de um arqU1V0 que esta HO

_ - ' anteriormente para O


adb pull [arquivo_origem_emulador] [ca/'inh0_0fGUV.lCl]

Por exemplo, para copiar O 111651110 GYQUWO que envlamos


computador, basta digitar o seguinte COmUd0
C:\androd-studto\sdk\p1atform-too1s>adb -s emulator-5554 DUU /data/10CH1/UP/ arquivo'
txt c:\temp\arquvo.tt
0 KB/s (0 bytes tn 7.000s)

H outras opes de uso da ferramenta adb, mas vamos deixar isso como leitura
para voc:
http://developerandroid.com/tools/help/adb. html
Gostaria apenas de dar uma dica caso voc perceba que o Android Studio e o
emulador no esto conversando muito bem. s vezes, se o emulador ca mui
to tempo aberto e executamos uma aplicao no Android Studio, parece que a
aplicao no instalada no emulador. como se o emulador estivesse parado.
Se isso acontecer, pode ser necessrio matar o processo do adb.ee em execuo
no sistema operacional. Isso pode ser feito com o comando adb kill-server. E para
iniciar o processo do adb pode-se utilizar o comando adb start-server. Outra forma
de reiniciar o processo adb.exe abrir a janela Devices da ferramenta Android Device
Monitor e clicar no item de menu Reset adb.

2.14 Informaes bsicas sobre a resoluo do emulador

Q . . ._ er o _ uma te a com resoluo HVGA


Os primeiros smartphones com Android tinham l
de tela, o cuidados
ue dem durante od 1'
(32-0480), T1185 hoje em dia existem smartphones e tablets com diversos tamanhos
q an a a guns desenvolvimento.

iar ~
emulador do Android nos permite simular exatamente o tamanho e a resoluo
da tela de um dispositivo real. Para realizar essa configurao basta escolh

manho da ela no momento de criar um novo emulador. Voc pode 5O1he


- -_Ce_ Ja eve terno
_ ,pois percebido
AVD Mana' er~aoicas_
sele `
etc 1\:-II; -2;1:va)dor.codm a resoluao HVGA (32Ox48O), QVGA (24-OX32O), VGA (48Ox8OO)
PO de d15P0SlUV0, o emulador criado com base nessas czacterist clonar um
Captulo 2 I Congurao do ambiente de desenvolvimento 69
Na gura 230 podemos visualizar como fica a resoluo da tela no emulador com
diferentes conguraes de AV`D.As guras mostram as resolues NVGA alta, I-NGA mdia
e QVGA baixa, respec1vamente.A resoluo QVGA (24Ox32O) so dispositivos muito
pequenos, como o famoso Sony Ericsson Mini. Muitas vezes pode ser complicado
desenvolver para celulares com telas to pequenas, pois necessrio customizar 0
projeto para ter barra de rolagem (scroll) em todas as telas e utilizar imagens menores.
Mas os smartphones com telas WVGA (480x800) so maiores e grande parte dos
aparelhos modernos est vindo com esse tipo de configurao ou at superior, o que
permite abusar melhor dos recursos grcos e criar uma tela bem diferenciada.

fz

Figura 2.30 - Emulador com as resolues WVGA, H VGA e QVGA respectivamente.

Apenas para dar uma ideia, como cada aparelho tem uma configurao de tela,
podemos utilizar imagens de tamanho diferentes para cada tipo de resoluo.
Para isso no projeto Android dentro do Android Studio criada uma pasta de
imagem para cada resoluo. Por exemplo, existe a pasta drawable-ldpi para celulares
QVGA (24Ox32O) de baixa resoluo, a pasta drawable-mdpi para celulares HVGA
(32Ox48O) de mdia resoluo, a pasta drawable~hdpi para alta resoluo com as
telas WVGA (480x800) e por a vai. A coisa comeou a car to complicada que
chegou o xhdp (extra high) e a histria continua.
Essas pastas no tm relao com o tamanho de tela, por exemplo, 240x320 ou
(480x800), e sim com a densidade e resoluo da tela. O tamanho da tela pode
ser o mesmo, mas a quantidade de pixels que a tela consegue exibir pode ser di
ferente, e isso tem a ver com a resoluo. Portanto, aparelhos WVGA (480x800),
embora tenham telas maiores, tambm apresentam resolues muito melhores,
para exibir imagens e grficos com uma tima denio.
Google Android - 4 2d5
. ' .. ' xl
em fra_bida
~, , ~ . ~ )0 . ~ -' -tor inserida
- , . ' na pasta
drawablc-mdP~ .
M lima mmgtm dt M px 480). Mas o que acontece se ela for
hida
- _ ,em
Pcrleitaniente
ul uma
em
- . d` . re in
tela
uma tela
iensionada
H\/GAmenor ou maior.
fifa? 8 imagem
para baixo em uma_tela ..
Ser redimensiw

_ .. .' .asrado. or 15
na
la P
orPadrao.
s araCaso
umaatela
imagem
maior5<~J
como _ WVGA
ara evl '
QVGA (2~lO32O) no temos problem8S.fT121 P _ f P . SO
(~l80800) a iinagem val distorcer e Perder quhdade, O que E espc -t tr que 0
podemos customizar as imagens em suas respCflV5 Past* P
Android faa isso em tempo de execuo.
Neste exemplo, para imagem de 100px, taramos a seguinte conta:
Para telas QVGA (24O32O), seria 100px 0,75 = 75PX- N55@ (3350 P0del05
inserir uma imagem de 75px na pasta drawable-ldpi. Ou voce pode deixar
que o Android redimensione a imagem para baixo em tempo de execuao.
Para telas WVGA (480800), seria 100px 1,5 = 150px. Nesse caso podemos
inserir uma imagem de 15Opx na pasta drawable-hdpi, pois esses modernos
aparelhos conseguem exibir imagens com muito mais denio.
O nome da imagem ser sempre o mesmo. Por exemplo, se o nome do arquivo
for imagempng, teremos vrias imagens com o mesmo nome, inseridas nas suas
respectivas pastas. Em tempo de execuo, conforme a resoluo da tela, o Android
vai escolher a pasta correta, voc s precisa garantir que a imagem vai estar l. Um
exemplo prtico que temos disso o cone da aplicao, criado automaticamente
pelo wizard com o nome icjaunchenpng e replicado nas pastas mipmap-mdpi,
mipmap-hdpi, mipmap-xhdpi e mipmap-xxhdpi para customizar o tamanho para cada
resoluo. Isso evita que o Android faa esse redimensionamento em tempo de
execuo, pois os recursos j foram informados em tempo de compilao.
Vamos aprender mais sobre esses detalhes durante o livro, ento que tranquilo

2.15 (omo fazer o download dos exemplos do livro


Se voc quiser fazer o cadastro no site ara
p mantermos contato, futuramente posgg
avis-lo de novos lanamem05_

Ou man . .
http://wwulivroandroid.com.br/

tenha contato nas redes sociais, que costumo postar sobre lan HITICII _
http://facebook.com/ricardolecheta Os
hUPS2//plus. google. com/+Ricardo Lehem
Captulo 2 I Congurao do ambiente de desenvolvimento 71
Caso queira apenas baixar o cdigo-fonte do livro, acesse o repositrio de cdigo
-fonte do GitHub nos seguintes endereos:
http://wwugithub.com/livroandroid/capitulos
http://wwmgithub.com/livroandroid/carros
http://wwwgithub.com/livroandroid/AndroidUtils
O repositrio /capitulos contm vrias pastas separadas por captulo. Aqui voc vai
encontrar os projetos prontos referentes aos exerccios de cada captulo. O reposi
trio /carros contm um passo a passo que vou utilizar durante o desenvolvimento
do projeto dos carros. Cada pasta corresponde a uma parte do projeto dos carros
concludo. O repositrio /AndroidUtils contm um projeto do tipo biblioteca com
classes utilitrias para nos auxiliar nos exemplos.
Pela explicao do livro, voc conseguir seguir os exemplos e entender o que
signica cada pasta. O objetivo dessas pastas servir de gabarito para voc.
Recomendo que voc tente fazer sozinho todos os exerccios de cada captulo e
o projeto dos carros passo a passo, mas se em algum momento tiver problemas
basta conferir o resultado com os exemplos do Gitl-Iub.
Para fazer o download do cdigo-fonte do GitHub voc pode simplesmente clicar
na opo Download Zip. Outra opo clonar o repositrio na sua mquina, assim se
eu fizer qualquer atualizao, como por exemplo uma possvel correo de bug
ou melhoria de algum exemplo, voc sempre pode atualizar o repositrio.
Com o Git instalado na mquina, abra um prompt e digite o seguinte comando
para clonar o repositrio:
git clone https://github. com/livroandroid/carros.git
Depois para atualizar o cdigo caso existam atualizaes utilize o comando gt pull.
Uma vez que voc fez os downloads dos exemplos, utilize o menu File > Open do
Android Studio para abrir o projeto desejado. Agora com voc, leia com calma
cada captulo e sempre conra as explicaes com os projetos de exemplo, que
podem servir de gabarito para voc.
Vamos l! Desejo desde j uma boa leitura.
\ cAPiruLo 3
Conceitos bsicos do Andr0d
-4
1
I

. , -- ~- ''m
criarrimir
telas na
Este captulo aborda alguns conceitos basicos do Android, como
aplicao, denir uma interface graca s1mpleS, fafaf eventos da tela e l P
mensagens (logs) da aplicao utilizando a ferramenta I.ogCat.
Um layout de tela no Android pode ser criado utilizando um arquivo XML que
dene os elementos da tela ou utilizando diretamente as classes da API Java. A0
nal deste captulo, voc ser capaz de criar telas simples na aplicao, demr
eventos para os botes e ainda visualizar os logs gerados pela aplicao.

3.1 Estrutura do projeto no Android Studio


No captulo anterior, instalamos o Android Studio e criamos o nosso primeiro
projeto para Android. Neste captulo vamos estudar mais detalhes sobre a estru
tura do projeto e os conceitos bsicos de desenvolvimento para Android.
O Android Studio pode abrir um projeto de cada vez, e cada projeto pode conter
um ou mais mdulos. A gura 3.1 mostra a estrutura do projeto que criamos
com a pasta do mdulo app fechada. A pasta app representa o mdulo padro
que e criado no projeto. Dentro da pasta app temos o cdigo-fonte e os arquivos
de compilao especcos desse mdulo. j na raiz do projeto existem os outros
arquivos, como por exemplo o q ar uz
uivo
gmb `ld. dl do projeto, que vale para
e geral

Nota: - . ii " "_ `


todos os mdulos.

Gradl estrutura de PHSHS 6 arquivos do projeto segue a estrutura de build do

72
Captulo 3 I Conceitos bsicos do Android 73
z_*^*"1*=i=

. fi . A ? ?i;*'"f W
1

*gif .gitignore
builcigradle
ll . 5
i;_igradle.prop:r1ies
'fg
E1-;3 l__,_z;
gradlew
gradiewbat
gii Iocai.properties
' settingmgradle
5 z ag; External Libraries
u

Figura 3.1 - Estrutura de arquivos do projeto.

A lista a seguir explica os arquivos que cam na raiz do projeto.


Pasta Descrio
app Mdulo app do projeto. O Android Studio abre um projeto de cada
vez e um projeto pode conter mais de um mdulo. O mdulo app
o padro.
build.gradle Arquivo de congurao do Gradle que vale para todo o projeto,
incluindo todos os mdulos. Voc provavelmente no vai alterar
nada nesse arquivo.
gradleproperties Arquivo de propriedades para customizar o build do Gradle.
gradlewbat Script que executa o build do Gradle para compilar o projeto.
local. properties Arquivo com as configuraes locais do projeto, como por exemplo o
caminho no qual o Android SDK esta instalado. Ao abrir um projeto
j existente, voc deve atualizar esse arquivo com o local do SDK;
por sorte, o Android Studio j faz isso automaticamente para voc.
settingsgradle Arquivo de congurao do Gradle que indica quais mdulos
devem ser compilados. Se voc abrir esse arquivo, ver que ele est
incluindo o mdulo app.

Ao expandir a pasta app voc ver os arquivos referentes a esse mdulo, e ba


sicamente aqui que cam os arquivos da aplicao. Por exemplo, na pasta
/app/src/main/ esto os arquivos .java, .xml e imagens do aplicativo, conforme a
gura 3.2.
Para visualizar a estrutura de diretrios real do projeto, selecione o item Project no
combo de opes que ca na parte esquerda superior da janela. Outra visualiza
o muito boa a Android, que mostra um resumo dos principais arquivos e deixa
a visualizao mais enxuta.
Google Android - 4' d

74
it ' ' 1
pszati '
HelloAn'li (\l('l('|lO `
. tr wi"
i

1.
v-.ii
.l
l

rrliz .L^
. *1]l lu'

i .il. _, . .i
s ul .l"
V ,W { _' lui, z
i\'..il~~
,, t, I,l\. .2
~\li.l\N'_{il' Kill
.lltiw lltzr
lxl l .
l

.till
,,),r17z.ll Nil);
ompzn ll) *WMV
www ii ll 'ii ^`
ii ' ii V,
3

gl

*,/ i}L1\" z*'{>.)l'\l V


,..i....s i--i
tz An l- 1 llf 3 `|'lv'\` "l`
llulivlf
rf _1>` _* ll
' iz.1 til.

Figura 3.2 - Estrutura de arquivos do projeto.

A seguinte lista explica os arquivos do mdulo app.


Pasta Descrio __ ____d ,_ _ _
build cam os arquivos compilados do mdulo. O arquivo apk
que o aplicativo compilado ca na pasta build/outputs/aph.
R. java A classe R. java gerada automaticamente ao compilar o projeto e permite
que a aplicao acesse qualquer recurso como arquivos e imagens utilizando
as constantes desta classe. Essa classe nu nca deve ser alterada manualmente.
O arquivo R. java gerado na pasta app/build/generated/soura'/r do mdulo.
libs
Pasta para inserir os arquivos .jars que devem ser compilados com o projeto
src/main/java Pasta com as classes java; por exemplo, a classe llainActivity que foi
criada pelo wizard.
src/main/res

d bl t '
Pasta que contm os recursos da 'ipz l'reao. como imagens, layouts
de telas e arquivos de internacionalizao. Existem cinco subpastasz
WW f.l1y0ul. menu. mipmap e values, com os seus respectivos classi
cadores, que vamos vericar mais adiante.
Captulo 3 i Conceitos bsicos do Android 75
Pasta Descrio
res/drawable Pasta com as imagens da aplicao. Atualmente como existem diver
sos dispositivos Android com diferentes resolues de telas, possvel
customizar as imagens para car com o tamanho exato em cada reso
luo. Para isso, h diversas pastas para as imagens: drawable-ldpi (low),
drawable-mdpi (medium), drau/able-hdpi (high), drau/able-xdpi (extra high)
e drawable-xxdpi (extra extra high). Na ltima verso do Android Studio
ele no cria todas as variaes, eu criei para mostrar a voc.
res/mipmap Pasta com o cone da aplicao, o qual por padro chama-se ic_launchex png.
Da mesma forma que a pasta /res/drawable, esta pasta tambm apresenta
variaes conforme a densidade da tela do dispositivo.
res/layout Pasta que contm os arquivos XML de layouts para construir as telas
da aplicao.
res/menu Pasta que contm os arquivos XML que criam os menus da aplicao,
que so os botes com aes na action bar.
res/values Pasta que contm os arquivos XMLutilizados para a internacionalizao,
congurao de temas e outras conguraes.
Cada arquivo seja imagem ou XML dentro da pasta /app/res contm uma referncia
na classe R, que automaticamente gerada ao compilar o projeto. Cada vez que
se altera, adiciona ou remove um arquivo dessas pastas, a classe R alterada para
reetir as informaes.
Por exemplo, se voc inserir uma imagem chamada smilepng em uma das pastas
/res/drawable, a constante R.drawable.smile ser automaticamente gerada na classe R.
Se voc inserir um arquivo XML chamado teste.xml na pasta /res/layout, a constante
R.layout . teste ser gerada. A classe R nossa grande aliada no desenvolvimento para
Android e nunca deve ser alterada manualmente. Observe que o cdigo-fonte da
classe MainActivity utiliza a constante R.layout.activity_main, a qual define o layout
utilizado para apresentar a tela ao usurio.

MainActivity.java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nain); // O layout da tela denido aqui
}

@0verride
oooqio Android ~ 4 d|
76

publlt haolvan on(roato0ntlomMenu(Henu menu) J menu). // Menu com botes na action bar
9t*lMt~nulnalr().ln\tt*(R"''~"cUV{ty~m n' A '
return tlui
1

\ _` , .z . -. ~ (UIC\'l\`;ll'ClI\tflllll
. .~ '. . - I; -Li.: *MalnActlvlty.rt \ttH"" U V Q
NO!l.l\titnt||ti Itmlt t lx vt l g I. ` H h.. mm`mc|1I(* tl
kh) Jg,R_1yaut.actlvlty_maln. /\inIrnt . tua n
l ~ ~ ' ^ W.1|ml.Isszitt1iic;it1H1
nltquivn dc 'nx- H /,rx/l`?|)|((/|( H'_\'_ HUN". \", lu) UIIUI \ P*
ii Ctrl+cllque utilizntln cm niuittis mitrns |\|i24"`<`~

3.2 Arquivo AndrodManfest.xmI


O iirquiviiz\nlri.I\~1ini_/i*s!.xml ii lmsc do uma ;1|?|itf;1 Andriiid c ctmtnt todas
nstwnigurucsticccmhiusixuuivxccutnriimohcntt
Qiiindu crinnitis ti prujctti HelloAndroldStudlo nn cipttiln mtcrior. iki criada ai
Malnnctlvlty c vlzi iiii miiiigiirntli ititmirizitnicziniciitc um arquivo /lminidMmi_'sr.xrnI
tftiimm activity inicial du pi'ictt,tti sujz1,(*it|ticI;i idivityqtic contni miric na
tcln initfiul (l lume) c rcprcscnta ti uplicitivti que ti tisui_'i vai executar. Nu ctligo ai
wwmumwmwmmmpmwmnmmnmmmmmmkmnmwnAmmmMmmkuxmL
n1:nittlcin C(Hl1ilCl1(L

1% Andro|dMan|fest.mI

?ml verslon="1.u encodlng="utf-8"?


manlfest mlns:androld="http://schemas.androld.com/apk/res/androld"
DCka9e="br.com.llvroandrold.helloandroldstudlo" /I Pacote nlco do projeto
appllcatlon

d'td*u"BC'<UP="U`U" // Se for true entao permlte backup no cloud


"dfd11<="@MlDmap/lc_launther" // cone do apllcatlvo na tela Home
"d'td*labl="@5't"9/PPa" // Nome do aplicativo na tela Home

- d tl _ i
androld:theme="@5tyl@/Apprhemev , Tema d i It
octlvlty 00 Cl/0 (/tvs/values/styles.ml)
androld:name="_n1ntV
Y" // Classe da Actlvlty que deve ser a@u1;d,
"f*<'=11"'@Slfloo/ooo nan@'~ // Titulo

lntont.ltor
A // Declara um ltro para exect avals mostrar na action bar
// ao MAIN indica que tff BCVY D0de ser executada com
|ctlon ondrold:n|mo~"|ndrold.lntont.|ctlon.HAIN" / O a inicial
Captulo 3 I' Conceitos bsicos do Android 77
// A categoria LAUNCHER indica que o icone da activity deve car disponivel
// na tela inicial
<category android:nane="android.intent.category.LAUNCHER" /
</intent-lter>

<activity android:name=".LoginActivity" />


<activity android:name=".CadastroUsuarioActivity" />
<activity android:nane=".BemVindoActivity" />

O XML sempre deve iniciar com as linhas a seguir, declarando o namespace para vali
dar os atributos utilizados e o pacote da aplicao. O encode do XML deve ser UTP-8.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="br.com.livroandroid.helloandroidstudio">

Dentro da tag declarado o pacote principal do projeto, utilizando a


tag . Esse o pacote identicador do projeto e deve ser nico no Google
Play O mesmo pacote declarado no arquivo app/build.gmdle, o qual vamos ve
ricar mais tarde.

obrigatrio que cada activity do projeto esteja declarada no arquivo


AndroidManiest.xml e para isso utilizamos a tag , a qual recebe o nome
da classe.

Geralmente um aplicativo Android tem um cone que ca na tela inicial do


Android. Quando o usurio clica nesse cone, a activity inicial do projeto exe
cutada, que neste caso a MainActivity.
<activity android:name=".MainActivity" android:label="@string/app_nane">
<intent-lter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-lter>

A tag <intent-lter> necessria para customizar a forma como a activity ser


iniciada. A ao MAIN significa que a activity pode ser iniciada isoladamente, como
o ponto inicial da aplicao. A ao MAIN como a famosa funo nain() da lin
guagem C, a qual utilizada para iniciar a aplicao. A categoria LAUNCHER indica
que a activity estar disponvel para o usurio na tela inicial junto com as outras
aplicaes que o usurio possui instaladas.
78 .'. utras
ong
Iml rWc*
~ de que
_ . ~ ~ uma activity_SLTH
na L . .
. . na
maioria
f levem conter
das \tes
' ' C urada
esse
somente ti OPde Con
Goo9le Android - 4 @d

como O POW ds Partida' portanto s O C ~ 'vit com a classe BemVndoAct1vtty


aurao. Por exemplo, para declarar uma acti y
basta uma declarao simples asslmi
<activty androd:nane=".Ber'\Vd0ACVfY" />
i los forem sendo criados nos ximos pro
captulos,_111815
A medlda que novos exemp ~ - ' ' l "o fornecidos.
detalhes sobre a conguraao do arquivo AndrozdMamest.xm Sera

tiviz Obrigatrio
Notazsempre . . . - t inicia a
que criarcongur-la
uma nova ac yO
_ _afqulvo
_ _ , ld
AndroidManifesz.xml. A Ma1nAct1v1ty foi configurada como a EICUVI Y_
LAUNCHER. Mais detalhes
aplicao, pois est declarada com a ao MAIN e a categoria 1 Intent
sobre 3 tag <intent-1ter> sero explicados no capitulo 20, sobre a c asse .U

3.3 (Iasse MainActivity


Aclasse MainActvty foi congurada pelo vvizard do Android Studio como a activity
inicial, portanto pode ser executada pelo usurio ao clicar no cone do aplicativo
na tela Home do Android.

A classe ManActvty ou qualquer outra activity deve ser lha da classe androd.
app.Actvty.

public class ManActvty extends androd.app.Activity {

A classe androd.app.Activty representa uma tela da aplicao, sendo responsvel


por controlar o estado e os eventos da tela. Assim, para cada tela da aplicao

An d `
ar '
~._1 e
'
desc h d _na ac tvtty
n.A.nao
t .l ~sabe
voc criar uma classe-lha de androd.app.Actvty. O mtodo onCreate(bund1e) pre

_' app
old.
cisa ser implementado obrigatoriamente e chamado de forma automtica pelo
n roid quando a tela e criada No entanto a classe andr ' '
21 Ila e para isso precisa da ajuda da classe andro1d.v1ew.Vew, que
POY SUH VZ Se encarrega de desenhar os componentes visuais como cam d
fex, botoes e imagens. Para isso existem diversas subclasses especializafias de
mostra o na guravericar
33 No asdiaclas
~ ml
' Q
andro1d.1ew.View, conforme podemos verificar no diagrama de classes resu .d
_ grama podemos
Ed1tTet, Inagevew etc., responsveis por desenhar . I SCSITEXVIEW, Button,
os e ementos gracos da tela
Captulo 3 n Conceitos bsicos do Android 79
G andro|d.app.Activity
0 f|ndViewById(id: int): android.view.View _ G an ro Cl Id. ` .Vl
View ew
O setContentV|ew(layoutResID: int): void O dfBW(C6I'IV51 android-cr=DhicS.CvS)= VO
0 setContentView(view: android.view.\ew): void V

4 V l V A \
G android.widget.TetView G androidiwidgeumagewew Q and,.d_Vew_VewGmUp

Q android.widget.AbsoIuteLayout \\
G ndroid.widget.Button j G android.widget.EditTet | _ G android.widget.ReIativeLayout

Q andro|d.widget.FrameLayout

Q android.widget.L|nearLayout

G android.widget.TableLayout

Figura 3.3 - Hierarquia da classe android.1/ieu View

Na classe Activity, podemos vericar pelo diagrama que existem dois mtodos
setContentView(view); o primeiro recebe um argumento do tipo View, e o segundo recebe
um nmero inteiro indicando o recurso de algum arquivo XML de layout. Isso porque
no Android possvel construir a tela de duas formas: diretamente pelo cdigo-fonte
Java, ou utilizando um arquivo XML de layout que define a view que ser exibida.
Independentemente de qual verso do mtodo setContentView(view) for chamado,
seja informando um objeto ou um arquivo de layout, esse mtodo responsvel
por fazer a ligao entre a activity e a view que ser responsvel por desenhar a
interface grca da tela, e deve sempre ser chamado durante a execuo do mtodo
onCreate(bund1e) da classe Activity.

Nota: para cada tela da aplicao existir uma activity para controlar seu estado e
eventos, mas para denir a interface grca da tela utilizada uma view. Dentro
da activity necessrio chamar o mtodo setContentView(view) para informar a
view responsvel por desenhar a interface da tela.

Se voltarmos para vericar o cdigo-fonte da classe MainActivity, podemos verificar


que o mtodo setContentView(view) recebeu a constante R.1ayout.activity_main como
argumento:
setContentView(R.layout.activity_main); // Arquivo /res/layout/activity_main.xml

Nesse caso, a classe R utilizada para acessar o arquivo /res/layout/activity_main.


xml de forma mgica e convert-lo em um objeto do tipo View.
80 _ , .Menu
. ` - > nstra uma sim;~C_l `. z
menu),tiict.uii
l _ ' r-t i1. '\w C
, - . ~foiu criado
~ ~- bem

` f "
I ' tu;aI11Cl

_
automa .
Google Android - 4 dl

m\(,(|oonCreate0pttonsMenu( I ` g l ' `_ K ' Sm|cmm;1atle como criar


`|SSCMalnACHVlty'dpumdulln .' f l on0 ttonsItemSelected(MenuItem item) C
um item de menu na action bar. _l.1 0 nclm O D' li ido na action bar. Mas por
](Cl18

ns v' ~ '
cliarnado Ll*m*l *lltllm l><*f=' U cm dk lmllm JGIOQ estudar tudo isso dep0I5
enquanto no se l`\UP mm essa plrtc' I (

, . . V , ~ - 'f MLou utilizar. a.Al


)I
3.4 Arquivo de layout activity_main.xml
No Android possivel criar o layout da tela em atquix os X <
z _e criai
- . o. layout
~; em varara l1ica
sc; 8 dene
java. mas o recomendado - ~ . . ~ ' ' rillerdo
XML, pai
gocios da camada de apresentaao. Podemos dizer que a activity e O Cont 1
pad,-50 MVC (Model View Controller) e a view o arquivo XML com o layOUI~
Uma view pode ser um simples componente grco (boto, checkbox, imagem) OU
uma view complexa. que atua como um gerenciador de layout, que p0Cl COHYT
varias views-lhas e tem a uno de organiza-las na tela. Os gerenciadores de layout
serao explicados no captulo . No cdigo a seguir, podemos visualizar 0 cdigo
-lonte do arquivo /res/layouz/activiry_main.xml que dene a interface grca da tela.

/res/layout/activity__main.xml
<?ml version="2.G" encoding="utf-8"?>
<RelativeLayout xmlns:androtd="http://schemas.androtd.com/apk/res/androtd"
xmlns:tools="http://schemas.android.com/tools"
androtd:layout_width="match_parent" // Largura da tela
android:layout_hetght="match_parent" // Altura da tola
androtd:paddtngLeft="@di.men/activtty_hortzontal_margin" // Espaamento na esquerda
androtd:paddngRtght="Qdtmen/acttvtty_hortzontal_margtn" // Espaamento na direita
android:paddtngTop="@dimen/activty_vertical_margtn" // Espaamento no topo
androtd:paddingBottom="@dtmen/acttvity_vertical_margln" // Espaamento em batxo
tools:contet=".HalnActtvity">

<TetVtew // Componente (view) que mostra um texto (label)


android:textz@string/hello_world" // Mensagem
androtd:layout_width="wrap_content" // Largura da view
androtd:layout_height="wrap_content" /> // Altura da view
/RelativeLayout>

_ML
. _ un
.'~ ( k ` ai `
' ~' '- " Q af UWUS
_
No cdigo loi utilizada a sintaxe @d
tmen para acessar valores de espa im
;1m dehnidos no arquivo /res/values/dinicms.xml. Deixar essas constantes 1 qul fo
0 0 Cm
_ _e poder customizar
constanteso uand
valor d -l J. I
Zad I, 13 boa pratica porque podemos alterar o cdigo ein um lugar cekiltr' l`
essas
exemplo, para uulizarum valor dihei . _, , , _., q 0neCeS*m PW
tte para a versao tablet do mesmo aplicativo.
Captulo 3 1 Conceitos bsicos do Android 31
/res/values/dmens.xmI

<!- Espaanento recomendado pelas boas prticas do Android Design. -->


<dinen nane="activity_horizonta1_nargin">16dp
<dimen name:"activity_vertica1_nargin">16dp

Nota: o valor 16dp recomendado pelas boas prticas de interface (guidelines)


como o espaamento padro para as margens de um layout. A notao dp
(density independent pixels) uma unidade de medida do Android para tornar
transparente ao desenvolvedor a quantidade de pixels utilizada em cada aparelho.
No Android nunca se deve utilizar a unidade de pixels (px), pois isso pode trazer
resultados diferentes dependendo da resoluo da tela. Uma dica interessante
utilizar o Ctr1+C1ique no arquivo XML, pois ao passar o mouse em cima das
notaes @dimen/valor ou @string/texto podemos abrir rapidamente o arquivo em
que os recursos foram denidos.

No cdigo-fonte do arquivo /res/layout/actii/ity_main.xml podemos ver a tag


<TetView> que mostra um simples texto na tela. Essa tag dene o atributo
android:text:"@string/he11o_wor1d", que utiliza uma mensagem identicada pela
chave heiio_wor1d localizada no arquivo /res/values/stringsxml. Observe que no
arquivo existem as tags e <TetView>, que correspondem s classes
ReiativeLayout e Textview, respectivamente. Ambas as classes so filhas da classe
android.view.View do Android. A classe Re1ativeLayout um gerenciador de layout
que tem o papel de organizar a disposio dos componentes. Nesse exemplo a
tag <TetView> est contida dentro da tag justamente para compor
a interface da tela.

Nota: para cada tag denida no arquivo XML de layout existe uma classe
correspondente que filha de android.view.View. Para exemplificar, as tags
<TetView>, e correspondem s classes android.widget.TetView,
android.widget.InageView e android.widget.Button.

Se voc abrir o arquivo /res/layout/activity_main.xml no editor, ver que na parte


inferior existem duas abas para alternar entre o cdigo-fonte XML e o editor
visual (Figura 3.4).
A figura 3.5 demonstra a opo Preview AII Screen Sizes, que mostra no editor a pr

muito no desenvolvimento.
-visualizao para diferentes tamanhos de telas. Esse recurso incrvel e ajuda
82 ..' .. ... ,_ ._ Goo9Ie Android - 4' d9

,,z.i
"o Q .~.z--~ - ooo e
.. . tz.. ii W o ~~~
izz,..,.... iai- ea tu
g 1 lfnmel YU' 7 .. .J
i l u l ineml you! (Homontd),
i [mari you! (VCWU i
Tablcl you!
W mzunow
l `5uyn
llljkclmvelayout
E Cl W'
Plam Tcxwitvv
i gm; urge Ten
i Wii Medium Text
E *Abi Small Text
J Button

rz ] p 4
wi Smallufkon

ll \Rdo8u!!on
~.
Q _ .`_...z.. - --fz
l__QCheclr8ox

Figum 3.4 - Editor visual.

No Android voc deve criar layouts que se ajustem automaticamente ao tamanho


e a resoluo da tela; portanto, se voc desenvolver corretamente, no tera pro
blemas com a diversidade de aparelhos. Apenas no caso dos tablets que tm um
grande espaco disponvel na tela talvez seja necessario um layout espec eo para
oferecer tuna melhor experincia ao usuario. Isso e feito para deixar o aplicativo
mais agradavel a fim de que seja utilizado no tablet, mas por padro o layout
de um aplicativo que funciona no smartphone deve funcionar perfeitamente no

i! (tuto
r iLmsupevo
I ~., m ifpw
tablet ou ate mesmo no Google TV

jmlquuh
3"'*Y-"""-W' '* vt A i _l `
G' ' "Nmn4~ - Owomm "Muvmmy- 6- vwzy. ii i
on bw __ Q'
i l *reohilcyoutduge tu
l UQIQOQNH..
l V *"*~vw *r;~~e~,i1.!-\r~.t.~

L - ii 'hlxilv zilug-z,
z F3 \ Pim.. nrguwim tm
hl pl Andmud Vamu-u
i'\*l li: r-= iva fz.1\i
' V-'Y-' la.z ;l\r rx

p logon uma Moo.


3 nz:o.zz
_ ;;ChIrlon l
i ` SIIKTI
i

' ei .
i

'_ .Y vlw
lr ieo,'-Jp c

Fium3$---- ' -._ .~ ,.


g P' ' WWl~It1 para varios tlispositivos
Captulo 3'n Conceitos bsicos do Android 33
3.5 Arquivo strings.xmI
O arquivo /res/values/stringsxml contm as mensagens para organizar os textos
em um nico arquivo centralizado, o que uma boa prtica de programao.
As mensagens desse arquivo podem ser traduzidas para diversos idiomas para
internacionalizar o aplicativo. Por padro, esse arquivo contm o nome do apli
cativo que digitamos ao criar o projeto e a mensagem que aparece na tela inicial.

/res/values/strings.xmI
<?ml version="2.G" encoding="utf-8"?>

<string name="app_name">HelloAndroidStudio
<string name="hello_world">Hello world!
<string name="action_settings">Settings
O nome do aplicativo denido pela chave app_name, e o texto que aparece na tela
denido pela chave hello_world. No arquivo /res/layout/actii/ity_main.xml, ao denir
a tag <TetView>, foi utilizado o atributo android:tet="@string/hello_world" para refe
renciar a mensagem denida pela chave hello_world. O padro para acessar essas
mensagens, como voc j deve ter percebido, @string/nomeDaChave.
Para criar um aplicativo com suporte a diversos idiomas, basta criar uma pasta
/res/values/values(cdigo do idioma) e traduzir 0 arquivo /res/values/strings.xml . A seguir
temos um exemplo de uma pasta com as mensagens em ingls e outra em portugus.
/res/values-en/strings.xml
/res/values-pt/strings.xml

3.6 Classe R

A classe R gerada automaticamente ao compilar o projeto e contm as constantes


para acessar os diversos recursos do projeto. Sempre que um recurso adicionado
no projeto, como por exemplo uma nova imagem, a classe R gerada automatica
mente para conter uma constante para 0 novo recurso criado. No Android Studio
a classe R gerada na pasta app/build/generated/source/r_

R.java
public nal class R {
public static nal class attr { }
84

l} _i
public static nal class dcawable a 20000.
Dublic static nal int icon=97 0 f

public static nal class lay0U


public static nal int main=0x7fG3000G,

public static nal class string { .


Google Android - 4 d9

public static nal int DD_3e=@7f9400e1'


public static nal int hello=07f040000,
}

naente!
Nota: a classe R nunca deve ser alterada manual -F __ _

3.7 Informaes sobre como acessar recursos de texto e imagem


Vamos aproveitar que falamos da classe R e explicar um pouco mais sobra sm
taxe para acessar os recursos do projeto. Para explicar alguns conceitos, veia este
trecho de cdigo do arquivo AndroidManiest.xml.
<application android:icon:"@nipmap/ic_launcher" // cone do aplicativo na tela Home
android:label="@string/app_name" ... > // None da pllcao na tela He

A tag android:icon dene o cone do aplicativo que vai car na tela inicial do
Android, sendo que a sintaxe @drawable utilizada para acessar a imagem
/res/drawable/ic_launchexpng. Essa sintaxe padro para acessar imagens sempre
que voc estiver em algum arquivo XML. Por exemplo, ao adicionar uma view
do tipo Imageview no arquivo /res/layout/activity_main.xml, podemos mostrar uma

Porm cas
gura utilizando a notao @drawable/none_gura:

ImageView android:src="@drawable/none_da_gura"

_ _ - os e mr um
1 _ _ _
android:layout_width="wrap_content" android:layout_height="wrap content" />
magem mamicamente
o voc precise acessar esse Imageview e atualizar a i d'
pelo codigo Java, vai precisar utilizar a classe R Primeiro precisam d `
identicador para o Inageview com a tag android:id e a sintaxe @+id/identgado
<InageView android:id="@+id/img"

- ~ _ 9 = wrap_content" />
android:layout_width="wrap content" androidlay0ut hei ht "

Com este id possvel utilizar o mtodo ndViewById(id) no cdi o d ' '


imagem
acessar come adepois
esse objeto, Condisso
i para acessar
utilizada a classe o
R recurs d
a actmty para
stante R . drawable . none_inagem. O 8
Captulo 3 i Conceitos bsicos do Android 35
// Encontra o objeto pelo id
Imageview img = (ImageView) ndViewById(R.id.img);
// Atualiza a imagem dinamicamente. A classe R utilizada para acessar o recurso.
img.setImageResource(R.drawable.nome_da_imagem);

Agora vamos falar um pouco de mensagens e o arquivo /res/values/stringsxml. Se


voc reparar novamente no cdigo do arquivo AndroidManifest.xml, ver que o
nome da aplicao foi denido pela chave @string/app_name. A mesma sintaxe pode
ser utilizada ao criar o layout dos arquivos em XML. Por exemplo, no arquivo
/res/layout/activity_main.xml foi criado um Textview que referencia a mensagem
@string/hello_world, conforme demonstrado a seguir.
<TetView android:text:"@string/hello_world"
android:layout_width="wrap_content" android:layout_height="wrap_content" />

Da mesma forma que zemos com o Imageview, tambm possvel atualizar o


texto de um Textview dinamicamente. Para acessar o objeto do Textview no cdigo,
novamente preciso denir um identificador para a view com a tag androidzid.
<TetView android:id="@+id/text"
android:layout_width="wrap_content" android:layout_height="wrap_content" />

Para acessar esse objeto Textview no cdigo, basta utilizar o mtodo ndViewById(id).
Note que a constante R.string.hello_world utilizada com objetivo de acessar a
mensagem hello_world que est denida no arquivo /res/values/stringsxml.
// Encontra o objeto pelo id
Textview text = (Textview) ndViewById(R.id.text);
text.setText(R.string.hello_world); // Atualiza o texto dinamicamente.
A fim de encerrar o assunto, vamos fazer uma breve reviso. Lembre-se de que a
notao com o caractere @ utilizada sempre que for necessrio acessar um recurso
em um arquivo XML. Caso o recurso precise ser acessado no cdigo Java, preciso
utilizar a classe R. A tabela 3.1 compara as duas formas de acessar os recursos:

Tabela 3.1 - Formas de acessar um recurso

Objetivo Utilizando XML Uti|izandoacIasseR


na pgastag/r'es/drawable _
z\cessarz1iniageniouzpngltxxizada. @drawab1e/foto R drawable foto l

Acessara mensagem hello definida @Strng/heuo R'String'heu0 2


no arquivo /res/values/strmgs.xrrzl l
86 Google Android - 4 edio
3.8 Arquivo buiId.gradIe
O sistema de build do Android baseado no Cradle. No projeto existe o arquivo
build. gradlc padro de todos os mdulos e o arquivo app/buildgradle com as con gu
raes de compilao do mdulo app, que onde ca o cdigo-fonte do aplicativo.
A seguir, podemos visualizar o arquivo buildgradle que ca na raiz do projeto.
Na prtica, voc no vai alterar esse arquivo, exceto se o plugin do Gradle for
atualizado, pois no arquivo ca o cdigo da verso do plugin.

buiId.gradIe
buildscript [
repositories {
jcenter() // Repositrio padro do Android
}

dependencies {
// Verso do plugin do Gradle. Se o plugin for atualizado atualize este cdigo
// Caso tenha um erro de compilao nessa linha, tecle Alt+Enter para abrir o assistente
// O assistente vai ajuda-lo a congurar a verso correta do plugin
classpath 'com.android.tools.build:gradle:1.0.9'
}

allprojects {
repositories {
jcenter() // Repositrio para todos os projetos
l
}

O arquivo mais importante o app/buildgradle que ca dentro da pasta do m


dulo app do projeto, lugar em que ca o cdigo-fonte da aplicao. No arquivo
app/buildgradle voc congura a verso do aplicativo e tambm a verso mnima
do Android (API Level) que seu aplicativo suporta, alm de declarar as bibliotecas
que so necessrias para a compilao. A seguir podemos visualizar o cdigo-fonte
do arquivo app/build.gradle. '
app/buiId.gradIe
apply plugin: 'com.android.application' // Aplica o plugin 'android' no script de
// compilao do Gradle
android { // Este elemento congura os parmetros de compilao do mdulo
compileSdkVersion 22 // API Level usada para compilar o cdigo (deve ser sempre a ltima)
buildToolsVersion "22.6.1" // Verso do Android SDK Build-tools baixada pelo SDK Manager
Captulo 3 1 Conceitos bsicos do Android 37
defaultCong { // Este elemento congura os itens do AndroidManifest.ml
applicationld "br.com.livroandroid.helloandroidstudio" // Pacote do projeto
// (identicador nico da aplicao)
minSdkVersion 22 // API Level minima que o aplicativo suporta.
targetSdkVersion 22 // API Level mxima utilizada para otimizar o build na compilao
versionCode 1 // Cdigo para identicar o aplicativo no Google Play
versionName "1.0" // Verso do cdigo com formato amigvel para o usurio
}

buildTypes { // Este elemento congura os tipos de build (debug e release)


release { // Congura o build do tipo release
minifyEnabled false // Congura para utilizar o proguard e obfuscar o cdigo
}

l
dependencies { // Declara as dependncias (bibliotecas) para compilar do projeto
// Inclui todos os arquivos .jar da pasta libs na compilao
compile leTree(dir: 'libs', include: ['*.jar'])
}

No nal do arquivo app/buildgradle so declaradas as dependncias do projeto,


mas isso vamos exercitar bastante durante o livro, portanto que tranquilo. A
parte mais importante desse arquivo de congurao so todos os itens que cam
dentro do elemento defaultCong. Nesse elemento so congurados: o pacote do
aplicativo, a verso mnima do SDK e o cdigo de verso do aplicativo. Antiga
mente essas conguraes cavam no arquivo AndroidManifest.xml, mas agora
tudo gerenciado pelo Gradle.
Com o Gradle possvel criar builds customizados do aplicativo, para, por exem
plo, criar verses que apontem para web services de homologao ou produo.
Todo esse poder e flexibilidade para fazer o build uma das vantagens do Gradle,
alm de gerenciar as dependncias, claro.

Nota: todo aplicativo (apk) deve ser assinado com um certicado digital antes
de ser instalado no dispositivo. Por padro o sistema de build do Gradle
compila o projeto no modo debug e release. O modo debug utilizado durante
o desenvolvimento, e o aplicativo assinado com o certicado digital de
desenvolvimento, o qual criado automaticamente pelo Android Studio e ca
na pasta do usurio ~/.android/debug.lceystore. O modo release utilizado para
publicar o aplicativo no Google Play e deve ser assinado com outro certicado,
o qual voc precisa criar. Vamos estudar mais detalhes sobre isso no captulo
38, sobre Gradle.
88 Google Android - 4 edio
3.9 Log(at - Escrevendo mensagens de log
Em java, para imprimir uma mensagem no console utilizado 0 coman
do Systen.out.println(string), mas no Android recomendado utilizar a classe
android.util.Log, que contm mtodos utilitrios para imprimir informaes com os
niveis de detalhes desejados, como informao (i), debug (d), warning (W) C ff0 ()~

Dica: no Android Studio, utilize a tecla de atalho Alt+6 para abrir a janela 6:Android.
Nessa janela voc ver os logs do LogCat,`que tem por nalidade gerenciar todos
os logs do sistema operacional.

Com a classe android.util.Log possvel criar logs de informao, debug, alertas e


erro. Cada log pode ser escrito em uma determinada tag, para que posteriormente
apenas as mensagens desejadas sejam recuperadas. Para demonstrar como criar
logs em diferentes nveis de severidade, altere o cdigo-fonte da classe MainActivity
conforme demonstrado a seguir.

MainActivity.java

inport android.util.Log;
public class MainActivity extends Activity {
private static nal String TAG = "livro";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_layout);
OOI

Log.v(TAG log de verbose");


Log.d(TAG log de debug");
Log.i(TAG log de info");
Log.w(TAG log de alerta"); _
Log.e(TAG log de erro", new RuntimeEception("teste de erro"))
}

Observe que a constante TAG denida na classe utilizada como identicador das
mensagens. Isso til para ltrar as mensagens por tags/categorias, facilitando a
visualizao e debug. Os mtodos da classe Log so bem simples, e comeam com
a primeira letra do nvel de severidade. Por exemplo, para imprimir um log com
nivel de alerta utilizado o mtodo Log.w(tag,nensagen). O W da palavra warning
Captulo 3 n Conceitos bsicos do Android 39
(alerta). importante entender que necessrio informar a tag do log, para que
depois seja possvel ltrar os logs apenas da tag desejada.
Agora execute o cdigo e visualize os logs gerados na janela LogCat (Figura 3.6).
Observe que mensagens vermelhas no LogCat so erros. Neste exemplo lancei uma

. . logar ~-o'
exceo no cdigo para voc visualizar um erro de teste, portanto acostume-se a olhar
o LogCat, pois qualquer exceo lanada pelo seu aplicativo ser detalhada aqui.

os-oe 15:41 O4 son 1211-1217/2 I/Jdwpi rqnonnq se o dzbuqqez puizzq and droppinq 'A Y
h9~06 l5:4 04 500 1073-1079/7 I/Jdwpi Iqnoxring second debuqger ~- pcing and drcppinq j
59-96 5 4 O-1 500 1280-1286/? I/Jdwp= Iqnoring second debuqqer -~ a ceptinq and droppinq
O9 O6 15 Of; 680 402-416/? I/Choreoqrapheri Skipped 30 frame! Th pplication my be doing wo much work on its main t 1. 5
9 06 l5 4 OS 80 402-416/7 I/Chareographer Skipped 30 frames! Th pplmation may be doing too much work on its mam t `
9 O6 l i O5 490 1750-1750/? V/livro log de verbose
9 E 15 -i O5 3flO 402-1G/7 I/Choreographerf Skipped 36 xames! Th applic :on may be doing too much work cm 'cs main 1 `.' 1
9 3 15 05 4390 1750-1750'? Dlivre log de debug
O 15 ~ 05 4 O 1750-1150/7 I/livro' log de info
9 E 5 4 5 500 1 50-1750/? H/livro~ log de alerta
l ~l Sl 175 -1750/? E/livro log de erro
g R nti.:eE p 1 n neste de erro
i::.l1vroa ci d livroend:o1.d_cp03.Hair\r:t1..'i;y.onC:e'ce(Ma1rzAct:;v1tz.zava:31)
ac ar:1r:1_d.app A 1:ivir.y.performC:ear:e{ .`z ' ,_;ff;_*',, ~1)
andrf.:1d.a p I umencation.calLz'c:1vii:yCnCreate(` .~V ~ '''= ;.''";_V,.i.:f3; f)
c ndroid pp A t' ` _1'hrea .performLaunchActiv1t:y(%ir* i-:':.2, '1z~)
:X cl pp A \:` `1:y'1'h ea .hondleLaunchl1;ivity(.fz; ;.. iQ:j_;_-;;fff_'_f_)
d d pp A ` y'l'b .acces:r$E0O(`. m jzff ` f f f)
d d pp A y'Ih i.hand1e2$es:sege(..;:* . ; ' ~. _ ;; _)

Figura 3.6 - ]anela LogCat.

Contudo, podemos vericar que nos logs no aparecem apenas as mensagens


que criamos, pois tambm aparecem todas as outras mensagens do sistema ope
racional. Mas foi exatamente por isso que criamos os logs utilizando a tag livro,
pois agora podemos ltrar as mensagens apenas dessa tag.
Para criar um ltro, procure no canto direito superior da janela LogCat o combo
com os ltros e clique em Edit Filter Conguration. Feito isso, crie uma congurao
de ltro para a tag livro, conforme mostra a gura 31
Create New Logcat Filter z=- z~=.

+ - =~= Ml
Filter ogcat messages by different parameters.
Empty elds will match ali messages.

=LI=z=rff== W l
. by Log Message (regex):
by Pgckage Name: J
bz-flD= l_w__w_W_,_,__-_;
by Log Lad: VEIKE _

l-<=*l

Figura 3.7 - Criao de um ltro para 0 LogCat.


90 Google Android - 4 edio
Nesse caso o nome da tag livro, pois o valor da constante TAG que definimos na classe.
private static nal String TAG = "Iivro";

Depois de criar o ltro, possvel visualizar somente os logs gerados pelo nosso
aplicativo (Figura 3.8). Agora podemos ver somente as mensagens que nos interessam.
Q- _
ioglfvel Verbos: lf '``- A`
i 41 1
1 il1 "
ql

'J
F
;) il J
J

l"

Pi
1 l
' l
J
l

Figura 3.8 - janela do LogCat exibindo as mensagens do ltro desejado.

Importante: acostume-se a utilizar o LogCat, pois nessa janela que todas as


mensagens de logs e erros so exibidas. Lembre-se de que, em caso de erro, o
stack trace das excees aparece no LogCat, e voc pode inclusive vericar
o nmero da linha que originou o problema. Sempre que seu aplicativo travar
(force close), olhe as mensagens de erro no LogCat. Lembre-se de no utilizar
o System.out.print1n diretamente, pois recomendado utilizar o LogCat e separar
os logs em nvel de severidade e tags.

3.10 Tratamento de eventos

Neste prximo exemplo vamos alterar o layout da MainActivity para criar uma tela
de login com dois campos para o usurio e senha, a m de fazer a validao desse
login de forma simulada. Neste exemplo vamos aprender no s a tratar o evento
de clique em um boto, como tambm a ler os valores digitados pelo usurio.
Para comear a brincadeira, altere o cdigo-fonte do arquivo /res/layout/
activity_main.xml conforme demonstrado a seguir:
Captulo 3 I Conceitos bsicos do Android 91
/res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout nlns:android="http://schenas.android.con/apk/res/android"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:gravity="center_vertical" android:orientation="vertical"
android:padding="16dp">
<TetView
android:layout_width="natch_parent" android:layout_height="wrap_content"
android:tet="@string/usuario" />

<EditTet android:id="@+id/tLogin"
android:layout_width="natch_parent" android:layout_height="wrap_content"
android:inputType="tet" android:singleLine="true" />
<TextView
android:layout_width="natch_parent" android:layout_height="wrap_content
android:layout_narginTop="10dp" android:tet="@string/senha" />
<EditTet android:id="@+id/tSenha"
android:layout_width="match_parent" android:layout_height="wrap_content
android:inputType="textPassword" android:singleLine="true" />
<Button android:id="@+id/btLogin"
android:layout_width="2G0dp" android:layout_height="wrap_content"
android:layout_narginTop="6dp" android:tet="@string/login"
android:textColor="#ffffff" android:layout_gravity="center"/>

A tag raiz desse layout um Lineartayout, que um gerenciador de layout que


organiza as views na horizontal ou vertical. Nesse caso a orientao foi congu
rada como vertical com o atributo android:orientation="vertical", portanto as views
sero posicionadas uma abaixo da outra. A tag <TetView> um simples label e a
tag <EditTet> um campo de entrada de dados para o usurio digitar um valor.
A tag , acredito que dispensa apresentaes.
O importante voc perceber que no layout foi adicionado um id para os dois
campos de texto e tambm para o boto. Isso feito com a tag android:id. No c
digo vamos utilizar o mtodo findViewById(id) para acessar esses objetos pelo id. A
seguir podemos vericar o cdigo-fonte atualizado da classe MainActivity que trata
o evento no boto e faz o login para o usurio ricardo e senha 123'

MainActivity.java

// Faa os imports das classes necessrias aqui.


// Caso no esteja familiarizado com Java, utilize o assistente do Android Studio.
92 Google Android - 4' ed0
/I Na linha do erro voc pode clicar neste assistente para fazer o import.
// O atalho ALt+Enter abre o assistente se o cursor estiver sobre a linha.
// O menu Code > Optimize Imports tambm pode ajudar.
public class HainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btLogin = (Button) ndViewById(R.id.btLogin);

@0verride l
btLogin.setOnClickListener(new View.0nClickListener() {

public void onClick(View v) {


Textview tLogin = (Textview) ndViewById(R.id.tLogin);
Textview tSenha = (Textview) ndViewById(R.id.tSenha);
String login = tLogin.getTet().toString();
String senha = tSenha.getTet().toString();
if("ricardo".equals(login) && "123".equals(senha)) {
alert("Bem-vindo, login realizado com sucesso.");
} else {
alert("Login e senha incorretos.");
}

});
}

private void alert(String s) {


// A classe Toast mostra um alerta temporrio muito comum no Android
Toast.makeText(this,s,Toast.LENGTH_SHORT).show();
l
}

No Android, para tratar os eventos de um boto utilizado o mtodo


set0nClickListener(iistener). Esse mtodo recebe como argumento uma instncia
da interface android.view.View.0nClickListener. A interface View.0nClickListener define o
mtodo onClick(view), o qual chamado quando o evento ocorrer, passando corno
argumento o objeto da view que gerou o evento, neste caso, o boto.

Nota: para definir um id para os componentes utilizada a notao android:id="@+id/


identicador_aqui". O mtodo ndViewById(id) utilizado no codigo para encontrar
uma view pelo seu id.

Depois dessa alterao, execute o projeto para conferir o resultado (Figura 39).
Ao digitar o usurio "ricardo" e senha " l2.3", o login de teste realizado.
Captulo 3 I Conceitos bsicos do Android 93

lJWQi ` 'fz ."_V' f%


Usuno
ricardo

Senha

..i

Bem vindo, login fealizado com sucesso.

Figura 3.9 - Tratamento de eventos.

Desenvolvedores com alguma experincia devem ter percebido que o tratamento de even
tos no Android similar a qualquer outra linguagem. Na verdade, existem muitas formas
de escrever esse mesmo cdigo, basta informar ao mtodo set0nClickListener(listener)
algum objeto que implementa a interface and roid .view . View . 0nClickListener.

O cdigo anterior utilizou o conceito de classes annimas do Java para fazer


essa implementao. Outra maneira de tratar o evento fazer a classe da activity
implementar a interface View.0nClickListener, e utilizar o this (self) para referenciar
a prpria instncia da classe para tratar o evento.

MainActivity.java

public class MainActivity extends Activity inplenents View.0nClickListener {


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nain);
Button btLogin = (Button) ndViewById(R.id.btLogin);
button.set0nClickListener(this); // O this representa a instncia da classe
}

@0verride
public void onClick(View view) { // A prpria classe implementa View.0nClickListener
// Cdigo que trata o evento aqui
}

}
94 Google Android - 4 edio
A desvantagem dessa implementao que, se voc tiver mais de um boto na
tela, o mesmo metodo onClick(view) ser chamado para todos OS botes- NCSSC
caso o parmetro View indica qual componente gerou o evento, e deve ser utilizado
para descobrir em qual boto foi feito o clique, conforme demonstrado a seguir.

ii MainActivity.java

public class MainActivity extends Activity implements 0nClickListener {


@0verride
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_layout);
Button btOk1 = (Button) ndViewById(R.id.botao0k);
Button btOk2 = (Button) ndViewById(R.id.botao0k2);
// Vamos imaginar que existem dois botes na tela
bt0k1.set0nClickListener(this);
bt0k2.set0nClickListener(this);
}

@0verride
public void onClick(View view) {
if(view.getId() == R.id.botao0k) {
// clicou no boto 1
} else if(view.getId() == R.id.botao0k2) {
// clicou no boto 2
}

Vejamos outra forma de escrever o mesmo cdigo, que criar um mtodo para
cada boto. Eu particularmente gosto desse jeito. A vantagem que fica simples
de separar cada clique em um mtodo diferente.

MainActivity.java

public class MainActivity extends Activity {


@0verride
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_layout);
Button btLogin = (Button) ndViewById(R.id.btLogin);
btLogin.set0nClickListener(onClickLogin());
}
Captulo 3 n Conceitos bsicos do Android 95
// O mtodo onClickLogin() retorna uma implementao de View.0nClickListener
private View.0nClickListener onClickLogin() {
return new Button.OnClickListener() {
public void onClick(View v) {
// Tratar o evento de clique aqui.
}

};
}

Dica: acostume-se a utilizar o assistente de cdigo com a tecla de atalho Alt+Enter


para complementar o texto do cdigo. Nesse exemplo eu digitei o mtodo
onClickLogin() e todo o restante foi criado com o assistente.

Ainda existe uma ltima maneira de tratar os eventos. Existem desenvolvedores


que preferem denir o nome do mtodo que deve ser chamado no arquivo XML
de layout.
<Button android:id="@+id/btLogin"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_margin="6dp" android:tet="Login"
android:onClick="onClickBtLogin" />

Nesse caso o atributo android:onClick="onClickBtLogin" informa que o mtodo


onClickBtLogin(view) ser chamado na classe da activity e deve existir, conforme
demonstrado a seguir:
public void onClickBtLogin(View view) {
// Trata o evento de clique aqui
}

Para gerar o cdigo do mtodo na activity novamente o assistente do Android


Studio pode ajud~lo. No arquivo de layout, clique na linha em que o atributo
android:onClick="onClickBtLogin" foi denido e tecle Alt+Enter. Voc ver uma opo
para criar o mtodo na activity
Eu no recomendo fazer desta ltima maneira, pois se o nome do mtodo for
digitado de modo incorreto voc descobrir o erro somente ao executar o projeto.
Em meus projetos, prero definir os mtodos no cdigo, pois qualquer problema
descoberto em tempo de compilao. Em muitos exemplos deste livro, acabei
usando essa tcnica de definir o mtodo no XML, pois ela reduz a quantidade
de cdigo a fim de facilitar a leitura.
* CAPTULO 4
A ) Activity
\-4
'I

A classe Activity representa uma tela da aplicao e responsvel por controlar


os eventos da tela e denir qual View ser responsvel por desenhar a interface
grca do usurio.
Neste captulo, vamos estudar como navegar entre telas da aplicao, como feita a
passagem de parmetros de uma tela para outra e o ciclo de vida da classe Activity.

4.1 Activity
Uma activity uma classe que deve herdar da classe android.app.Activty ou de
alguma subclasse desta, a qual representa uma tela da aplicao e responsvel
por tratar os eventos gerados nessa tela.
A classe da activity deve sobrescrever o mtodo onCreate(bundi.e). Esse mtodo
obrigatrio e responsvel por realizar a inicializao necessria para executar a
aplicao, como por exemplo chamar o mtodo setContentView(view) para denir
a interface de usurio.

Cada activity deve ser obrigatoriamente declarada no arquivo AndroidManiest.xml.


Isso feito por meio da tag , como demonstrado a seguir.
<activtty androd:name=".MinhaC1asseActivity" />

No h muito o que falar da classe androd.app.Actvity. Apenas que utilizada para


construir uma tela da aplicao. Assim, se voc est pensando em criar uma nova
tela, vai precisar de uma nova activity A coisa mais importante que voc precisa
lembrar que, sempre que uma nova classe de activity for criada, ela precisa ser
declarada no arquivo AndroidManifest.xml.

Nessa congurao, a activity geralmente declarada com a sintaxe do ponto, o


que indica que o pacote da classe relativo ao pacote do projeto. Por exemplo, se

96
Captulo 4 n Activity 97
o pacote do projeto br.com.1vroandrod.cap4 e a classe tambm est nesse pacote,
podemos utilizar a sintaxe do ponto.
<activty android:name=".MinhaClasseActvty" />

No entanto, se a classe da activity estiver em outro pacote, como por exemplo br.com.
1vroandrod.cap4.activity, podemos declarar essa activity com a seguinte sintaxe:
<activty androd:name=".activity.MinhaC1asseActvty" />

Se achar necessrio, denir o nome completo da classe tambm no errado:


<actvity androd:name="br.1vro.androd.cap4.activity.MinhaC1asseActvity" />

Nota: no erre o nome da classe da activity na congurao do AndroidManiest.xml


e lembre-se de que o nome precisa ser exatamente igual, pois case-sensitive.
Uma boa dica para ter certeza de que o nome est correto segurar a tecla Ctrl e
passar o mouse em cima do nome. Se 0 texto car selecionado, voc pode clicar
para abrir o cdigo-fonte da classe no editor. Se o editor abrir tudo est correto.

Na prtica podemos associar a palavra activity palavra tela Por exemplo,


vamos analisar as seguintes frases, na qual a primeira est escrita com a palavra
activity e a segunda com a palavra tela'
1. Iniciar uma activity: iniciar uma tela
2. O sistema operacional decidiu encerrar a actvityX para economizar memria:
O sistema operacional decidiu encerrar a tela X para economizar memria?
Seguindo esse raciocnio, se for necessrio criar uma nova tela no projeto, voc
saber que preciso criar uma nova activityA traduo da palavra activity para o
portugus atividade. Ento, tambm podemos dizer que uma activity representa
uma atividade, ao ou funcionalidade que 0 usurio pode realizar dentro de
sua aplicao. Se preferir, sempre que ler a palavra activity em uma frase pode
interpreta-la como atividade* Prero manter a palavra em ingls neste livro para
maior consistncia.

4.2 Classes FragmentActivity e AppCompatActivity


Existem algumas subclasses famosas da classe androd.app.Actvity que bom
voc conhecer desde j. Agora talvez o conceito no fique claro, pois estamos s
comeando, mas futuramente voc pode voltar neste tpico e l-lo novamente.
98 Google Android - 4 edio
listou explicando isso porque o Android Studio pode gerar um cdigo diferente, de
pendendo da verso do Android que voc selecionar no wizard de criao de projetos.
Ento vamos l! No Android 3.0 foram criadas a action bar e a API de fragments.
A action bar representada pela classe androd.app.ActonBar e um fragment pela
classe androd.app.Fragment. Para utilizar essas classes em verses mais antigas do
Android o Google criou a biblioteca de compatibilidade. A biblioteca de compati
bilidade v4 (API Level 4) compatvel com o Android 1.6 ou superior, e dentre as
APIs que ela tem est contida a API de fragments. Mas para usar os fragments de
compatibilidade todas as activities do projeto precisam herdar de androd.support.
v4.app.FragmentActivty, que uma subclasse especial da classe androd.app.Actvty
que permite utilizar os fragments nas verses antigas do Android. Ao utilizar a
biblioteca v4 voc deve utilizar a classe androd.support.v4.app. Fragment para acessar
os fragments e no a classe nativa androd.app.Fragment.
Da mesma forma, existe a biblioteca de compatibilidade v7 (API Level 7), que
compatvel com 0 Android 23 ou superior. A biblioteca v7 contm a action bar
de compatibilidade e permite habilitar a action bar nos dispositivos mais antigos.
Para isso todas as activities do projeto precisam herdar de androd.support.v7.app.
AppCompatActivty. Ao utilizar a biblioteca v7 voc deve utilizar a classe androd . support.
v7.app.ActonBar para acessar a action bar e no a classe nativa android . app.ActonBar.
Ento basicamente temos trs classes de activity que voc precisa conhecer.
androd.app.Actvity - Classe padro da activity
androd.support.v4.app.FragmentActvty - Classe da biblioteca de compatibili
dade v4, que permite utilizar os fragments em verses antigas do Android.
androd.support.v7.app.AppCompatActvty - Classe da biblioteca de compatibi
lidade v7, que permite utilizar a action bar em verses antigas do Android.
A classe AppCompatActi.vty lha de FragmentActvty.

Como exerccio, voc pode criar outro projeto no Android Studio e escolher a
API Level 9 (Android 23) como a mnima do projeto. Ao fazer isso, o Android
Studio vai criar 0 projeto utilizando a biblioteca de compatibilidade v7, e nesse
caso a ManActvity ser lha de AppCompatActvty. Bem, teoricamente era isso que
deveria acontecer, porm a verso do Android Studio que utilizo ao escrever este
livro gerava o cdigo antigo.
public class ManActvty extends androd.support.v7.app.ActlonBarActvty {
O correto seria usar a classe AppCompatActivty:

public class ManActvty extends androld.support.v7.app.AppCompatActlvty {


Captulo 4 I Activity 99
O wizard gera a activity de compatibilidade corretamente, porm ele usa a
ActonBarActvty em vez da AppCompatActvty. O problema que em 21 de abril de
2015 o Google postou no blog que a ActonBarActvty foi descontinuada (deprecated)
a favor da AppCompatActvty. possvel que quando voc estiver lendo este livro o
wizard do Android Studio j esteja gerando o cdigo atualizado, pois isso acon
teceu quando eu estava terminando de revisar o livro.

Nota: no se preocupe com essas questes de compatibilidade agora, estou


apenas introduzindo o assunto para voc ter uma ideia. Por enquanto utilize a
classe androd.app.Acti.vi.ty nativa nos exemplos. Durante seus estudos, ao criar
um novo projeto sempre utilize a maior verso do Android disponvel, pois vou
inform-lo quando precisar criar um projeto com compatibilidade.

As dependncias para essas bibliotecas so declaradas no arquivo buildgradle,


mas vamos deixar para mostrar esses exemplos mais tarde, pois ainda precisamos
estudar o bsico sobre activity
Nos captulos sobre Action Bar (5) e Fragments (8) vamos aprender a utilizar as
bibliotecas de compatibilidade, portanto que tranquilo. Por ora, le~mbre-se de
que no captulo 2 eu pedi para voc criar o projeto no Android Studio sempre
utilizando a ltima verso, assim estamos utilizando a classe padro da activity
que a androd.app.Activty.
Pelo menos agora voc j conhece essas trs classes do tipo activity e quando
encontrar algum cdigo que as utilize ter uma ideia do porqu. Esse tpico foi
apenas para alert-lo disso, mas, como eu j disse, que tranquilo porque vamos
estudar tudo isso depois.

4.3 Ciclo de vida de uma activity


Para ser um bom desenvolvedor Android, muito importante entender o ciclo de
vida de uma activitjg isto , os possveis estados que ela assume. O importante
entender que o sistema operacional cuida desse ciclo de vida, mas ao desenvolver
aplicaes importante levar cada estado possvel em considerao para desen
volver uma aplicao mais robusta.
Por exemplo, digamos que voc criou um maravilhoso jogo no Android e, enquanto
o usurio est jogando, algum faz uma ligao para ele. Nesse caso, o usurio
vai parar o jogo para atender a ligao, no ? E o que acontece com o jogo? O
sistema operacional vai parar o jogo temporariamente (pause) e coloc-lo em
U
100 Google Android - 4 edio
segundo plano enquanto o usurio atende a ligao. Depois que a ligao terminar,
o sistema operacional rciniciar a aplicao do jogo. Agora, a grande pergunta
: ser que seu jogo vai conseguir continuar de onde parou? Ser que o estado e
informaes do jogo sero salvos ou tudo ser perdido? O Android fornece toda
a estrutura necessria para controlar este estado, basta voc entender o ciclo de
vida de uma activity e implementar os mtodos corretamente.
Uma activity tem um ciclo de vida bem denido. Cada activity iniciada inserida
no topo de uma pilha, chamada de activity stack ou, se preferir traduzir, pilha
de atividades? O conceito de pilha j bem conhecido por todos. Assim, sempre
que uma nova activity inserida no topo da pilha, a activity anterior que estava
em execuo ca logo abaixo da nova. A activity que est no topo da pilha a
activity que est em execuo no momento, as demais podem estar executando
em segundo plano, estar no estado pausado ou totalmente paradas.
Sobre essa pilha importante voc entender que no Android at a tela inicial
(Home) uma activity Na verdade, sempre que voc abre um aplicativo, a activity
que representa aquela tela inserida no topo da pilha. Ento digamos que voc
esteja na tela inicial do Android e clicou no cone do Browser. Depois voc clica
no cone do Gmail. Nesse momento temos a seguinte pilha: Home > Browser> Gmail,
sendo que a aplicao da tela inicial sempre a base da pilha. Nesse caso alguma
activity da aplicao do Gmail est executando no topo da pilha, e a activity do
Browser est parada em segundo plano (pause).
Sempre que uma activity est pausada o sistema operacional pode decidir encerrar
o processo, para, por exemplo, liberar recursos e memria para outras aplicaes.
Por exemplo, digamos que o usurio estava jogando e de repente decidiu navegar
na internet e, para isso, ele parou o jogo. Isso faz com que o Android insira no
topo da pilha a aplicao do browser, e deixe em segundo plano 0 jogo que est
temporariamente parado. Agora, digamos que o usurio esquea-se de voltar ao
jogo para continu-lo, e, por algum motivo, o sistema operacional precisa liberar
recursos e memria. Sendo assim, como o jogo no est mais em uso, o sistema
operacional pode decidir encerrar seu processo. Nesse momento sua aplicao
pode decidir salvar algumas informaes ou no.

Nota: cada aplicao nativa do Android, como o browser, a tela inicial (Home),
a agenda e a prpria tela para discar para um nmero de telefone denida
por uma Activity. Portanto, esse conceito de pilha de atividades utilizado para
todas as aplicaes, sejam as desenvolvidas por voc ou uma aplicao nativa,
pois tudo funciona sobre a mesma arquitetura.
Captulo 4 I Activity 101
Agora partiremos para a prtica. Existem mtodos da classe Activity que podem ser utili
zados para controlar o estado da aplicao. Dentre eles j vimos o mtodo onCreate(bund1e)
que responsvel por inicializar a activity e dar incio ao seu ciclo de vida. Agora vamos
estudar outros mtodos importantes: onCreate(bund1e), onStart(), onRestart(), onResume(),
onPause(), onStop() e onDestroy().A gura 4.1 demonstra o ciclo de vida completo de uma
activity exibindo os possveis estados e a chamada de cada mtodo.
Fonte:

http://developer android.com/training/basics/activitylifecycle/starting.html

Resumzed H _
=.._\\ j (vision) |
onFiesume() onPause()
onResume0 \
____,,,; ':' O inli O Started O .z/O Paused
onStart()
<..\_ (vtibiei _`l (prauy
ontartii onStop() L
visible) 1

Created ~nHesta.rt()---if jp .gwppedunp A gli----


0nCfT3te(l xy- JM \. ,.~. ' /3 Ongetfyll
nmwyea

Figura"4.1 - Ciclo de vida de uma activity.

Depois de ver o diagrarrfa da figura 4.1, leia atentamente o signicado de cada

Mtodo Descrio
mtodo do ciclo de vida da activity

onCreate(bund1e) O mtodo onCreate(bund1e) obrigatrio e chamado uma nica vez.


O objetivo desse mtodo fazer a inicializao necessria para exe
cutar a aplicao. Nele deve-se criar uma view e chamar o mtodo
setContentVew(view) para configurar o layout da tela.
onStart() O mtodo onStart() chamado quando a activity est cando visvel
ao usurio e j tem uma view Pode ser chamado depois dos mtodos
onCreate() ou onRestart(), dependendo do estado da aplicao.
onRestart() O mtodo onRestart() chamado quando uma activity foi parada
temporariamente e est sendo iniciada outra vez.
onResume() O mtodo onResume() chamado quando a activity est no topo da
pilha activity stacl' e dessa forma j est executando como a activity
principal e interagindo com o usurio. Podemos dizer que o mtodo
onResume() representa o estado de que a activity est executando.
importante voc entender que quando o mtodo onResume() executar
102 Google Android - 4 edio
Mtodo Descrio (cont.) _, g
o usurio j est vendo a tela. Por isso esse mtodo frequentemente
utilizado para disparar threads que consultam os dados em web
services ou banco de dados para atualizar as informaoes da tela.
onPause() Sempre que a tela da activity fechar, o mtodo onPause() ser chama
do. Isso pode acontecer se o usurio pressionar o boto Home ou
o boto voltar para sair da aplicao. Ou tambm pode aC0ntCr
se voc receber uma ligao telefnica. Nesse momento o mtodo
onPause() chamado para salvar o estado da aplicao, para que
posteriormente, quando a activity voltar a executar, tudo possa ser
recuperado, se necessrio, no mtodo onResume().
onStoD() O mtodo onStop(~) chamado logo depois do mtodo onPause() e
indica que a activity est sendo encerrada, e no est mais visvel ao
usurio. Depois de parada, a activity pode ser reiniciada se necessrio.
Caso isso ocorra, o mtodo onRestart() chamado para reiniciar a
activity Caso a activity que muito tempo parada em segundo plano
e o sistema operacional do Android precise limpar os recursos para
liberar memria, o mtodo onDestroy() pode ser automaticamente
chamado para remover completamente a activity da pilha.
onDestroy() O mtodo onDestroy() literalmente encerra a execuo de uma
activity O mtodo onDestroy() pode ser chamado automaticamente
pelo sistema operacional para liberar recursos ou pode ser chamado
pela aplicao pelo mtodo nish() da classe Activity. Depois de o
mtodo onDestroy() ter executado, a activity removida completa
mente da pilha e seu processo no sistema operacional tambm
completamente encerrado.
Para demonstrar as chamadas dos mtodos do ciclo de vida da activity vamos criar
a classe DebugActivity, que sobrescreve cada mtodo e insere um log do LogCat.
Para este prximo exemplo vamos criar o projeto HelloActivity, mas se preferir
abra o projeto pronto dos exemplos do livro. O cdigo-fonte da classe DebugActivity
pode ser visualizado a seguir:

DebugActivity.java

// Activity que imprime logs nos mtodos de ciclo de vida


public class DebugActivity extends Activity {
protected static nal String TAG = "livro";
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
Log.i(TAG, getClassName() + ".onCreate() chamado: " + icicle);
}
Captulo 4 I Activity 103
protected void onStart() {
super.onStart();
Log.i(TAG, getC1assNane() + ".onStart() chamado.");
}

protected void onRestart() {


super.onRestart();
Log.i(TAG, getC1assNane() + ".onRestart() chanado.");
}

protected void onResune() {


super.onResune();
Log.i(TAG, getC1assName() + ".onResume() chanado.");
}

protected void onPause() {


super.onPause();
Log.i(TAG, getClassName() + ".onPause() chamado.");
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.i(TAG, getC1assNane() + ".onSaveInstanceState() chanado.");
}

protected void onStop() {


super.onStop();
Log.i(TAG, getC1assName() + ".onStop() chanado.");
}

protected void onDestroy() {


super.onDestroy();
Log.i(TAG, getCiassNane() + ".onDestroy() chanado.");
}

private String getC1assName() {


// Retorna o none da classe sen o pacote
String s = getC1ass().getNane();
return s.substring(s.lastIndex0f("."));
}

Nota: sempre que sobrescrever um mtodo da classe Activity, chame o mtodo


da classe me com o super, caso contrrio uma exceo ser lanada.

Essa classe imprime um log quando cada mtodo do ciclo de vida for chamado.
O log criado com a tag livro, portanto necessrio criar um ltro para essa tag
na janela do LogCat, conforme explicado no captulo 3. O prximo passo alterar
104 Google Android - 4 edio
a classe MainActvty para ser lha de DebugActivty, assim ela vai herdar todos os
mtodos que foram customizados na sua classe me.

i MainActivity.java

public class MainActivity extends DebugActivity {


// Mesmo cdigo aqui
}

Ao executar o projeto no emulador, no estamos interessados no layout da activity


ento desta vez vamos analisar somente os logs que mostram as chamadas para
cada mtodo do ciclo de vida. Na primeira vez que a aplicao executar, os se
guintes logs so gerados. Observe que os mtodos onCreate( ), onStart() e onResume()
so chamados na sequncia.
INFO/ID(8494): ManActvty.onCreate() chamado.
INFO/ID(8494): ManActivity.onStart() chamado.
INFO/ID(8494): ManActvity.onResume() chamado.

Agora clique no boto voltar (back) do emulador para sair da activity Isso pode
ser feito tambm pressionando a tecla Est. Observe que agora os mtodos onPause(),
onStop() e onDestroy() foram chamados para encerrar o ciclo de vida da activity
INFO/ID(8494): MainActivity.onPause() chamado.
INFO/ID(8494): MainActivity.onStop() chamado.
INFO/ID(8494): HanActivity.onDestroy() chamado.

Nesse caso, como o boto voltar foi pressionado, o sistema operacional sabe que
a activity precisa ser destruda. Por isso, o mtodo onDestroy() foi chamado, elimi
nando completamente a activity da memria.
Agora volte na tela inicial do emulador e entre novamente na aplicao. Isso vai
chamar os mtodos onCreate(), onStart() e onResume(). Ento, clique no boto Home
para voltar tela inicial. Observe que nos logs os mtodos onPause() e onStop()
foram chamados, mas no o mtodo onDestroy().
INFO/ID(8670): ManActvity.onPause() chamado.
INFO/ID(8670): ManActivty.onStop() chamado.

lsso acontece porque a activity no foi completamente destruda, apenas retirada


do topo da pilha, e agora est parada em segundo plano.
Por ltimo, volte tela inicial Home e clique n cone da aplicao novamente. lsso
vai reiniciar a activity fazendo com que ela volte ao topo da pilha para ser executada
em primeiro plano. Assim, s mtdos onRestart(), onStart() e onResume() so chamados.
Captulo 4 I Activity 105
INFO/ID(10550): ManActvty.onRestart() chamado.
INFO/ID(10550): MainActvity.onStart() chamado.
INFO/ID(10550): MainActvty.onResume() chamado.

Observe que o mtodo onCreate(bundle) chamado uma nica vez. Se a activity


estiver parada em segundo plano, o mtodo onCreate(bundle) no chamado nova
mente. j o mtodo onResume() chamado sempre que a tela car visvel ao usurio.
Perceba que os mtodos onPause() e onStop() so sempre chamados ao sair da tela.
O mtodo onResume() chamado sempre que iniciar ou voltar para a aplicao.
O mtodo onCreate() chamado apenas na primeira vez que a aplicao criada.
Caso a activity seja totalmente destruda, evento que acontece ao clicar no boto
voltar, o mtodo onDestroy() chamado para eliminar os recursos e encerrar o ciclo
de vida da activity Outra forma de destruir a activity chamar o mtodo nsh()
programaticamente no cdigo.
Entender o funcionamento do ciclo de vida de uma activity muito importante
para desenvolver aplicaes no Android. Temos de estar preparados para aes
externas que podem ocorrer, tal como uma ligao telefnica para o usurio. Essa
ao faz com que o sistema operacional do Android interrompa (pause/stop) a
activity atual, colocando-a em segundo plano. Isso feito porque a aplicao na
tiva da ligao quem vai ocupar o topo da pilha de atividades. Numa situao
como essa, quando a ligao terminar, temos de voltar e executar a aplicao de
onde ela parou sem perder nenhuma informao.

Nota: entender o ciclo de vida de uma activity fundamental para dominar o


desenvolvimento para Android. isso que diferencia um bom desenvolvedor
de um desenvolvedor comum.

4.4 Ciclo de vida avanado - oque acontece ao rotacionar o celular?


Ao girar a tela do celular da vertical para a horizontal importante voc saber que
o Android vai destruir a activity atual e vai recri-la logo em seguida. O Android
faz isso porque ele precisa recriar todas as views e aplicar espaamentos e margens
adequadas para a nova orientao.
Durante esse processo de troca de orientao, o Android vai chamar o mtodo
onSaveInstanceState(bundle) na classe da activity Esse mtodo recebe um objeto do
tipo androd.os.Bund1e como argumento que deve ser utilizado para armazenar os
106 Google Android - 4' edio
dados cnt uma estrutura de chave e valor. Para demonstraresse comportainent.
vatnos executar a aplicacao novamente. Ao fazer isso, a MainActlvi.ty e criada t:
inserida tio ltipti da pillta, conforme inostratn estes logs:
MainAct'tvity.onCreate() chamado: null
MalnActlvlty.onStart() chamado.
MatnActtvlty.onResume() chamado.

Agora pressione a tecla de atalho (trI+F11 do emulador para girar a tela para a
l1()l'l2t)Ill`ill.()S logs a segttir mostrain que a activity foi destruda e recriada, mas
durante esse processo o metodo onSaveInstanceState(bundle) foi chamado.
Ma'tnActlvtty.onPause() chamado.
MatnActtvtty.onSaveInstanceState() chamado. // Salve o estado aqui
HalnActtvlty.onSt0D() chamado.
MatnActivity.onDestroy() chamado. // Actlvty foi destruda
MalnActivlty.onCreate() chamado: Bundle[{...}]}] // Actlvlty foi recrlada. Recupere o
// estado aqui
MainActivlty.onStart() chamado.
MatnActivtty.onResume() chamado. // Acttvtty est visivel para o usurio
Se voc salvou valores no Bundle l no mtodo onSaveInstanceState(bundle) possvel
recuperar este estado no Bundle que voc recebe como parmetro no mtodo
onCreate(bundle). para isso que serve esse Bundle no mtodo onCreate(bundle). Se
for a primeira vez que a activity executada, esse Bundle sempre estar nulo.
Entretanto, no caso da rotao da tela em que o Android faz esse processo para
recriar a activity, o Bundle pode estar preenchido cont os dados salvos no mtodo
onSaveInstanceState(bundle)_

Nota: o comportamento padro do /\ndroid ao girar a tela destruir a activity


atual e recriar outra. sua responsabilidacle manter o estado da aplicacao salvando
os dados no Bundle durante a execuo do mtodo onSaveInstanceState(bundle).
para depois recuperar o estado no mtodo onCreate(bundle).

Essa teoria inicial para voc j ficar esperto, mas no captulo 8. sobre fragments.
vamos revisar esse conceito com exerccios praticos.

4.5 Navegao entre telas e inicializao de uma nova activity


(ieralniente utn aplicativo e composto de varias telas. entao precisainos aprender
como fazer a I1`lV(.}.!,Iflt) entre as telas.
Captulo 4 u Activity 107
Existem dois mtodos que podem ser utilizados para iniciar outra activity/ tela:
startActvity(ntent) e startActvtyForResu1t(intent,codgo). A diferena entre eles
que o mtodo startActvty(ntent) apenas inicia a prxima activity sem qualquer
vnculo. O mtodo startActvtyForResult(ntent,codigo) recebe um parmetro que
identica essa chamada, para que posteriormente essa segunda activity possa re
tornar alguma informao para a activity que a chamou. Esse mtodo utilizado
caso a activity inicial que fez a chamada esteja interessada em obter o retorno
quando a segunda activity terminar.
Esse retorno de uma activity para outra pode ser utilizado, por exemplo, em uma
aplicao que exibe uma tela para escolher um contato do celular e, logo depois
de escolher o contato, a informao retornada para a activity inicial, para, por
exemplo, enviar uma mensagem ou email para o contato selecionado.
Os mtodos startActvty(ntent) e startActvtyForResult(codigo,resu1tado,ntent) re
cebem um objeto do tipo androd.content.Intent como parmetro. A classe androd.
content.Intent o corao do Android, tudo gira em torno dela, e uma explicao
detalhada ser fornecida no captulo 20.
Ento mos obra! Crie uma nova classe camada BemVi.ndoActvty, que tambm
deve herdar de DebugActvty, assim podemos monitorar as chamadas dos mtodos
do ciclo de vida. Para criar uma activity preciso fazer trs coisas:
1. Criar a classe Java que estende de alguma subclasse de android.app.Actvty.
2. Criar o arquivo XML de layout.
3. Registrar a activity no arquivo AndroidManifest.xml.
Para facilitar esse trabalho, recomendo voc clicar com o boto direito no pacote
das classes do projeto e selecionar o wizard New > Activity> Blank Activity (Figura 42).
Esse wizard vai auxili-lo a executar estes trs passos.

.~ Cuz
ff; _ . XCtri+
l Rle .C Java Class

gem, mc fil Package


Cpv warn crz1s1+ c *W ""9 ^
' Copy Reference Ctrl* \l+ Shifh C ' Alm- V um
z Bam ,,,.,\, zig. Anmrvdwcy
i Find Qsages lt+F? iai Fade' Shu* Activity _
Find in Bath... Ctrh Shi?t+F ii' F'a9'* " Blank fvty with Fragment

Figura 4.2 - Wizard para criar uma activity.

Depois de criar a activity com o Wizard, digite o seguinte cdigo-fonte:


108 Google Android - 4 edio
n BemVindoActivity.java

import android app.Activity;


import android.os.Bundle;
public class BemVindoActivity extends DebugActivity {
@0verride
protected void onCreate(Bundle savedlnstancetate) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bem_vindo); // Layout desta activity
// Recebe o nome enviado por parmetro
Bundle args = getIntent().getExtras();
String nome = args.getString("nome");
// Vamos atualizar o texto do Textview com uma mensagem de bem-vindo
Textview text = (Textview) ndViewById(R.id.text);
text.setText(nome + ", seja bem-vindo.");
}

No layout da activity vamos adicionar um simples Textview com o id


android:id="@+id/text", para atualizar o texto dinamicamente dentro do cdigo.

/res/layout/actvity_bem_vindo.xmI
<?xml version="1.G" encoding="utf-8"?>
<LinearLayout mlns:android="http://schemas.android.com/apk/res/android"
mlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:padding="10dp" >
TextView android:id="@+id/text"
android:layout_width="wrap_content" android:layout_height="wrap_content" />

classe.xml. _
Nota: o arquivo de layout XML segue a nomenclatura /res/layout/activity_nome_

Lembre-se de que todas as activities precisam ser declaradas no arquivo


AndroidManiest.xml. A vantagem de utilizar o wizard do Android Studio que
ele j fez essa congurao.
Captulo 4 I Activity 109
AndroidManifest.xmI

<application ...>
<activity android:nane=".MainActivity" .. >
. . . // intent-lter da MAIN aqui.

activity android:nane=".BemVindoActivity" android:label="Ben-vindo" /

Nota: todas as activities precisam ser declaradas no arquivo AndroidManifest.xml.


Geralmente somente uma activity ter as conguraes de <intent-lter> MAIN e
LAUNCHER, pois a activity que ca na tela inicial e chamada pelo usurio.

O prximo passo alterar o cdigo da classe MainActivity para navegar para a activity
BenVindoActivity. Na classe MainActivity zemos o exemplo do layout de login e vamos
continuar de onde paramos. Caso o login seja feito com sucesso, vamos navegar para
a prxima tela, a qual vai mostrar uma mensagem de bem-vindo ao usurio. Nesse
exemplo vou passar um parmetro nome=Ricardo xo para a prxima tela.

MainActvty.java

public class MainActivity extends DebugActivity {


@0verride
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nain);
Button btLogin = (Button) ndViewById(R.id.btLogin);
btLogin.set0nClickListener(onClickLogin());
}

private View.OnClickListener onClickLogin() {


return new View.OnClickListener() {
@0verride
public void onClick(View v) {
Textview tLogin = (Textview) ndViewById(R.id.tLogin);
Textview tSenha = (Textview) ndViewById(R.id.tSenha);
String login = tLogin.getText().toString();
String senha = tSenha.getTet().toString();
if("ricardo".equals(login) && "123".equals(senha)) {
// Navega para a prxima tela
Intent intent = new Intent( getContext(), BemVindoActivity.class);
no Google Android - 4' edio
Bundle parans = new Bund1e();
parans.putString("none", "Ricardo Lecheta");
intent.putExtras(parans);
startActivity(intent);
} else {
alert("Login e senha incorretos.");
}

};
}

private Context getContext() {


return this;
}
private void a1ert(String s) {
Toast.makeTet(this,s,Toast.LENGTH_SHORT).show();
}

Para navegar para a prxima tela, criado um objeto do tipo android.content.Intent


informando a classe da activity que deve ser chamada. Ao criar a intent, preciso
passar a referncia do contexto, que a classe android.content.Context, que por sua
vez me de android.content.Activity.

Por isso, geralmente comum ver no cdigo-fonte o contexto sendo referenciado com
o this da classe, pois o this no Java representa a instncia do objeto atual. No caso de
o cdigo estar dentro de uma classe Activity do Android, o this representa essa activity
Intent it = new Intent(this, BemVindoActivity.c1ass);
startActivity(it);
Eu muitas vezes gosto de declarar a varivel context conforme demonstrado a
seguir. Neste exemplo simples no tem muita utilidade, mas em exemplos mais
complexos vale a pena.
nal Context context = this;
Intent it = new Intent(contet, BemVindoActivity.c1ass);
startActivity(it); '
Veja que no cdigo do mtodo onC1ick(view) da MainActivity no foi utilizado o
this para passar o contexto. Isso porque o mtodo onC1ick(view) criou uma classe
interna (inner class do java), e nesse caso o this faz referncia classe interna c
no classe MainActivity. Por isso criei o mtodo96tC0f@'C() para retornar o this
e facilitar o cdigo.
111
Captulo 4 n Activity

Ao executar a aplicao e fazer o login, feita a navegao para a tela de bem


-vindo, conforme a figura 43. Como voc j deve saber, para voltar tela anterior
basta utilizar o boto de voltar.

1g Login
` V CapD4-Activity
i . v ' I..i ::/ '

li
i L'._..:r~'..= Ricardo Le|;li;=u, aaja bcrri vinda
i ricardo
ii
1 :`~._1.':i

7 ..-_ ___ _ ____-___, ____] I

Figura 4.3 - Navegao de telas com a activity.

Agora vamos voltar a falar do ciclo de vida da activity Ao abrir a segunda activity
ela inserida no topo da pilha de atividades e a tela do login est parada em
segundo plano. Para conrmar a teoria, vamos verificar os logs na janela LogCat.
Ao abrir a primeira activity podemos vericar nos logs que os mtodos onCreate(),
onStart() e onResume() foram chamados normalmente como esperado.
INFO/ID(11033): MainActivity.onCreate() chamado.
INFO/ID(11033): MainActivity.onStart() chamado.
INFO/ID(11033): MainActivity.onResume() chamado.

At agora no h novidades. Mas ao fazer o login os seguintes logs aparecem no LogCat:


INFO/ID(11033): MainActivity.onPause() chamado. // Primeira activity interrompida (pause)
INFO/ID(11033) BemVindoActivity.onCreate() chamado // Segunda activity iniciada
INFO/ID(11033). BemVindoActivity.onStart() chamado.
INFO/ID(11033): BemVindoActivity.onResume() chamado. // Segunda activity colocada no
// topo da pilha
INFO/ID(11933): MainActivity.onStop() chamado. // Primeira activity parada (stop)

Podemos vericar que a activity MainActivity teve seus mtodos onPause() e onStop()
chamados para deixar a primeira tela em segundo plano. j a activity BemVindoActivity
teve os seus mtodos de inicializao chamados e agora ocupa o topo da pilha.
112 Google Android - 4 edio
Entretanto, o que acontece se 0 boto voltar for pressionado? O sistema operacional
identificar que a activity BemVindoActivity deve ser destruda, porque teoricamente
ela no mais necessria. Isso far com que a activity MainActivity seja relniciada,
voltando ao topo da pilha. Esse fluxo pode ser vericado pelos seguintes logs:
INFO/ID(11033]: BemVindoActivity.onPause() chamado. // A segunda activity Dfd
INFO/ID(11G33] HainActivity.onRestart() chamado. // Reinicia a primeira activity
INFO/ID(11G33 HainActivity.onStart() chamado.
INFO/ID(11033 HainActivity.onResume() chamado. // Volta ao topo da pilha
INFO/ID(11033 BemVindoActivity onStop() chamado.
INFO/ID(11033] BemVindoActivity.onDestroy() chamado.// Destri a segunda activity

Observe que os logs demonstram que a activity BemVindoActivity foi destruda, uma
vez que a chamada ao mtodo onDestroy() foi realizada. j a activity MainActivity foi
reiniciada, chamando os mtodos onRestart(), onStart() e onResume(). importante
que voc exercite o conceito de ciclo de vida de uma activity brincando bastante
com os logs do emulador.
Lembre-se de que os eventos extemos, como o usurio atender uma ligao telefnica,
tambm podem parar a activity e deix-la executando em segundo plano. Os mtodos
do cielo de vida devem estar preparados caso isso aconteaj que o exemplo da ligao
foi lembrado, vamos aproveitar e finalizar o assunto com chave de ouro e simular uma
chamada telefnica, para que a activity que est executando seja inserida em segundo
plano enquanto o usurio atende a ligao. Caber a voc executar a activity analisar
os logs e estudar o que ocorre quando o usurio atende uma chamada.
Para simular a chamada telefnica, abra a ferramenta Android Device Monitor no menu
Tools >Android >Android Device Monitor e procure pela janela Emulator Control. Nessa janela digite

3 .es Qi Z ._
um nmero de telefone no campo incoming Number e clique no boto (all (Figura 4.4).

L "`. Y.

Figura 4.4 - Simulando uma ligao,


Captulo 4 I Activity 113
A figura 4.5 mostra o emulador simulando uma ligao telefnica. A foto do Mickey
apareceu nessa gura porque no captulo 32, sobre a agenda de contatos (Content
Provider), eu cadastrei os contatos Mickey Donald e Pateta no meu emulador.

,ap Mickey 4.52 PM


-Q incoming call

>< DISMlSS K, xmswa

Figura 4.5 - Emulador recebendo uma ligao simulada.

Lembre-se: se alguma activity estiver em execuo enquanto a ligao for feita, ela
ser removida do topo da pilha e car parada em segundo plano. Agora quem
ocupa o topo da pilha a prpria aplicao nativa da ligao. Como assim, a pr
pria aplicao da ligao? Isso mesmo, a tela que exibe a ligao, assim como a tela
inicial, o browser, os mapas, a agenda de contatos etc., todas elas so uma activity
s que nativas e j disponveis no Android. Aos poucos voc vai entendendo que
no Android tudo funciona da mesma forma, seja uma aplicao desenvolvida por
voc, seja uma nativa do Android.
Voltando ligao, quando ela terminar e o usurio fechar a tela, a activity que
estava parada em segundo plano ser reiniciada e voltar ao topo da pilha, estando
pronta para interagir com o usurio novamente. Esse comportamento incrvel, j
que o sistema operacional encarrega-se de tudo. Ele coloca a activity em segundo
plano e depois a reinicia quando necessrio, e, claro, todos os mtodos de ciclo
de vida so chamados para o seu controle.
Depois de toda essa teoria no se esquea de brincar um pouco com o emulador:
e muito importante entender o funcionamento do ciclo de vida da classe Activity
114 Google Android - 4' edio
Nota: se existirem muitos processos parados em segundo plano e se as condies
de memria estiverem baixas, o sistema operacional pode decidir encerrar o
processo de uma activity, chamando o mtodo onDestroy(). O fato que 0 sistema
operacional encarrega-se do ciclo de vida da activity. Cabe ao desenv0lvCClOT
apenas implementar os mtodos desse ciclo corretamente.

4.6 Mais detalhes sobre a classe Bundlee como passar parmetros


No exemplo anterior, aprendemos a utilizar 0 mtodo startActvity(ntent) para
navegar entre as telas e vimos que a classe androd.os.Bundle utilizada para passar
parmetros usando a estrutura de chave e valor.
Para revisar o cdigo que fizemos, veja como foi criado um Bundle e nele foi pas
sado o parmetro none=Rcardo. Depois chamado o mtodo ntent.putExtras(bundle)
para passar esses parmetros para a intent:

public class MalnActivity extends DebugActvty {

f("ricardo".equals(login) && "123".equals(senha)) {


Intent intent = new Intent(getContet(),BenVndoActvty.class);
Bundle parans = new Bundle();
parans.putStrng("none", "Ricardo Lecheta");
ntent.putEtras(params);
startActvty(ntent);
}

Nesse exemplo uma string foi adicionada como parmetro, mas a classe Bundle tem
mtodos para diferentes tipos primitivos, como por exemplo: putBoolean, putChar,
putByteArray, putShort, putInt, putlong, putFl_oat, putDouble e vrios outros.

Se quiser voc pode escrever esse cdigo de maneira mais simplificada, pois a classe
Intent tem alguns atalhos para passar parmetros. Nesse caso podemos substituir
o trecho de cdigo anterior por apenas trs linhas. Internamente a classe Intent
vai continuar utilizando 0 Bundle, mas isso ca encapsulado.
public class HanActvity extends DebugActvty {

if("rtcardo".equals(login) && "123".equals(senha)) {


Intent intent = new Intent(getContet(),BenVindoActlvty.class);
Captulo 4 I Activity 115
intent.putEtra("nome", "Ricardo Lecheta");
startActivity(intent);
}

Para ler o parmetro na segunda activity; tambm podemos utilizar um atalho, e


ler diretamente da classe Intent, conforme demonstrado a seguir:
Intent intent = getIntent();
String nome = intent.getStringEtra("nome"); // L o parmetro do Bundle

Ou voc pode recuperar o objeto Bundle completo para ler os parmetros.


Intent intent = getIntent();
Bundle args = intent.getExtras();
String nome = args.getString("nome");

Existem vrios mtodos para cada tipo primitivo, como getIntEtra(chave),


getLongExtra(chave), getBooleanExtra(chave) etc. Agora que voc j conhece a classe
Bundle e os mtodos da classe Intent que encapsulam o acesso, ca a seu critrio
utilizar a forma de enviar e recuperar os parmetros que mais lhe agradar.

4.7 O bsico sobre action bar e como voltar para tela anterior
No ltimo exemplo, mostramos como navegar entre duas activities da aplicao.
Sempre que uma activity chamada, surge a necessidade de voltar tela anterior,
e para isso voc pode utilizar o boto de voltar do Android, ou colocar o indicador
de voltar na action bar.
Para adicionar o indicador de voltar na action bar, basta utilizar o mtodo
getActionBar().setDisplayHomeAsUpEnabled(true), e quando o usurio clicar no boto ele
vai disparar a ao de menu com o identicador android.R.id . home. Para testar a brin
cadeira, altere o cdigo da classe BemVindoActivity conforme demonstrado a seguir:

BemVindoActivity.java

public class BemVindoActivity extends DebugActivity {


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bem_vindo);
Bundle args = getIntent().getExtras();
String nome = args.getString("nome);
116 Google Android - 4 edio
Textview text = (Textview) ndViewById(R.id.tet);
tet.setTet(none + ", seja ben-vindo.");
// Adiciona o boto "up navigation"
getActtonBar().setbisp1ayHoneAsUpEnab1ed(true);
}

@0verride
public boolean on0ptionsItenSe1ected(MenuItem item) {
int id = iten.getItemId();
if(d == android.R.id.hone) {
// 0 mtodo nsh() vai encerrar essa activity
nsh();
return true;
}

return super.onOptionsItemSe1ected(tem);
}

Nota: o mtodo getActionBar() retorna o objeto android.app.ActonBar que est


disponvel para o Android 3.0 (API Level 11) ou superior. Se estivssemos
utilizando a biblioteca de compatibilidade, seria utilizado o mtodo
getSupportActionBar(). Posteriormente vamos aprender a manter a compatibilidade
com verses antigas do Android, mas por enquanto no se preocupe com isso.

Desta vez, ao executar o projeto voc ver que na action bar da segunda activity
apareceu a seta que aponta para esquerda (Figura 4.6), indicando que o usurio
pode voltar para a tela anterior. O indicador de voltar na action bar chamado
de up navigation e vai adicionar uma pequena seta para esquerda indicando
que o usurio pode clicar nela para subir na hierarquia de telas.
O evento gerado pelo up navigation como se o usurio tivesse clicado em qual
quer outro boto da action bar. Nesse caso, porm, o identificador do evento a
constante androd.R.d.hone da classe androd.R nativa do Android. Observe que no
cdigo, como temos de voltar manualmente para a primeira activity chamado o
mtodo nsh(), que faz com que a activity atual seja encerrada. Assim, o Android
vai remover a activity da pilha e chamar todos os mtodos do ciclo de vida como
onPause(), onStop(), at o onDestroy().

Antes de continuarmos o assunto, deixe-me explicar algo importante sobre o up


navigation. Segundo as boas prticas de design do Android, existe uma diferena
entre o boto voltar do Android e o up navigation. O boto voltar sempre volta
para a tela anterior e pronto. Mas o up navigation conceitualmente faz a aplicao
subir na hierarquia de telas. Por exemplo, se o celular est parado na tela Home do
Captulo 4 I Activity 117
Android e sua aplicao for chamada por meio de uma noticao (como se che
gasse um email), voc pode decidir como o up navigation deve funcionar. O boto
voltar simplesmente vai voltar para a tela anterior (que nesse exemplo a home),
mas o up navigation pode voltar para uma tela diferente (tela com a lista de emails).
Muitas vezes voc tambm pode ter vrias telas empilhadas: A > B > C > D > E. Na
tela E, se voc pressionar o boto voltar, as telas sero desempilhadas uma a uma
at a tela A. Mas utilizando o up navigation podemos mudar esse comportamento
e fazer a aplicao voltar direto para a tela A. Isso ca a critrio da sua aplicao;
o importante voc entender que o up navigation nem sempre funcionar igual
ao simples boto voltar do Android.

*~-ii r;?; . ,zz . . ,` /~.,/ zk_.VV_,,/

Usuario Ricardo Lechet, seja bem vindo.


ricardo

Senha
` lllliiit

,__..___ _ ___-,_mJ

Figura 4.6 - Boto de up navigation na action ban

Nota: acostume-se com o termo up navigation, o qual se refere seta de voltar que
colocada na parte superior esquerda da action bar. Outro detalhe importante:
para encerrar uma activity por programao utilize o mtodo finsh(). Ao fazer isso,
o mtodo onDestroy() da activity ser chamado para encerrar o seu ciclo de vida.

4.8 Links teis


Para complementar sua leitura, segue o link da documentao oficial:
Android API Guides - Activities

http://developer android.com/guide/components/activities. html


xi CAPITULO S
Action Bar e temas
O

liste capitulo e sobre o padro de design mais importante do Android, que e a


action bar, ou seja, a barra de navegao que fica na parte superior da aplicao,
a qual contem os botes corn aes, tabs e menus para interagir com o usuario.
Aprender a utilizar a action bar e seguir as recomendaes de design d Android
e um diferencial importante para ter um aplicativo de sucesso.

5.1 Introduo Action Bar


A action bar mostra de forma consistente para o usuario as possveis aes que
ele pode fazer no aplicativo. A grande vantagem de utilizar a action bar que os

'i "A
usurios de Android j esto acostumados com ela, pois todos os aplicativos
nativos so feitos assim.
Para entender a action bar, vamos estudar a figura 5.1.

ai. i ii narB I ,,:


tar Acto
Figura 5.1 - Action ban

1. App Icon

Por padro o cone da action bar mostra o cone do projeto e pode ser
customizado con forme sua necessidade. Nesse espao tambm mostrado
o up navigation que a seta para esquerda que indica que o usuario
pode navegar para cima na hierarquia de telas.

118
Captulo 5 I Action Bar e temas 119
Esse cone atualmente me deixou um pouco intrigado, e me fez pensar
um pouco antes de escrever as prximas frases. Desde que a action bar
foi criada, a documentao ocial refora o conceito de que esse cone
representa algo importante, como o logo da aplicao. Porm, com o sur
gimento do Material Design, a action bar nos dispositivos com Android 5.0
ou superior no mostra o cone, diferentemente de como era no Android
3.x e 4.x. No Material Design dado um foco maior na cor principal da
aplicao (primary color) versus a cor de acentuao (accent color) para
dar destaque s views e a alguns componentes. No Material Design uma
boa prtica customizar as cores da action bar para se identificar com a
marca do cliente ou aplicativo. Tambm recomendado utilizar a cor de
acentuao para destacar as principais aes quando necessrio.
Por isso, dependendo da verso do Android, voc ver aplicativos que
mostram o cone na action bar ou no.

2. View control

Nesse espao podemos mostrar o ttulo do aplicativo ou da tela em que o


usurio est, ou utilizar algum controle de navegao como o drop-down
e as tabs.

3. Action buttons

Espao dedicado para os botes que representam as aes mais comuns


do seu aplicativo. Caso a quantidade de cones no se encaixe no espao
reservado, automaticamente eles so inseridos no menu do action overow

4. Action overow

Menu flutuante que mostra as aes que no so to frequentes no aplicativo.

5.2 Temas Holo e Material

O segredo para utilizar a action bar est no tema que o aplicativo utiliza, o qual
configurado no arquivo AndroidManiest.xml.
A interface do Android funciona com base nos temas. Desde sua criao os dois
temas clssicos eram o Theme.B1ack e Theme.Lght. O tema Theme.B1ack utiliza o fundo
preto e fonte branca e o tema Theme.Lght o contrrio, utiliza o fundo branco e
a fonte preta.
120 Google Android - 4' edio
lisscs eram os temas ate o Android 2.x, mas a partir do Android 3.0 (Honeycmb)
foi criado o tema Holographic, popularmente conhecido apenas como Holo. O tema
Holo tambm tem suas variaes com fundo preto ou branco, que so os temas
Theme.Holo e Theme.Holo. Light.

j no Android 5 (Lollipop) foi criado o tema Material, que aplica as regras do


l\~1latcrial Design. Segundo o Google esta foi a maior mudana da histria referente
a design na plataforma do Android. O tema Material tambm tem suas variaoes
com fundo preto ou branco, que so os temas Theme.Material e Theme.Material.Light.
Entender o que um tema muito importante para voc ser um bom desenvol
vedor Android, por isso, tentarei explicar desde o bsico, inclusive voltando um
pouco na histria desde as primeiras verses do Android.
A maneira mais fcil de voc entender o que um tema abrir um arquivo de
layout no editor visual. No editor possvel congurar o tipo do dispositivo para
fazer a pr-visualizao, congurar a orientao (vertical ou horizontal), o idioma
caso voc tenha preparado o aplicativo para internacionalizao etc. Uma das
conguraes que podemos fazer no editor escolher o tema para visualizar a
tela. Por padro, o editor utiliza o tema AppTheme, conforme indicado na gura 5.2.
H z.~z.:.__ '
Fa me Q- - I z.;>Y'P~~s~z
WW" . -.ari
' .Y .2.

._ 'E'
L~ z~;;\ 's

., -:z1.L.'
*ef ~i..'

~.;" fz-". fzz

.' \|.z,.'
_ ge 'ef'

JU
z ha..
f .>=.:~.f.i
.: ,.,:_>
, a, rar; ~
*`.1_zrc':
s;c e
''7 ..rr;.zE' `
Dl* 'fz'

Figura 5.2 - Pr-visualizao do layout com o tema padro.

Por enquanto vamos deixar para l este AppTheme, depois voltamos a falar dele. Agora
vamos brincar um pouco com o editor. Para trocar o tema que o editor utiliza, clique
no combo do AppTheme e escolha um dos temas Classic > Black ou Classic Light Light.
Esses so os temas utilizados at o Android 2.x (Figura 53). Observe que nesse tema
no existe a action bar, pois antigamente na barra superior era mostrado apenas
um pequeno ttulo, que inclusive muitas aplicaes deixavam oculto.
.
Captulo 5 I Action Bar e temas 121

I
f* MW-mfm' * <ff~*f.f~==~I .aa, .r
2E C:zll@~u=~

J,i \..
-\*fa*ul-.`

l Cap-Activity
. senna
l

Li, ___ __
I
QQ2El_,-
BI=

2 1;
' '
* 'im' s'_
5 W

*afif,
. .-~-
i ll-~.,

:al .~~
l -.I
ll H:p_.~_
wuu-

Stnha
fzi i at ,Q5
Gium - 9- ''21'

Figura 5.3 - Pr-visualizao do layout com os temas do Android 2.x.

Com a chegada do Android 3.0 (API Level 11) e os temas Theme.Ho1o e Theme.Ho1o. Light
a histria mudou, e nasceu a action bar, que representa o padro de design mais

.
importante do Android, pois nela que cam os botes com as principais aes
do aplicativo. Para fazer a pr-visualizao do layout nos temas Holo e HoIo.Lght
basta selecionar a verso do tema desejado no editor (Figura 5.4).

I M . _.
T activity__main.m1 X . _. . A activity maimxml > li V A
I32- =*
tvi, ,=
#25 ,Wu
lg ig; uzuz4~ ' Qoie "H @~ vzi- lg Q; g;Nzus4v - lwqm W- h rivai
El

Figura 5.4 - Pr-visualizao do layout com o tema Holo.

Na pr-visualizao voc vai perceber que o tema Holo padro tem fundo preto
e a fonte tem uma cor azul parecida com a do filme Tron: O Legado. j o tema
Ho1o.Lght tem o fundo branco com fonte preta, e a action bar fica com um fundo
cinza. importante entender que no tema Holo (escuro) os botes da action bar
devem ser brancos. E no terna Ho1o.Lght (claro) os botes da action bar devem ser
escuros, assim a visualizao dos botes da action bar cam coerentes. Cada tema
tem diversas variaes; no entanto, isso voc vai perceber com o tempo. Uma das
,ii1; 1lI.
122 Google Android - 4 edio
\';1ria(es de tema mais utilizadas o Hoio.Light.DarkActionBar, qu d1X21 0 fUnd0
da tela claro igual o Ho1o.Light, mas o fundo da action bar ca escuro, Pfm1fmd0

1 . ._
utilizar botes brancos na action bar.

irI=~
uI | ut ___
Por ltimo voc pode selecionar no editor para visualizar o tema Material Dark e
Material Light, conforme a figura 5.5. Veja que a diferena entre o tema Material
para o Holo e que 0 I-Iolo mostrou 0 cone na action bar.
l , (N`]_fT1I.IYl K 1 0 dmty_man.xml - _
'yflll
'- ,. .il* ';- zz r;
if ' :,& fi . . , ~'' 5'
1 ' Ntxux 4' rs' Q'Mterra| W' ii: A 1- ' Nc\us4- ' ' ' fhf f112*'
* l3&&ii:'ic:.

` Gnplclviy i
E

l
l
I

L...._a.
l

i l

i
r

Figura 5.5 - Pr-visualizao do layout com o tema Material.

Certo, muito bem. Agora vamos voltar a falar daquele AppTheme que vimos no editor
visual. De onde esse nome surgiu? O tema AppTheme denido no arquivo /res/vaIucs/
styles.xml, e 0 editor consegue ler essa configurao e mostra-la para voc. Esse
o tema da aplicao, portanto, nele que vamos fazer as customizaes de cores.
A partir deste momento preste muita ateno, pois estou explicando com base
nos arquivos que foram gerados no wizard na poca em que este livro estava
sendo escrito. Mas 0 wizard frequentemente muda a forma de gerar os arquivos,
portanto o que importa voc entender 0 conceito. A seguir temos 0 arquivo
styles.xml, que foi criado pelo wizard, nele que 0 tema AppTheme foi definido. Esse
arquivo foi congurado para utilizar ou tema Holo. Veja que 0 tema AppTheme herda
de Theme.Ho1o.Light.

/res/values/styIes.xmI

<sty1e name="AppTheme" parent="android:Theme.Ho1o.Light ">


Captulo 5 I Action Bar e temas 123
E no arquivo AndroidManiest.xml o tema AppTheme foi congurado como o tema
do projeto com a notao @styIe/tema. Por isso o editor visual l esse AppTheme, pois
ele o tema do projeto.

AndroidManifest.xmI
<?xmI version="1.0" encoding="utf-8"?>

<appIication android:theme="@styIe/AppTheme" >

Nota: o tema que o aplicativo vai utilizar configurado no AndroidManiest.xml. Por


padro, o tema AppTheme criado automaticamente no arquivo /res/values/styles.xml
e herda de algum tema nativo do Android, seja alguma variao dos temas HoIo
oi1MateriaI.

Veja que o Android Studio tambm criou o arquivo /res/values-v21/styles.xml, que


est configurado para utilizar o tema Material. A pasta /res/values-v21 utilizada
para configurar os recursos para o Android 5.0 (API Level 21) ou superior.

/res/values-v21/styIes.xmI

<styIe name="AppTheme" parent="android:Theme.Materia1.Light ">

No Android, sempre que voc ver uma pasta com um trao e um nmero, como
por exemplo /res/values-1/21, porque esse nmero referente ao identificador da
API Level com o qual essa pasta compatvel. Nesse caso, o Android vai utilizar
por padro o arquivo /res/values/styles.xml, e se o dispositivo tiver o Android 5.0 ou
superior (API Level 21), a congurao feita no arquivo /res/values-v21/styles.xml
utilizada.

Nota: os identicadores numricos nas pastas so chamados de qualicadores


por API Level e denem a verso do Android que vai utilizar esses recursos.
124 Google Android - 4= edio
Para encerrar esta breve explicao sobre temas, lembre-se de que no ar
quivo AndrilMmi_csr.xml o tema da aplicacao definido pelo trlbuw
androd:theme:"@style/nome_do_tema". lsso e feito assim para que o tema possa ser
customizado dependendo da versao do Android.
limbora voc possa customizar o tema dependendo da verso do Android com
os qualicadores por API Level e criar variaes da pasta /res/values, atualmente
isso nao e mais necessario, pois podemos utilizar a biblioteca de compatibilidade
e usar o terna Apptlompat para todas as verses do Android. Vamos primeiro estudar
como utilizar a action bar nativa e depois aprenderemos mais detalhes sobre essas
questes de compatibilidade.

5.3 Projeto de exemplo sobre action bar


Para estudarmos o funcionamento da action bar, abra o projeto HeIIoAt'tionBar no
Android Studio, o qual faz parte do material de download do livro. Para fazer isso.
utilize o menu File Open e selecione a pasta do projeto.
Ao executar esse projeto no emulador, o resultado ser como a figura 5.6, que
mostra os botes de busca e atualizar na action bar, bem como a ao de Settings
no menu action overflow. Saiba que os botes que cam como action buttons
podem ter imagens, mas os botes que ficam no menu action overflow contm
apenas textos.

Settings

z~n'l ,,;'i` iti|.I_`_ '.i

Figura 5.6 - Exemplo de action bar:


Captulo 5 -Action Bar e temas 125
Os arquivos de menu so denidos no arquivo XML /res/menu/menu_main.xml.
Como voc pode ver no cdigo-fonte a seguir, os botes na action bar aparecem
na mesma ordem em que esto denidos no arquivo.

/res/menu/menu_man.xmI
<menu xmlns:android="http://schemas.android.com/apk/res/androd"
m1ns:too1s="http://schemas.android.com/tools" >
<item androd:d="@+d/action_search"
android:icon="@drawable/c_action_search" androd:title:"@string/action_search"
androd:showAsAction="a1ways" />
<tem androd:id="@+d/action_refresh"
androd:icon="@drawable/ic_acton_refresh" android:title:"@string/acton_refresh"
androd:showAsAction="a1ways" />
<item android:id="@+d/acton_settngs"
android:tit1e="@string/action_settngs"
androd:showAsActon="never" />

Ao executar o projeto, os cones de Search e Refresh vo aparecer na action bar,


pois esto configurados com a opo androd:showAsActon="a1ways". j a ao
de Settings ca no menu action overovsg pois est congurada com a opo
androd:showAsActon="never". Ao clicar nos botes, o evento est sendo tratado. A
gura 5.6 mostra o resultado ao clicar no boto de Refresh. Note que cada item de
menu referencia um texto que est cadastrado no arquivo /res/values/stringsxml.

/res/values/strings.xmI
<?m1 version="1.0" encoding="utf-8"?>

<strng name app_name">LvroAndroidCap5-ActonBar</strng>


<strng name he11o_wor1d">He11o wor1d!</strng>
<strng name action_settings">Settings
<strng name action_search">Search</string
<strng name action_refresh">Refresh

Para utilizar esse arquivo XML de menu, a activity deve implementar o metodo
onCreateOptonsMenu(menu) e inar o menu XML. Isso simples conforme mostra
este cdigo:
@Override
public boolean onCreate0ptonsMenu(Menu menu) {
// Ina o menu com os botes da action bar
126 Google Android - 4' edio
getHenuInater().inate(R.menu.menu_main, menu);
return true;

Uma vez que o menu com os botoes da action bar esto configurados, basta imple
mentar o mtodo on0ptionsItemSelected(MenuItem) para tratar os eventos gerados pelos
botoes. Por isso no arquivo XML dc menu foi denido um id para cada ttcm. O
codigo-fonte completo da classe HainActivity do projeto pode ser visualizado a scgutr.

l: ManActivity.java

public class MainActivity extends Activity {


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

@0verride
public boolean onCreate0ptionsMenu(Menu menu) {
// Ina o menu com os botes da action bar
getHenuInater().inate(R.menu.menu_main, menu);
return true;
}

@0verride
public boolean on0ptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_search) {
toast("Clicou no Search!");
return true;
} else if (id == R.id.action_refresh) {
toast("Clicou no Refresh!");
return true;
} else if (id == R.id.action_settings) {
toast("Clicou no Settings!");
return true;
}

return super.on0ptionsItemSelected(item);
}

private void toast(String msg) {


Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}

}
Capitulo S I Action Bar e temas 127
Esse cdigo est mostrando um alerta ao clicar em algum boto da action bar,
portanto execute o projeto no emulador e congura o resultado. Conforme po
demos verificar, adicionar os botes na action bar realmente simples.

Nota: ao congurar um action button no arquivo XML de menu, recomendvel


utilizar um cone para deixar o visual mais interessante. Muitas vezes, somente
de olhar o cone, o usurio j sabe o que aquele boto faz, como so os casos
da lupa de busca e o refresh. No entanto, mesmo que uma gura seja utilizada,
e importante congurar o ttulo, porque se o usurio pressionar o boto por
dois segundos o Android vai mostrar um toast com o ttulo desse boto. Isso
tambm importante por questes de acessibilidade, pois deficientes visuais
utilizam softwares que conseguem ler tudo o que est escrito na tela. O mesmo
conceito aplica-se ao componente Imageview, cujo atributo android:contentdescrpton
fornece o texto explicativo da gura, o qual pode ser lido por estes softwares.

5 4 Opes de visualizao dos action buttons (always, never, ifRoom)


Ao adicionar um action button na action bar, voc deve escolher como ser feita
a visualizao deste, isto , se ele sempre ficar visvel, ou se car disponvel no
menu do action overflow etc. Para isso, voc pode utilizar qualquer uma destas
constantes no atributo app:showAsActon="xxx":

Indica que o boto sempre deve car visvel como action button. re
comendado utilizar essa opo para denir as aes mais comuns do
aplicativo.

Mostra o boto na action bar se existir espao, ou move ele automatica


mente para o menu action overow caso no tenha. Muitas vezes essa a
congurao adequada para manter a compatibilidade com diversos tipos
de dispositivos e tambm com telas na vertical e horizontal.

w1thText

Mostra o ttulo do boto ao lado do cone, caso tenha espao disponvel


na action bar. Por exemplo, na horizontal existe mais espao na action bar,
portanto possvel exibir o ttulo opcionalmente.
128 Google Android - 4 edio
never

Nunca mostra 0 boto na action bar, deixando a ao nO 11161111 8CUOI1


overflow

co11apseActonVew

Esse atributo indica que uma view que geralmente grande deve ser
contrada para exibir apenas o boto. Esse 0 caso do boto de busca do
Android, que ca contrado, mas ao ser clicado se expande para o usurio
digitar o texto.
Com o tempo voc entender melhor cada um desses itens, mas lembre-se de
que geralmente recomendado utilizar as opes fRoom para garantir que se no
houver espao o boto aparea no menu action overow, e a opo never se voc
tiver certeza que a opo deve car no menu action overflovv Tambm possvel
combinar essas opes com o separador, como por exemplo: app:showAsActon="if
Room|wthTet". Agora com voc, brinque um pouco com essas opes e veja os
resultados no emulador.

1
Nota: segundo as boas prticas do Android, os action buttons (botes com
aes) devem ser utilizados para as aes mais comuns da tela, ou seja, as aes
que sero mais utilizadas pelo usurio. j as aes que so menos utilizadas,
como por exemplo Ajuda e Configuraes, devem car no menu action overflow
(menu flutuante).

5.5 Template de cones para os botes da action bar


Ao criar os cones para os botes da action bar, importante seguir o padro de
cores. Por exemplo, o projeto de exemplo est congurado para utilizar o tema
Material conforme demonstrado a seguir:

/res/values-v21/styIes.xmI
<?m1 verson="1.0" encodng="utf-8"?>

<sty1e name="AppThene" parent="androd:Theme.Materal.Lght.DarkActonBar">


</sty1e
Captulo 5 I Action Bar e temas 129
Nesse caso, como foi congurada a action bar com o padro escuro Dark os
botes precisam ser brancos, por isso verique que os cones que coloquei na
pasta /res/drawable so claros (Figura 5.7).
Eres __i,
p tg drawable-mdpi
D*-F' dfawmbte-nidp Q W
ic,,action_refr:sh.png
ic__action_s:zarch.png i
D layout
menu
i va|ues I
* ==' v'alues~w820dp _
W AndroidManif:st.xmI 1

Figura 5.7 -cones para os botes da action bar

Nota: os nomes dos cones da action bar seguem a nomenclatura c_acton_none.png.

Voc deve estar se perguntando de onde eu tirei essas guras. Felizmente existe
uma coleo com o template de vrios cones com as aes mais comuns, como:
atualizar, buscar, adicionar, deletar, copiar, colar, compartilhar etc. Para baixar o
pacote de cones da action bar, acesse a pgina da documentao da action bar e
procure pelo link Download the Action Bar Icon Pack.

http://developer android.com/design/patterns/actionbar html


Ao descompactar o arquivo do pacote, voc ver as imagens para o tema Holo
Dark e Holo Lgh. No projeto que criei neste captulo, estou utilizando o tema
Theme.Matera1.Lght.DarkActonBar. Isso signica que a action bar escura e os botes
devem ser brancos. Nesse caso o correto selecionar algum cone criado para o
tema Holo Dark. Eu copiei as guras de Refresh e Search para a pasta /drawable/xxhdpi.
No pacote de cones voc ver que existem as guras para vrias densidades,
mas eu geralmente coloco no projeto apenas as guras para a maior densidade,
e deixo o Android redimensionar as imagens em tempo de execuo, no caso de
o aplicativo executar em telas com menor resoluo.

5.6 Classe android.app.ActionBar


Por padro, o ttulo que aparece na action bar o nome da activity congurado
no atributo androdzlabel da tag <actvty> no arquivo AndroidManiest.xml.
130 Google Android - 4 edio
Esse ttulo pode ser customizado dinamicamente no cdigo, 6 550 P0d ser ne'
cessrio dependendo da lgica da aplicao. A activity p ode chamar o mtodo
getActionBar() para obter o objeto android.app.ActionBar e depois chamar O metodo
actionBar.setTit1e("") para customizar o ttulo.

MainActivity.java
import android.app.Activity;
import android.app.ActionBar;
public class MainActivity extends Activity {`
protected void onCreate(Bund1e savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.1ayout.activity_main);
ActionBar actionBar = getActionBar();
actionBar.setTit1e("Captu1o S");
}

Ao executar esse exemplo no emulador, voc ver que o ttulo da action bar ser
Captulo 5' Existem vrios mtodos na classe android.app.ActionBar e a lista a
seguir contm alguns dos mais importantes.

setCustomView(int ou View)

Permite adicionar uma view customizada na action bar. Um exemplo de


view customizada o boto de busca do Android, que encapsulado na
classe Searchview.

setTit1e(string)
Altera o ttulo da action bar.

setIcon(DrawabIe)

Altera o cone home que por padro mostra o cone do projeto.

setDisp1ayShowTit1eEnab1ed(boolean)

Congura se para exibir o titulo na action bar.

setDispIayShowHomeEnabied(boolean)

Congura se para exibir o logo/cone na action bar, chamado de home


Captulo 5 n Action Bar e temas 131
setDisp1ayHomeAsUpEnabled(boolean)

Exibe a setinha para esquerda up navigation para indicar que o usurio


pode voltar tela anterior ou navegar para cima na hierarquia de telas.
Embora existam muitos outros mtodos na classe android . app.ActionBar, o recomen
dado voc ler a documentao ocial (javadoc) da classe. Alguns dos mtodos
so para criar a navegao por tabs e drop down, ento vamos estud-los depois.

5.7 SearchView

A action bar permite adicionar views customizadas, sendo que um exemplo cls
sico o Searchview. Para este prximo exerccio, vamos utilizar o Searchview; assim,
quando o usurio tocar no boto de busca, o campo de texto ser expandido
para o usurio digitar o texto da busca. Felizmente o Searchview j faz todo esse
trabalho e para utiliz-lo basta congurar a tag android:actionViewCiass conforme
demonstrado a seguir.

/res/menu/menu_main.xmI
<menu xmins:android="http://schemas.android.com/apk/res/android"
xm1ns:toois="http://schemas.android.com/tools" >
<item android:id="@+id/action_search"
android:icon:"@drawabie/ic_action_search" android:title:"@string/action_search"
android:showAsAction="a1ways"
android:actionViewC1ass="android.widget.SearchView" />
// . . . Outros botes de refresh e settings aqui

Nota: o Searchview uma view customizada que pode ser inserida na action bar,
a qual chamada de Action View. Um Action View tem por objetivo substituir o
boto da action bar por alguma view customizada.

No cdigo da activity; basta obter -o -objeto do S=ea'rchView e configurar para a apli


cao tratar o evento Searchview.0nQueryTextListener. Note que o cdigo a seguir
est resumido, pois estou mostrando apenas o que precisa ser alterado referente
ao Searchview.
132 Google Android - 4 edio
Qu ManActivity.java

import android.widget.Searchview;
public class MainActivity extends Activity {

@0verride
public boolean onCreate0ptionsMenu(Menu menu) {
// Ina o menu com os botes da action bar
getMenuInater().inate(R.menu.menu_main, menu);
Henulten item = menu.ndItem(R.id.action_search);
Searchview searchview = (Searchview) item.getActionView();
searchview.set0nQueryTextListener(onSearch());
return true;
}

private Searchview.0nQueryTetListener onSearch() {


return new Searchview.0nQueryTetListener(){
@Override
public boolean onQueryTextSubmit(String query) {
// Usurio fez a busca
toast("Buscar o texto: " + query);
return false;
}

@Override
public boolean onQueryTetChange(String newText) {
// Mudou o texto digitado
return false;
}

};
}

Ao executar o projeto e clicar o cone de busca, o Searchview vai expandir para o


usurio digitar a busca. A gura 5.8 mostra o resultado em que eu digitei o texto
Livro Android e pressionei no emulador para fazer a busca.
Captulo 5 n Action Bar e temas 133

Helio 'NOYC' Helio world!

Buscar o texto: Livro Android

Figura 5.8 - Exemplo de SearchView

5.8 Action provider


De forma similar ao action vievsg um action provider tambm substitui algum
boto por um layout customizado. C* action provider mais famoso de todos o
de compartilhar. Por exemplo, na galeria de fotos, ao compartilhar uma foto, o
Android mostra automaticamente todos os aplicativos que podem enviar a foto,
como por exemplo: Gmail ou Hangouts.
Para configurar um action provider em algum boto da action bar, basta adicionar a tag
androd : actonProvderC1ass e informar alguma subclasse de androd .vew.ActonProvder.
Neste exemplo vamos utilizar a classe androd.widget.ShareActonProvder que facilita
o trabalho de compartilhar algum contedo.

/res/menu/menu_main.xmI
<menu xmlns:androd="http://schemas.androd.com/apk/res/androd"
xmlns:tools="http://schemas.androd.com/tools" >
<tem androd:d="@+id/acton_search"
androd:icon:"@drawable/c_acton_search" androd:title:"@string/acton_search"
android:showAsAction="always" androd:actonVewC1ass="androd.wdget.SearchVew" />
ten androd:d="@+d/action_share"
androd:con="@drawable/c_acton_share" androd:tt1e="@strng/acton_share"
android:showAsActon="a1ways"
androd:actionProvderC1ass="android.widget.ShareActonProvder" /
<tem
134 Google Android - 4 edio
android:id="@+id/action_refresh" android:icon="@drawable/ic_action_refresh"
android:title="@string/action_refresh"
android:showAsAction="ifRoom" />
<item
android:id="@+id/action_settings" android:title:"@string/action_settings"
android:showAsAction="never" />

Nota: como desta vez existem trs botes na action bar, congurei os botes de
busca e compartilhar como showAsAction="always" para carem visveis, mas o boto
de refresh deixei como showAsAction="ifRoom"; assim, o Android vai decidir se o boto
vai car como action button ou se vai ser mostrado no menu action overflow.

Depois de congurar o item de menu da action bar com o ShareActionProvider, basta


customizar a Intent que ser utilizada para disparar a mensagem ao sistema opera
cional, a m de compartilhar o contedo Vimos no captulo 4, sobre a classe Activity,
que uma Intent pode ser utilizada para navegar entre as telas da aplicao, mas na
verdade uma intent representa uma mensagem que enviada ao sistema operacional
para os mais variados ns. No caso do compartilhamento, quando a intent enviada,
o sistema operacional vai perguntar para todas as aplicaes instaladas quem que
consegue tratar essa mensagem para compartilhar o contedo O cdigo-fonte a seguir
est resumido e mostra apenas o necessrio para implementar o ShareActionProvider.

MainActivity.java

import android.uidget.ShareActionProvider;
public class MainActivity extends Activity {

@0verride
public boolean onCreate0ptionsMenu(Menu menu) {
// Ina o menu com os botes da action bar

// Searchview `
getHenuInater().inate(R.menu.menu_main, menu);

Menultem searchltem = menu.ndItem(R.id.action_search);


Searchview searchview = (Searchview) searchltem.getActionView();
searchview.set0nQueryTetListener(onSearch());

// ShareActionProvider
Henelten shareltem = menu.ndItem(R.id.action_share);
SharectionProvider share = (ShareActionProvider) shareltem.getActionProvider();
share.setShareIntent(getDefaultIntent());
return true;
Captulo 5 I Action Bar e temas 135
}

// Intent que dene o contedo que ser compartilhado


private Intent getDefau1tIntent() {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/*");
intent.putExtra(Intent.EXTRA_TEXT, "Texto para compartilhar");
return intent;
}

Ao executar a aplicao no emulador, o resultado deve ser como a gura 5.9. O

l
1w l
ShareActionProvder mostra todos os aplicativos que conseguem tratar a mensagem
enviada pela intent de compartilhamento, porm no simulador somente o aplicativo
de mensagem est instalado. Em um dispositivo real, comum encontrar vrios

z4 1
l
1I EKi. i1..'
aplicativos ao clicar no cone de compartilhar. Nesse exemplo vimos a configurao

y
.
!
I
E
' 1
= l l
de uma intent bsica para compartilhar textos. Futuramente, durante o desenvol
vimento do aplicativo para carros, veremos como compartilhar a foto de um carro.

Heilo world! ,TO I p ,


5i

1i
5

.
zTexto
I
1 ir , . _ . , _ .
para compartilhar

Figura 5.9 - Exemplo de ShareActionPr01/ider

5.9 Split action bar


Dependendo da aplicao, voc pode precisar de mais espao para exibir os
botes na action bar, e uma opo utilizar o split action bar, que vai deixar os
botes na parte inferior da tela. Para habilitar a split action bar, edite o arquivo

a tag na configurao da tag . _


AndroidMcmifest.xml e insira o atributo android:ui0ptions="splitActionBarwhenNarrow" e
136 Google Android - 4 edio
AndroidManifest.xmI
<3m1 version="1.0" encoding="utf-8"?>
manifest ... >
application ... >
attivity android:name="br.livroandroid.cap5.actionbar.MainActivity"
android:1abe1="@string/app_name"
android:ui0ptions="sp1tActionBarHhenNarrow">
<neta-data android:nane="android.support.UI_0PTIONS"
android:va1ue="sp1itActonBarHhenNarrow" />
<ntent-1ter>...</intent-1ter>
</actvity>
</app1caton>
</manfest>

Feito isso. ao executar o projeto o resultado deve ser como a figura 5..lO. Na ver
dade, a split action bar economiza espao se necessrio; caso o dispositivo esteja
na horizontal, como existe espaco suciente, os botes da action bar cam na
parte superior normalmente.

* 'i L `*f. Oi kl

Figura 5.10 - Split action ban

Nota: a configurao da split action bar deve ser feita activitv por activity e no
e possivel alterar pelo codigo, somente no arquivo Ai1ridMziiij~st.xml. Essa
conguraao parece que toi descontinuada (deprecated) no Material Design
pois no Android 5.0 isso no funciona mais. O print que voc est vendo e do
Android 4.4 com o tema Holo.
Captulo 5 n ction Bar e temas 137
5.10 Up navigation
No captulo 4, sobre activity criamos um aplicativo com uma tela de login com
a mensagem de bem-vindo, a qual foi mostrada em outra tela. Para voltar tela
anterior, podemos utilizar o boto voltar nativo do Android, ou o up navigation,
que a seta que aponta para a esquerda e ca na action bar.
Como j explicado anteriormente, o up navigation utilizado para subir na
hierarquia de telas; seu funcionamento muitas vezes parecido com o boto
voltar, mas, dependendo do caso, pode ser diferente. Vimos que para mostrar
a seta do up navigation na action bar basta chamar o mtodo getActionBar().
setDisp1ayHoneAsUpEnab1ed(true) e depois o mtodo on0ptionsItenSe1ected(Menulten)
chamado; o identicador android . R.id . home deve ser utilizado para identicar a ao.
@0verride
public boolean onMenuItenSe1ected(int featureld, Menulten item) {
// Clicou no "up navigation"
if(iten.getItenId() == android.R.id.hone) {
// O mtodo nish() vai encerrar essa activity
nish();
return true;
}

return super.onMenuItenSe1ected(featureld, iten);


}

Se no quiser voc no precisa implementar o mtodo onOptionsItenSe1ected(Menulten),


pois possvel congurar o AndroidManiest.xml para que o comportamento do up
navigation da activity siga o padro, que voltar a tela anterior. Para isso existe
o atributo android:parentActivityNane, que permite congurar a activity me na hie
rarquia de telas, assim o Android sabe para qual tela precisa voltar. Como esse
atributo foi criado no Android 4.0 (API Level 14), preciso congurar tambm a
tag neta-data para suportar as verses com Android 2.1 (API Level 7) ou superior.
Ento faa o teste! Altere o cdigo do arquivo AndroidManifest.xml do projeto que
fizemos com a tela de login, e comente o mtodo onOptionsItenSe1ected(Menulten) na
classe BenVindoActivity, pois ele no ser mais necessrio. Ao executar o projeto no
emulador, o up navigation vai funcionar normalmente.

AndroidManfest.xmI
<?xn1 version="1.0" encoding="utf-8"?>
<nanifest ... >
<app1ication ... >
<activity android:nane=".MainActivity" android:1abe1="@string/tit1e_nain_activity" >
133 Google Android - 4 edio
</activity
<activity android:nane=".BenVindoActivity" android:parentActivityName="-HBHCVY" >
<!-~ Compatibilidade com a API levei 7+ -->
neta-data android:nane="android.support.PARENT_ACTIVITY"
android:va1ue=".HainActivity" /

/appiication

5.11 Navegao por tabs na action bar


A navegao por tabs na action bar permite ao aplicativo mostrar as principais
sees que o usurio pode navegar e considerada o nvel (top-level) de navegao
do seu aplicativo. As tabs devem ser utilizadas no caso de existirem poucas sees
para navegar no aplicativo, sendo que o principal objetivo mostrar ao usurio
as sees que o aplicativo contm de forma simples e rpida.
A navegao por tabs utilizada em aplicativos como o Google Play Para aplicati
vos que temham muitas sees de nvel (top-level), um padro de design que est
sendo muito utilizado o Navigation Drawer (menu lateral utilizado no aplicativo
do Gmail), pois nele o menu lateral pode exibir diversas opes e mostrar uma
rolagem na vertical.
Adicionar as tabs na action bar bem simples, basta utilizar o mtodo
setNavigationMode(ActionBar.NAVIGATION_MODE_TABS) da classe ActionBar e depois criar as tabs
com o mtodo addTab() . Ao clicar numa tab, os mtodos da interface ActionBar . TabListener
so chamados para permitir que o aplicativo realize a ao necessria para trocar o
contedo da tela. Para brincar com as tabs, vamos alterar o projeto He11oActionBar para
criar trs tabs. Ao clicar em cada tab, vamos apenas mostrar um alerta com o toast.

MainActivity.java

public class MainActivity extends Activity {

@0verride
protected void onCreate(Bund1e savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.iayout.activity_main);
ActionBar actionBar = getActionBar();
actionBar.setTit1e("Capitu1o 5");
Captulo 5 I Action Bar e temas

/I Congura a action bar para utilizar as tabs


actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Cria as tabs (Passa como parmetro o indice de cada tab: 1,2,3)
actionBar.addTab(actionBar.newTab().setText("Tab 1")
.setTabListener(new MyTabListener(this,1)));
actionBar.addTab(actionBar.newTab().setText("Tab 2")
.setTabListener(new MyTabListener(this,2)));
actionBar.addTab(actionBar.newTab().setText("Tab 3")
.setTabListener(new MyTabListener(this,3)));
}

Para o cdigo compilar crie a classe MyTabListener, a qual implementa a interface


ActionBar.TabListener e responsvel por tratar os eventos das tabs.

MyTabLstener.java

import android.app.ActionBar;
import android.app.FragmentTransaction;
import android.content.Context;
import android.widget.Toast;
public class MyTabListener implements ActionBar.TabListener {
private Context context;
private int tabIdx;
public MyTabListener(Context context, int tabIdx) {
this.context = context;
this.tabIdx = tabIdx;
}

@0verride
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
// Chamado ao selecionar uma tab
Toast.makeText(context, "Selecionou a tab: " + tabId, Toast.LENGTH_SHORT).show()
l
@0verride
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
// Chamado quando a tab perde o foco (se outra tab selecionada)
}

@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
// Chamado quando uma tab selecionada novamente.
l
}
HO

\11l`111.1
\

\111
._\
.1.\1`1 11c11.11'1111`111~
`\
1 1 1. _ ~1111 11111 1(\11\1
1 11 11111u.1 11 1c1111.11111 111*c c\c111|1111 111.11 .1 111 1.11 1 1

1I\\
1 _ 1.\1\( 111111111.111.1
\111`1l.1\1\1111111`1`11.11.11\ 1~1cc11111.111.1. N1|11'1111`1 1|111111111 111111 _1\x
1111119111 Androld 41 edi

_ 1 11. ~ . .1\. 111

. 111 . 11 .111
\\\ .11`111.1u\11;1c1.11111c111c.1u1.111:.111111111111c111111111111.1111.1 111.1 l~>1'1 * "* * *
1 1 1 \ `. . ` . 1.
'\
\l11(` \.111111 cs1u11.11 11111 1\1l1111\~111uu1' 1 1111 131 1 1
.~\111*11
1 11111.11 11111.1 1.11\1\ 11111111111111111.1111111111111111 1' 1 11.1111.11111.11 1111.11 11111. ll 111
1

1 1. . 111 111

1l111111\1\111`\`11`\\'1`1\1`1`I.11\11l1`|\1\111`1`1`11\1`1l111\1`l1\111l1l111l11.\111\11 1 1111111111 Il 1
1

c1c1111.11` .11|uc11* c11111c111111.

:z111~1~111111111 11 1311 L'

1~`1`u1.1 1.11 .-1111111111111 111m 11111.1

.1-11.
Ateno: \'11c1* 11c\'c 1c1 |1c11'1~1111111 1`111` c\1s1c111 .11}11l1\ .11c1`1.1s \\\'.\l`l\ll\}S1 1111
1
111 11i1;11 11.15 l.111s. Isso 1\_\1Hl\`\`l` I`\11_\I11\` 1111 .~\11111'11111 1.11 11 111111111 11c 11.1\'1'1;.1c.111

|1111'1.111s 11.1 .111111111 111111111 111~sc1111111111.11111 111c111'c1.111~11\.

l)[`}`\1lS 1111 1111111;1c I 11 .T11l_ 11 11111111111 111|111111111l1:1111 11111.1 1111111111c1`.1 1111


\`\\1I\\\(`1\l\lS 111111.-'.11111s 1111 M.111*1'1.11 I3c11z11 c11.1111.111.1 .-11111111111 111~11gr1 Su1.1r
111 11.111-. 111`l1ll`1` 11s 1111\'11 111111111111c1111-s. 1111 1*1`1.11111 11 111111 _1\-11111_ 1111~ 111111111 11

p1^11111`111 11111111~ 1.1 111: c 111111.'.11111 1.11'.1 1111.11 1.I1\s. \`.111111s c11111.1 111 111.115 1.1111c
1111 111'1c11\'111\^1'l` U 1\l11\`-111\' 11115 1'.11'1'11. 11111111 1111111'.u' 11111111 1'1i.11` 1.111s \.\\111
.1 .11`1I1\11 1\.11`. 1110511111 1|111` 111`|W1`1'1`.111'1_1. 111115 CNIC 11\1~|\\}1|11 1~ 11111 11_\.111 11 \111'1`

|\I`1`1`1.11`1\I1111`1`1\ 111.1\1111111\'1111.1s1.111 1111111.11'11111111.11 1~s1.11'11c11cc.11c11cp111'111c


1111111111111 111111 1'c1"11111c1111.11111111111;'.11'.1 11111111.11'11 .1I\11111\\ l.*\.
Captulo 5 I Action Bar e temas 141
5.12 ActionBar(ompat - a biblioteca de compatibilidade da action bar
No evento Google I/ O 2013, o Google anunciou o suporte a action bar para verses
anteriores do Android, compatvel com o Android 2.1 (API Level 7) ou superior. Essa
biblioteca conhecida como biblioteca de compatibilidade v7 ou ActionBarCompat.
Para utilizar a action bar de compatibilidade, a primeira tarefa a fazer declarar a
dependncia para a biblioteca v7 no arquivo app/buildgradle do mdulo. Lembre
-se de que existe o arquivo build. gradle que ca na raiz do projeto (no esse) e o
arquivo app/buildgradle que fica dentro do mdulo. Voc geralmente vai mexer no
arquivo de configurao do mdulo. Como exerccio, vamos migrar o projeto de
exemplo da action bar deste captulo para utilizar a action bar de compatibilidade,
para deixar o projeto compatvel com o Android 2.1 (API Level 7).
Ento vamos l! Para comear a brincadeira, faa duas alteraes no arquivo
app/build.gradle.

1. Altere o atributo minSdkVersion para 7


2. Adicione a dependncia para a biblioteca appcompat-v7.

app/buiId.gradIe
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultCong {
applicationld "br.com.livroandroid.actionbar"
ninSdkVersion 7 // API Level 7 (Android 2.1)
targetSdkVersion 22
versionCode 1
versionName "1.0"
}

dependencies {
compile leTree(dir: 'libs', include: ['*.jar'])
// Dependncia da biblioteca de compatibilidade v7
conpile 'com.android.support:appconpat-v7:22.1.1'
1

No item defaulttong foi denido que a aplicao suporta o Android 2.1 (API Level 7)
como a verso mnima e o target o Android 5.1 (API Level 22). Lembre-se de que
o target deve ser sempre a ltima verso e quando voc estiver lendo este livro
1 42 Google Android - 4 edio
, . - z - ~ uivo dentro do
bem provavel que existam versoes novas. Na ultima linha dO 8fCl
item dependences configurada a seguinte dependencia:
Compile 'com.android.support:appcompat-v7:22.1.1'

Isso indica ao Gradle que a biblioteca de compatibilidade deve ser adicionada


como dependncia do projeto, a qual contm a action bar de compatibilidade.
No meu caso a verso 22.1.1, pois a verso do item Android SuDDf'f Lbffy que
instalei pelo SDK Manager.

Nota: ao adicionar uma nova dependncia no buildgradle clique no boto Sync Ilow
que aparece no editor. Isso faz com que o Gradle baixe a dependncia e a deixe
ativa no projeto, para que as funcionalidades como o assistente de cdigo e o
compilador encontrem as classes desta biblioteca. Essa opo tambm pode ser
acessada pelo menu Tools > Android > Sync Project with Gradle FIGS

O simples fato de referenciar no arquivo buildgradle a biblioteca de compatibili


dade da action bar faz com que o Gradle faa o build corretamente e resolva essa
dependncia na compilao do projeto. Mas lembre-se de clicar no boto Sync Now
que aparece no editor!
Depois de adicionar a dependncia, a primeira tarefa a fazer congurar 0 tema
do projeto no AndroidManifest.xml. O tema de compatibilidade o Theme.AppCompat
e suas variaes so o Theme.AppCompat.Light e Theme.AppCompat.Lght.DarkActonBar.
Ento altere o arquivo /res/values/stylesxml para utilizar o tema Theme.AppCompat.
Lght.DarkActonBar.

/res/values/styIes.xmI
<resources
<sty1e name="AppTheme" parent="Theme.AppConpat.Lght.DarkActonBar">

Como vamos utilizar o tema de compatibilidade AppCompat, no precisamos ter


vrios arquivos styles.xml, portanto apague os arquivos que esto em pastaS
/res/values-1/11 ,/res/values-1/14,/res/values-v21 etc. O Objetivo de utilizar essas pastas
com os qualicadores por API Level alterar o tema dependendo da verso do
Android. Vamos utilizar o tema AppCompat,que nico para todas as verses, por
isso podemos deixar apenas um arquivo /res/values/styles.xmI no projeto
_ j Q ' car o que precisa ser alterado no cdigo
Depois de configurar o tema, vamos veri
da activity Primeiramente, altere o cdi
80 da HACtvty para que ela seja lha
Captulo S I Action Bar e temas 143
de android.support.v7.app.AppCompatActivity. Feito isso, em vez de utilizar o mtodo
getActionBar() que retorna a classe android.app.ActionBar, obrigatrio utilizar o
mtodo getSupportActionBar() que retorna a action bar de compatibilidade, cuja
classe android.support.v7.app.ActionBar.

O cdigo a seguir mostra as alteraes bsicas da MainActivity para utilizar a action


bar de compatibilidade:

MainActivity.java
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.ActionBar;
public class MainActivity extends AppCompatActivity {
@Override

protected void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getSupportActionBar();
actionBar.setTitle("Capitulo 5");

A MainActivity utiliza tambm o Searchview e o ShareActionProvider, e essas classes


tambm fazem parte do pacote de compatibilidade, por isso precisamos alterar o
cdigo para utilizar as classes android.support.v7.widget.Searchview e android.support.
v7.widget.ShareActionProvider. Alm disso, importante que ao congurar os itens
de menu no mtodo onCreate0ptionsMenu(menu) voc utilize a classe android.support.
v4.view.MenuItemCompat para obter o Searchview e o ShareActionProvider. A seguir podemos
visualizar o cdigo completo da classe MainActivity com todas as alteraes necess
rias para utilizar a action bar de compatibilidade. Preste ateno nos imports das
classes, pois estamos importando os pacote android.support.v4 e android.support.v7.

MainActivity.java

import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.ShareActionProvider;
public class MainActivity extends AppCompatActivity {
@Override
144 Google Android - 4 edio
protected void onCreate(Bundie savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.1ayout.activity_main);
ActionBar actionBar = getSupportActionBar();
actionBar.setTit1e("ActionBar Compat");
// Navegao por tabs
actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS);
// Cria as tabs (Passa como parmetro o indice de cada tab: 1,2,3)
actionBar.addTab(actionBar.newTab().setTet("Tab 1")
.setTabListener(new MyTabListener(this,1)));
actionBar.addTab(actionBar.newTab().setTet("Tab 2")
.setTabListener(new MyTabListener(this,2)));
actionBar.addTab(actionBar.newTab().setTet("Tab 3")
.setTabListener(new MyTabListener(this,3)));
}

@0verride
public booiean onCreate0ptionsMenu(Menu menu) {
// Ina o menu com os botes da action bar
getMenuInater().inate(R.menu.menu_main, menu);
// Searchview
Menultem searchltem = menu.ndItem(R.id.action_search);
Searchview searchview = (Searchview) HenuItemCompat.getActionView(searchltem);
searchview.set0nQueryTetListener(onSearch());
// ShareActionProvider
Menultem shareltem = menu.ndItem(R.id.action_share);
ShareActionProvider share = (ShareActionProvider)
Henultemtompat.getActionProvider(shareltem);
share.setShareIntent(getDefau1tIntent());
return true;
}

Como o exemplo que fizemos utiliza a navegao por tabs, precisamos ajustar
os imports da classe MyTabListener para utilizar a action bar de compatibilidade e
tambm a verso de compatibilidade da classe FragmentTransaction. Vamos estudar
mais detalhes sobre a classe FragmentTransaction no captulo 8, sobre fragments.

MyTabListener.java

import android.support.v7.app.ActionBar;
import android.support.v4.app.FragnentTransaction;
Captulo 5 I Action Bar e temas 145
public class MyTabListener implements ActionBar.TabListener {
// Mesmo cdigo aqui
}

Muito bem, estamos quase acabando. Para nalizar a migrao para a biblioteca
de compatibilidade, precisamos ajustar o arquivo XML de menu. No exem
plo que zemos utilizamos as tags android:showAsActon, android:actionVewClass e
androd:actionProvderC1ass para congurar os itens de menu e tambm o Searchview
e o ShareActionProvider.

O problema que as verses antigas do Android no conhecem essas tags, ento


precisamos adicionar o namespace "app" no XML e em vez de utilizar o atributo
como androd:showAsActon="a1ways" Vamos utilizar como app:showAsActon="always".

A seguir podemos visualizar as alteraes necessrias no arquivo de menu. Preste


muita ateno em como o namespace "app" foi utilizado e veja que tambm estamos
utilizando as classes android.support.v7.widget.SearchVew e android.support.v7.widget.
ShareActionProvder da biblioteca VZ

/res/menu/main.xmI
<menu xmlns:android="http://schemas.androd.com/apk/res/android"
xmlnsztools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" tools:contet=".ManActvity">
<item androd:id="@+id/action_search"
android:icon="@drawable/c_acton_search" androd:title:"@string/action_search"
app:showAsActon="always"
app:actionVewC1ass="androd.support.v7.widget.Searchview" />
<item androd:id="@+id/action_share"
android:icon:"@drawable/ic_action_share" android:title="@string/action_share"
app:showAsActon="always"
app:actonProvderC1ass="android.support.v7.widget.ShareActonProvder" />
<item androd:id="@+d/action_refresh"
android:icon:"@drawable/c_action_refresh" android:title="@string/acton_refresh"
app:showAsActon="ifRoom" />
<item android:id="@+d/action_settings"
android:title="@string/action_settings"
app:showAsActon="never" />

Pronto! Isso tudo. Relembrando, zemos os seguintes passos para utilizar a


biblioteca de compatibilidade da action bar:
146 Google Android - 4 edio
1. Declarar a dependncia no arquivo app/buildgradle.
2. A activity precisa ser lha de androd.support.v7.app.AppCompatACtV>'
3. No cdigo da activity utilize 0 mtodo getSupportActonBar() para obter o
objeto androd.support.v7.app.ActonBar.

4. Ao congurar os itens de menu, utilize a classe androd . support.v4.view.MenuIternC0mDB

5. Utilize as classes de compatibilidade android.support.v7.wdget.SearchVew e


androd.support.v7.wdget.ShareActionProvider.

6. No arquivo XML de menu, utilize o namespace "app" pois as verses antigas do


Android no conhecem as tags showAsAction,actionVewC1ass e actionProvderClass.

Atualmente o Google recomenda utilizar as classes do pacote de compatibilidade,


pois a vantagem que essa biblioteca compilada junto com o cdigo do projeto,
e a biblioteca baixada pelo SDK Manager. Para qualquer melhoria ou correo
de bugs nessas classes basta atualizar a biblioteca pelo SDK Manager. j no caso
de uma biblioteca nativa, ela est naturalmente embutida dentro do sistema
operacional. Torna-se ento uma boa prtica utilizar sempre as bibliotecas de
compatibilidade; isso vem funcionado to bem que vrias classes so distribudas
apenas nessas bibliotecas. o caso do famoso componente ViewPager que ainda
vamos estudar, que ca na lib v4 e para o qual nem existe uma verso nativa.

Dica: ao criar um projeto no Android Studio com suporte ao Android 2.3


(API Level 9), a action bar de compatibilidade ser automaticamente congurada
no projeto.

5.13 Links teis

Para complementar sua leitura, seguem alguns links importantes da documen


tao ocial:
Android User Interface - Action Bar

http://developenandroid.com/guide/topics/ui/actionbart html
Android Training - Adding the Action Bar

https://developerandroid.com/training/basics/actionbar/index. html
Android Training - Styling the Action Bar

https://developerandroid.com/training/basics/actionbar/styling.html
, cAPruLo
it

Interface grca
tw gerenciadores de layout
\

No Android, existem diversos tipos de gerenciadores de layout. Alguns podem


organizar os componentes na horizontal e vertical, outros podem organizar os
componentes em uma tabela com linhas e colunas.
Neste captulo, aprenderemos a organizar os componentes da tela com o layout
desejado e construiremos diversos exemplos.

6.1 View

A classe androd.vew.Vew a classe-me de todos os componentes visuais do


Android, e suas diversas subclasses so utilizadas para criar a interface grca
do aplicativo. Cada subclasse de View precisa implementar o mtodo onDraw(Canvas),
responsvel por desenhar o componente na tela.
Voc deve ter percebido que muitas vezes, neste livro, chamamos uma view sim
plesmente de componente, para facilitar a leitura. Existem dois tipos de views/
componentes, os chamados Widgets e os gerenciadores de layout. Um widget
um componente simples que herda diretamente da classe View, como as classes
Button, Inagevew e Textvew. j os gerenciadores de layout consistem em subclasses
de androd.view.VewGroup e so popularmente chamados apenas de layouts.

6.2 (Iasse ViewGroup


Um gerenciador de layout utilizado para organizar a disposio dos componentes
na tela. A classe-me de todos os gerenciadores de layout a androd .vew.VewGroup.
Na gura 6.1, podemos visualizar a hierarquia das classes View e Viewroup, com
algumas de suas subclasses:

147
148 Google Android - 4 edio
J 'Garod.app.u:t|vlty _
ii ~ ' c G android.view.VIeW
0 rndvnewayldodz ht):ari-dro|d.v1ew.`v'ew ._.___ _ __________._ ,.._. _ _
o sctConter\tVlew(leyoutRoslD: inn. vozd o dzowtev- WW 0'*'"3""*)* "'d
O setCmtent\=rew(\-rew: androd.v1ew.v|ew): void N 7
,\;. _'|' t Q af-0d_vl0w.V|QWGI'OtD
G an: oe! ex view Q <5dl0|ll.\MdQEl.ll'l'l5QBV|BW
VA\
- _ G andzro|d.wrd9et.AbsoluteLayout - \
'B android.wldqet.Button G ondroid.w\doet.EdrtTet ~ G nd|ozd.wdqet.Rt-latrvetayout
G andro|d.w|d1et.FrarneLayout

G .zndozd.widoe=t.LmeafLwUf

G androd.wdqez.rableia~/out

Figura 6.1 - Hierarquia da classe Weu/Group.

Conforme visualizado na gura 6.1, as principais classes de layout so:


Layout Descriao g _ _ ,V
Abso1uteLayout Permite posicionar os componentes, fornecendo as coordenadas x
e y Est deprecated.
FrameLayout Tipo mais comum e simples de layout. Funciona como uma pilha,
sendo que uma view ca por cima da outra.
Li.nearLayout Utilizado para organizar os componentes na vertical ou horizontal.
TableLayout lho de LnearLayout e pode ser utilizado para organizar os com
ponentes em uma tabela, com linhas e colunas.
Re1ati.veLayout Permite posicionar um componente relativo a outro, por exemplo,
abaixo, acima ou ao lado de um componente j existente.

6.3 Congurando a altura e largura de uma view


Ao construir a interface grfica da tela, necessrio congurar a largura e altura
do layout principal, bem como a largura e altura de cada view inserida no layout.
Isso feito por meio dos parmetros androd:1ayout_heght e androd:1ayout width.
Parmetro Descrio
androd:1ayout_height Especfica a altura de un;;Q-~ *Hum W .`m_"
androd:1ayout_wdth Especica a largura de uma view
Captulo 6 n Interface grca - gerenciadores de layout 149
O trecho de cdigo a seguir mostra a congurao de largura e altura de um
LinearLayout.

<LnearLayout mIns:androd="http://schemas.android.com/apk/res/android"
androd:1ayout_wdth="natch_parent" androd:Iayout_heght="natch_parent"
android:orentaton="verticaI" >

Esses dois parmetros podem receber os seguintes valores:


Valor Descrio
fiII_pa rent Signica que o componente precisa ocupar todo o tamanho denido
por seu pai (layout). Isso deve ser utilizado sempre que algum layout
ou view precisa ocupar a tela inteira ou todo o espao de layout
denido pelo layout-pai.
natch_pa rent Idem ao fiII_parent. Na verdade, o fiII_parent virou deprecated no
Android 2.2. Se voc vai criar aplicaes para Android 2.2 ou superior,
poder utilizar o match_parent. Ambas as notaes tm o mesmo fun
cionamento, e o Google apenas descontinuou a notao U._parent.
wrap_content Utilizado para o componente ocupar apenas o tamanho necessrio
na tela, sem esticar.
nmero (dp) Nmero inteiro especicando o tamanho, por exemplo, 50dp para
ocupar 50 pixels da tela. A notao dp (density independent pixel) faz
a converso correta de pixels conforme a densidade/ resoluo da tela
do dispositivo. Nunca utilize a notao 50px, sempre utilize 50dp para
garantir que o aplicativo funcione bem em diversos tamanhos de telas.

Os parmetros androd:Iayout_heght e androd:Iayout_wdth so denidos pela classe


interna ViewGroup.LayoutParans. Se voc construir a tela utilizando diretamente a API
Java, ser necessrio conhecer essa classe. Caso contrrio, isso no obrigatrio.
Nos prximos tpicos veremos na prtica como congurar a largura e altura do
layout e de suas vievig e explicaremos detalhadamente todos os gerenciadores de
layout do Android.

6.4 Entendendo as constantes wrap_content e match_parent


Neste tpico, vamos criar alguns exemplos para voc entender o signicado das cons
tantes wrap_content e match_parent, utilizadas para definir o tamanho do layout e das views.

Nota: para testar os exemplos crie o arquivo XML de layout no projeto, e faa a
pr-visualizao do layout no editor visual. No ser necessrio executar o cdigo.
Ou, se preferir, abra o projeto deste captulo no Android Studio e abra cada arquivo
de layout no editor, assim car mais fcil para acompanhar as explicaes.
150 Google Android - 4 edio
Nesses arquivos de layout, vamos escolher FrameLayout como tag raiz, mas isso
na verdade nao importa. O primeiro exemplo demonstra >FFf'1@L>'0U Uflllfmd
(vsatrihtiuwsandroid:1ayout_widthtrandrod:1ayout_heightxnimdrwraD_Ctt-l5U
significa que a altura e largura d layout sera exatamente o espaco I1CCCSS8l`l()
para conter todos os componentes/views definidos na tela.

/res/layout/exempIo_wrap_content.mI
<?m1 version="1.0" encoding="utf-8"?>
<FrameLayout m1ns:android="http://schemas.androd.com/apk/res/androd"
androd:1ayout_width="wrap_content" androd:1ayout_heght="wrap_content"
android:background="#8B8B83" >
<ImageVew
android:1ayout_wdth="wrap_content" android:1ayout_heght="wrap_content"
androd:src:"@drawab1e/android_green" />

Nota: sc a altura e largura de um layout forem especicadas como wrap_content,


o tamanho desse layout ser denido pelo tamanho necessrio para desenhar
todos os seus componentes.

Nesse exemplo, o Image-View utiliza o valor wrap_content para denir sua altura e
largura, consequentemente a imagem ocupa somente o tamanho necessrio. A
gura 6.2 mostra a pr-visualizao deste layout no editor.

Figura 6.2 - l~xcmpl de wrap_cnten_


Captulo 6 i Interface grca - gerenciadores de layout 151
Observe que o fundo cinza atrs da imagem mostra o tamanho ocupado pelo
layout principal, que nesse caso o mesmo do tamanho da imagem. O restante
da tela ca com fundo branco, pois o tema padro do projeto.

Nota: sempre que car em dvida sobre qual o tamanho que o layout est
ocupando, utilize o atributo androd:background para denir uma cor para o fundo.
Neste caso estou utilizando a cor cinza, assim possvel visualizar a rea
retangular ocupada pelo layout.

No prximo exemplo, vamos alterar a altura e largura do layout principal para


match_parent para fazer com que ele preencha a tela inteira.

/res/layout/exempIo_match__parent.xmI
<?xm1 verson="1.0" encodng="utf-8"?>
<FrameLayout m1ns:androd="http://schemas.androd.com/apk/res/android"
androd:1ayout_width="match_parent" android:1ayout_height="match_parent"
androd:background="#8B8B83" >
<ImageVew
android:1ayout_width="wrap_content" androd:1ayout_heght="wrap_content"
androd:src="@drawable/androd_green" />

A gura 63 mostra que desta vez o layout com fundo cinza ocupou a tela inteira e a
imagem ocupou apenas um pequeno espao necessrio para que fosse desenhada.

Figura 6.3 - Exemplo match_parent.


152 Google Android - 4* edio
,. rt ~ r, . " - ' w wra content faz
L ,omo podemos ver o 11_parent ou match_parent esttcam a new. L D
com que a view ocupe somente o espao necessario.

... .. -. ~.
~ -. z; ~~
' ' *' zhr* uma
7 `ilm*nte.
Dica: um atalho interessante do Android Studio c o Shtft+Sh1ft, qu* l
Janekapanivocechguarcuuquerrnnnechranquni)paral0LJh2 k)3

Agora vamos alterar tambm a largura e altura da imagem para I'1'CCh_Df@'f- 1550
signica que ela deve esticar e ocupar o tamanho ocupado por seu pal.

a- /res/layout/exempIo_match_parent_imagem.xml

<?xm1 verson="1.0" encodng="utf-8"?>


<FrameLayout m1ns:androd="http://schemas.androd.com/apk/res/androd"
androd:1ayout_wdth="match_parent" androd:1ayout_heght="match_parent"
android:background="#8B8B83" >
<ImageVew
android:1ayout_wdth="natch_parent" androd:1ayout_height="natch_parent"
androd:src="@drawable/androd_green" />

O resultado dessa alterao pode ser visto na gura 6.4. Sempre que usar o valor
match_parent, os componentes vo esticar/expandir para preencher 0 tamanho do
layout-pai. Mas tome cuidado com imagens, pois geralmente elas devem ser dc
nidas como wrap_content, justamente para no distorcer a figura.

Figura 6.4 - Exemplo com a imagem c5rian10_


Captulo 6 I 'Interface grca - gerenciadores de layout 153
Em linhas gerais, recomendado que a largura e altura do layout principal sejam
denidas como match_parent para ocupar a tela inteira. Se necessrio, congure a
cor de fundo do layout para ter certeza do tamanho que ele est ocupando. Ao
congurar a altura e largura para cada view da tela, possvel combinar os valores
match_parent e wrap_content para expandir os componentes somente na vertical ou
horizontal, conforme necessrio.
Para voc entender melhor como funciona o match_parent e wrap_content, vamos criar
outro exemplo. Desta vez vamos utilizar o componente EdtText, que representa
um campo para o usurio digitar algo.

/res/layout/exempIo_textview_wrap_content.xmI
<?ml verson="1.0" encodng="utf-8"?>
<LnearLayout xm1ns:androd="http://schemas.androd.com/apk/res/androd"
android:1ayout_width="match_parent" androd:1ayout_height="match_parent"
androd:paddng="10dp" androd:orientaton="vertca1" >
<TetVew

androd:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content"
androd:tet="@strng/nome" />
<EditText
androd:1ayout_width="wrap_content" androd:1ayout_height="wrap_content"
android:nputType="tet" />
<BU'C'C0n

androd:layout_wdth="wrap_content" androd:1ayout_heght="wrap_content"
android:1ayout_gravity="right" androd:text="@strng/ok" />
</LnearLayout>

A gura 6.5 mostra a pr-visualizao desse layout. Observe que o campo de


texto ocupou somente o espao necessrio, pois sua largura foi denida com
android:layout_width="wrap_content" e no existe nenhum texto digitado. medida
que o usurio digitar algo, esse campo vai expandir automaticamente, o que pode
no ser o desejado.

Figura 6.5 - Campo de texto com wrap_content.


154 Google Android - 4 edio
.\ruaias pn^tairusuiatk\ veia qtufrilaywiut e utu LinearLay0Ut f<ll***f"l<*
Y3i
\'ertieal. o qual liaz com que eada view seia adieiouada lo;o al aixo da outra ver
tiealnieute.(3tura etutvaekidt'e.urihtutiandrod:layout_grVy="F9h"Itlotati
que lax. eom ele seia posieionado ua direita.
lara eorrigir o layuitJesse siniples rniulario.\ Nifi ^\'l"ff " L
ruira th eatuivo ele texttx o seja. a \1e\v EdtTet.lss e leito ewiui atribtiui
androd:1ayout_wdth="match_parent" tiara tpie stia laiyuara tvreeaielia tuJt esrxigti
tlisw\i1i\w:l tll;i}wL1t-twai.

/res/layout/exempIo_textview_wrap_content.xmI
<?xml version="1.0" encodng="utf-8"?>
<LinearLayout xmlns:androd="http://schemas.androd.com/apk/res/androd"
android:1ayout_wdth="match_parent" android:1ayout_heght="match_parent"
androd:paddng="10dp" androd:orentation="vertcal" >
<TextView
android:layout_width="wrap_content" androd:layout_height="wrap_content"
androd:tet="@strng/nome" />
<EdtTet
androd:1ayout_wdth="natch_parent" androd11ayout_heght="wrap_content"
androd:nputType="tet" />
<Button
android:1ayout_wdth="wrap_content" android:1ayout_heght="wrap_content"
androd:1ayout_gravty="rght" androd:tet="@strng/ok" /

A figura bb mostra a r~-muziiztzti do layout. e dessa vez o eampo de texto


esueotiualarguraxu11oe1uxu'uxJottaniauluiehspeniuxd.Lbserveiqueidezupenas
estuxiutiaIargtu1r,pustitiniexeuiosiiatxiufuguraeatweh:altura,;1epialtx)utuiua
com wrap_content. (omo exereieio, voe pode estiear o eampo de texto ua altura
txutiverriqturaeonteee

Fgunibb-(Mnqnnh'uwhunninuuh_unnwHruthuuuni
Captulo 6 I Interface grca - gerenciadores de layout 155
Note que no adicionamos valores xos para o tamanho, pois recomendado
criar telas que se ajustam automaticamente conforme a resoluo. Por isso no
importa se o aplicativo vai executar no smartphone, tablet ou numa gigante TV
que o layout ser o mesmo.

6.5 Framelayout
A classe androd.wdget.FrameLayout o mais simples de todos os gerenciadores de
layout e utilizada para empilhar uma view sobre outra.
possvel adicionar vrios componentes dentro do F rameLayout, e sempre os ltimos
componentes caro sobre os anteriores, seguindo o conceito de uma pilha, em
que o ltimo elemento ca no topo. O caso mais comum disso para inserir um
ProgressBar por cima de alguma outra view:A propsito, a classe ProgressBar uma view
que desenha aquela bolinha que ca girando para simular algum processamento.
Para exemplicar, vamos inserir um ProgressBar por cima do boto OK do formulrio
do exemplo anterior. Dessa forma, ao clicar no boto podemos disparar a animao
do Prog ressBar para simular o processamento de alguma tarefa. Vamos aprender
como fazer isso no cdigo depois, por enquanto vamos estudar apenas os layouts.

/res/layout/exempIo_frame_Iayout_1.xml
<?m1 version="1.0" encodng="utf-8"?>
<LnearLayout xmlns:androd="http://schemas.androd.com/apk/res/androd"
androd:layout_wdth="match_parent" androd:layout_heght="match_parent"
androd:orentaton="vertca1" androd:paddng="19dp" >
<TetVew androd:1ayout_wdth="wrap_content" androd:layout_height="wrap_content"
androd:tet="@strng/nome" />
<EdtText androd:1ayout_wdth="match_parent" androd:1ayout_heght="wrap_content"
androd:inputType="tet" />
<FrameLayout android:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content" >
<Button
androd:layout_wdth="wrap_content" androd:1ayout_heght="wrap_content"
androd:1ayout_gravty="rght" androd:text="@string/ok" />
<ProgressBar androd:Iayout_width="wrap_content" androd:1ayout_heght="wrap_content"
androd:1ayout_gravty="center" />

</LnearLayout>

A gura 6.7 mostra a pr-visualizao desse layout. Talvez na gura no que


visvel, mas eo ProgressBar to crculo animado que est sobre o boto. justamente
isso que o *FrameLayout faz, ele adiciona uma view sobre a outra, como uma pilha.
156 Google Android - 4 edio

* -s.,
z

Figura 6.7 - FrameLayout com um ProgressBar

Nota: vamos estudar mais sobre os componentes visuais no prximo captulo;


no momento preocupe-se apenas com os gerenciadores de layout. Apenas
por curiosidade, o ProgressBar ao ser inserido no layout vai exibir a animao
automaticamente. Para parar a animao, voc deve esconder o ProgressBar com
o mtodo setVsib1e(boo1ean) definido na classe androd.vew.Vew.

Outro caso comum de utilizao do FrameLayout com o ProgressBar quando temos


uma lista na tela, como por exemplo a lista de contatos da agenda. Como boa
prtica de programao, recomendado que, durante o carregamento dos dados
da lista, o ProgressBar seja utilizado para exibir uma animao para o usurio. O
seguinte layout mostra um Lstvew, que o componente que exibe uma lista e
no centro um ProgressBar para mostrar a animao.

/res/layout/exempIo_frame_Iayout_2.mI
<?xm1 verson="1.0" encodng="utf-8"?>
<FrameLayout xmlns:androd="http://schemas.android.com/apk/res/androd"
androd:1ayout_wdth="match_parent" androd:1ayout_heght="match_parent"
androd:orientaton="vertca1" androd:paddng="10dp" >
LStVew
androd:d="@+d/Istvew"
androd:1ayout_wdth="match_parent" androd:1ayout_heght="match_parent" />
ProgressBar
android:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content"
androd:1ayout_gravity="center" />

A figura 6.8 mostra a pr-visualizao desse layout. O editor mostra urna lista para
simular que o Lstvew est preenchido. j o ProgressBar utilizado para mostrar a
animao para o usurio, enquanto os dados da lista esto sendo carregados. O
ProgressBar est por cima do Lstvew, pois isso que o FrameLayout faz_
Captulo 6 I Interface grca - gerenciadores de layout

ltm 1
o..
mzrl THY K

R2_
fzti ima Z

Item 3
`S|.'l' i
.lif Q*

lte-m 4
sua trr'n -1

Item 5
tltl Hr-m S

'Item 5
au: mais l

Item 7

Figura 6.8 - FrameLayout com um LzstV1ew e ProgressBar

6.6 LinearLayout
A classe androd .wdget. LinearLayout um dos gerenc1adores de layout ma1s utilizados
sendo possvel organizar os componentes na horizontal (padrao) ou na vertlcal
A orientao, nesse caso, configurada pelo atr1buto androtd ortentatton
A seguir temos um exemplo de como utilizar a classe L1neacLayout

/res/layout/exemplo_linear_layout_1 xml
<?xnl verslon="1.0" encodng="utf-8"?>
<LnearLayout xnlns:androd="http://schenas androtd com/apk/res/androtd
androd:layout_wdth="natch_parent" androtd layout hetght match parent
androd:ortentation="horlzontal ou verttcal
androd:paddng="10dp" >
<ImageVew androd:src="@drawable/androtd blue
androd:layout_wdth="wrap_content androtd layout hetght wrap content
androld:contentDescrpton="@strng/content descrtptton /
<InageVew androd:src="@drawable/androtd green
androd:layout_wldth="wrap_content androtd layout hetght wrap content
androd:contentDescrpton="@string/content descrtptton /
Google Android - 4 edio

^A
158

~ ' II ~ u ` ` I ' ' . :H lp H.


A figura 6.9 exibe a pr-visualizao desse layout, priml
ro cm a configurao
andro1d:or1entat1on= horizontal eaoladocomaconfiguraaoandrotd.or1enta'C10 VG 61

''IPI|
Pa|e[[e- 'UPene
V' N Of! ' Vl ev2palee
Pxus NexusV One
_ ' ll
exem0l0_l|near_laY0ut_1 xml 2 ' 0mDl0-l''UY0Ul- 1 *ml i

Form Widgets Cl lffi' Fi , ~ Form WWF lr-l 'J


*W l*~t*.'!3v At- Teirtvuew

^~ Larue lex? l'L~ Large Text

' ^.~l (hum left fm) Medium Text

I'I
Ab Small Text
Small Text
l* Button
Button ;~ vw

Q .:'l.

'* Small Button Small Button

.r Text Fields
. Toczqle8utton

3 V
fl cneciB0
Lv~\= _.
C recl<8o
ToggleButton gi z?

Figura 6.9 - LinearLayout na horizontal e vertical.


O funcionamento do LnearLayout bem simples e no tem muito o que explicar.
Apenas lembre-se de que, caso o atributo androdzorentaton seja omitido, 0 padro
horizontal.

6.7 Linearlayout - controle do alinhamento "Iayout_gravity"


Agora demonstraremos como alinhar os componentes de forma centralizada, na
esquerda ou direita da tela. Para isso, usaremos 0 atributo androd:layout_gravty.
Os valores vlidos para esse atributo so top (cima), bottom (baixo), left (esquerda)
right (direita), center_vertcal, fill_vertical, center_horzontal, fill_horzontal, center c fill.
Anteriormente, no exemplo do formulrio com o Franelayout e o ProgressBar, utili
zamos o seguinte cdigo:
<ProgressBar
androd:layout_wdth="wrap_content" androd:layout_heght="wrap_content"
android:layout_gravty="center" />

Repare que o ProgressBar est declarado com o atributo androd :layout gravty="center",
o qual faz com que ele seja posicionado no centro do seu layout-pai. Para demons
trar outras maneiras de utilizar o atributo androdzlayout gravty, criaremos uma
Q ue
tela com trs imagens inseridas na vertical, a in a as
cam l` hna
d esquerda, no
centro e na direita da tela.
Captulo 6 I Interface grca - gerenciadores de layout 159
/res/layout/exempIo_Iinear_Iayout_2_gravity.xmI
<?xm1 verson="1.0" encodng="utf-8"?>
<LnearLayout xmlns:android="http://schemas.android.com/apk/res/androd"
android:1ayout_wdth="match_parent" androd:1ayout_height="match_parent"
android:orentaton="vertica1" >
<ImageVew
androd:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content"
android:1ayout_gravity="1eft" androd:src="@drawable/androd_green" />
<InageVew
android:1ayout_wdth="wrap_content" android:1ayout_heght="wrap_content
androd:1ayout_gravty="center" androd:src="@drawab1e/androd_b1ue" />
<ImageVew
android:1ayout_width="wrap_content" android:1ayout_height="wrap_content"
android:1ayout_gravty="right" androd:src="@drawab1e/androd_green" />

A gura 6.10 exibe as imagens alinhadas esquerda, no centro e na direita con


forme esperado.

Figura 6.10 - Controlando 0 alinhamento com 0 atributo layout _gra1/ity.

6.8 LinearLayout - controle do peso


Outra forma de organizar os elementos na tela atribuir um peso (porcentagem)
para cada um. O componente com o maior peso ocupar o maior espao na tela.
Para isso podemos utilizar o atributo android:1ayout_weight.
Para demonstrar isso, criaremos um exemplo com um formulrio, que contm
os campos nome, email e observaes. Nesse exemplo o campo observaes
deve ocupar a rea restante da tela para que o usurio possa digitar um texto um
pouco maior. Por isso foi definido o peso = 1 para esse componente utilizando o
atributo android:1ayout_weght="1".
160 Google Android - 4 edio
f1 /res/layout/exempIo_Iinear_Iayout_3__weight.mI

<?m1 verson="1.0" encodng="utf-8"?>


<LnearLayout m1ns:androd="http://schemas.androd.com/apk/FGS/3dfd"
androd:orentaton="vertca1"
androd:1ayout_wdth="match_parent" androd:1ayout_heght="match_D3f@"" >
<TetVew
androd:1ayout_wdth="wrap_content" androd:1ayout_heght="wraD_C"t@"t"
androd:tet="Nome" />
<EdtTet
androd:1ayout_wdth="match_parent" androd:1ayout_heght="wrD_C0t@t
androd:tetCo1or="#ff0000" />
<TextVew
androd:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content
androd:tet="Ema1" />
<EdtTet
androd:1ayout_wdth="match_parent" androd:1ayout_heght="wrap_content" />
<TetVew
androd:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content"
androd:text="0bservaes" />
<EdtTet
androd:layout_wdth="match_parent" androd:1ayout_height="0dp"
androd:1ayout_weght="1" />
<Butt0n
androd:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content"
androd:text="Envar" />
</LnearLayout>

A gura 6.11 mostra a pr-visualizao desse layout. Observe que o campo ob


servaes ocupou o restante da tela. Isso ocorreu porque o campo observaes
foi denido com o atributo androd:layout_weght="1" e androd:1ayout_heght="9dp".
Como ele o nico componente que tem peso, esticou na altura.

Nota: sempre que utilizar o peso com o atributo androd:1ayout_weght, deve-se


denir a largura ou altura da view com Gdp. Essa notao indica que a largura
ou altura da view deve respeitar o peso atribudo.

Sempre que apenas um componente na tela precisar ocupar o tamanho restante,


basta atribuir o valor 1 para o atributo android:1ayout_weght, como acabamos de
vericar. Mas o que acontece se for necessrio expandir mais de um componente
Para facilitar a explicao criaremos um novo exemplo, com trs campos de texto.
l
Captulo 6 n Interface grca - gerenciadores de layout 151

E1
Enviar
2

Figura 6.11 - Exemplo de layout_weight com peso = 1.

/res/layout/exempIo_linear_Iayout_4_weight.xmI
<?xm1 version="1.0" encodng="utf-8"?>
<LinearLayout xmlns:androd="http://schemas.androd.com/apk/res/androd"
androd:orentaton="vertica1"
androd:layout_wdth="match_parent" android:layout_heght="match_parent" >
<EdtTet.androd:1ayout_weght="1"
andrd:layout_wdth="match_parent" android:1ayout_height="0dip"
android:text="Texto (weght=1)" />
<EditTet android:1ayout_weght="2"
androd:1ayout_wdth="match_parent"
android:1ayout_height="0dip"
android:text="Texto (weight=2)" />
<EdtText androd:1ayout_weight="3"
android:layout_wdth="match_parent" androd:1ayout_height="0dp"
android:tet="Texto (weght=3)" />

Observe que cada EdtText define um valor diferente para o atributo


androd:1ayout_weight. O primeiro define o valor 1, o segundo o valor 2, e o terceiro
o valor 3. A gura 6.12 mostra a pr-visualizao desse layout. Como podemos
vericar, o campo de texto com o maior peso ocupou a maior rea da tela.
Lembre-se de que tambm a altura de cada componente foi denida com 0dp ou
Gdip, que a mesma coisa. Isso permite deixar a altura configurvel pelo peso que
esse componente tem. O mesmo conceito tambm se aplica largura.
162 Google Android - 4 edio

|'QI1O (vnil=2l

Iulo (miqti-3)

Figura 6.12 - Exemplo do atributo layout_u/eight para controlar o peso.

Para entender melhor o que aconteceu, vamos fazer uma superconta para somar
estes valores: 1 + 2 + 3 = 6. Como a soma dos valores do atributo 1ayout_weght ,
cada campo de texto vai ocupar o espao proporcional na tela, relativo ao total.
como se 6 fosse 1.000/0. Assim, podemos visualizar que o ltimo campo denido
como 1ayout_weght=3 ocupou metade da tela, sendo que 3 50% de 6.
Para entender melhor como a atribuio de pesos funciona, vamos brincar um
pouco com esse exemplo, alterando o cdigo-fonte do arquivo XML de layout.
Por exemplo, vamos alterar o primeiro campo de texto para peso = 3. Nesse caso.
agora a soma ficaria 3 + 2 + 3 = 8 (Figura .13). Como o primeiro e o terceiro
campo tm os mesmos pesos, eles ocuparo o mesmo espao na tela. j o campo
do meio ser o menor.

Para nalizar este tpico, vou dar uma dica muito importante e que muitos desen
volvedores Android demoram a descobrir ou entender. O componente Lstvew que
utilizado para criar listas deve ser utilizado na maioria das vezes com peso = 1
na vertical para esticar a sua altura.
<LstVew
androd:d="@+d/Iistvew"
androd:1ayout_wdth="match_parent"
androd:1ayout_heght="@dp" androd:1ayout_weght="1" />
Captulo 6 n Interface grca - gerenciadores de layout 153
A diferena que, se congurarmos a altura como androd : layout_heght="match_parent",
a lista vai esticar sem pensar em quem est abaixo dela, mandando todas as outras
views para fora da tela. Mas com a configurao do peso, o Ltstvew vai esticar
at onde puder, pois geralmente somente ele tem o peso = 1, ou seja, somente o
Lstvew deve esticar. medida que formos avanando na leitura deste livro, vamos
aprender mais detalhes e voltamos a revisar este conceito.

Y mw (weight =3}

Texto (wegm<=2} 3

Texto (wegzm=3}

Figura 6.13 - Exemplo do atributo layout_u/eight para controlar 0 peso.

6.9 Tablelayout - uso de uma tabela com linhas e colunas


A classe androd.wdget.Tab1eLayout um dos layouts mais teis para construir al
gumas telas, como por exemplo formulrios. Cada linha da tabela formada por
um and rod.wdget.Tabl.eRow, que uma subclasse de LnearLayout e consequentemente
pode conter outros componentes, em que cada um representa uma linha na tabela.
O TableLayout tem os atributos androd:stretchColumns e androdzshrnktolumns, os quais
recebem os ndices das colunas, separadas por vrgula, que devem ser alteradas.
Por exemplo, pode-se informar para o atributo androd:stretchColumns os valores
2,3 para alterar apenas as colunas de ndice 2 e 3. Observe que o ndice inicia
em zero, de modo que nesse caso as colunas 3 e 4 sero alteradas.
Veja a seguir a denio de cada atributo:
164 Google Android - 4 edio
android:stretchCo1umns - Faz com que as colunas ocupem O spag d15P0mVl
na tela, expandindo-as. Use esse atributo quando for necessario que uma
coluna ocupe a linha inteira. O funcionamento como um coispan de uma
pgina HTML.
androidzshrinktolumns - Faz com que as colunas especicadas sejam sempre
exibidas na tela. Caso o valor do texto seja muito grande e que para fora da
tela, a linha quebrada e o texto exibido em vrias linhas na mesma coluna

6.10 TabIeLayout e shrinkCo|umns - contrao de colunas


O atributo android : shrinkCo1umns recebe o nmero das colunas que preciso contrair,
ou seja, fora o contedo da coluna para car dentro da tabela. Esse recurso deve
ser utilizado quando o componente de uma coluna longo demais.

/res/layout/exempIo_tab|e_Iayout_shrink.xm|
<Tab1eLayout xmins:android="http://schemas.android.com/apk/res/android"
android:1ayout_width="match_parent" android:1ayout_height="match_parent"
android:shrinkCo1umns="2">

<TetView android:tet="Co1una 1" />


<TetView android:tet="Co1una 2" /

<TetView android:tet="Co1una 1" />


<TetView android:text="Co1una 2" />
<TetView android:text="Texto Grande que vai sair da tela mas o shrinkCo1umns=2 foi
utilizado para quebrar. " />

<TetView android:text="Co1una 1" />


<TextView android:text="Co1una 2" />
<TetView android:text="Coiuna 3" />

Neste exemplo, a coluna 2 da segunda linha (lembre-se de que o ndice da colu


na C0m8 m 0) tem Um texto muito grande. O atributo android:shrinkCo1unns foi
usado para forar seu contedo a ser exibido na tela (Figura 6.14). Dessa fQfm3_ 0
texto foi quebrado e consequentemente foi necessrio utilizar mais de uma linha.
Captulo 6 n Interface grca - gerenciadores de layout 165

Coluna 1CoIuna 2 _v__~_.__m___~~__W___


Coluna 1 Coluna exto Grande que vai sair da
aew um shri=nkCoIumns=2

eu -_c_,_13_33_9.12s9_U_?L$l Li
Coluna ICo|una 2CoIuna. 3

Figura 6.14 - TableLayout com shrin/cC0lumns.

6.11 Tablelayout e strechCoIumns - expanso de colunas


O atributo androd:stretchColumns recebe o nmero das colunas que precisam ser
expandidas (forar o preenchimento da tela inteira).

/res/layout/exempIo_tabIe_layout_stretch.xmI

<Tab1eLayout xmlns:androd="http://schemas.android.com/apk/res/androd"
androd:1ayout_wdth="match_parent"
androd:layout_heght="match_parent"
androd:stretchCo1umns="1" >

<TetVew android:text:"@strng/lsta_de_produtos" />


<Vew

android:1ayout_heght="2dp"
androd:background="#FF90909@" />

<TetVew androd:tet="@strng/produto_a" />


<TetVew

android:layout_gravty="rght"
androd:text="@string/reas_100" />

<TetVew androd:tet="@strng/produto_b" />


<TextView

androd:layout_gravty="rght"
androd:tet="@strng/reas_200" />

<TextVew androd:tet="@strng/produto_c" />


<TetVew
166 Google Android - 4 edio

androd:1ayout_gravty:"rght"
androd:tet="@string/reais_300" />

<Vew

androd:1ayout_heght="2dp"
androd:background=#FF909090" />
<LnearLayout
androd:1ayout_wdth="wrap_content"
androd:1ayout_heght="match_parent"
androd:gravty="bottom|center_horzonta1" >
<Button
androd:1ayout_wdth="wrap_content"
androd:1ayout_heght="35dp"
android:text="@strng/cancelar" />
<Button
androd:1ayout_wdth="wrap_content"
androd:1ayout_heght="35dip"
androd:tet="@strng/comprar" />
</LnearLayout>

A pr-visualizao desse layout pode ser vista na gura 615.

-.

Cancvm Comum

Figura 6.15 -'I`ab1I-ayut com strctchColumns.

Observe que o tamanho da segunda coluna 6 mai r >


que o daprimeirajustamente
pelo atributo androd:stretchColumns estar con
*urado.V
ej 1 t nn1em
-b que o atributo
Captulo 6 I Interface grca - gerenciadores de layout 157
androd:1ayout_gravty=" right" usado para posicionar os valores da segunda coluna
direita da tabela. Os botes na parte inferior da tela esto centralizados, pois
o LinearLayout est com a congurao e androd:gravity="botton|center_horizonta1".
Tambm possvel adicionar outros componentes (views) na tabela, no somente
o TableRow. Caso outro componente seja adicionado na tabela ele ocupar a linha
inteira. Veja que esse exemplo demonstrou a integrao entre dois layouts dife
rentes, LinearLayout e TableLayout.

Nota: um gerenciador de layout tambm um tipo de View e por isso possvel


inserir um layout dentro de outro para criar interfaces mais complexas. Esse
conceito chamado de layouts aninhados.

6.12 Tablelayout - criando um formulrio


Um formulrio com o Tab1eLayout similar a um formulrio HTML. Cada Tab1eRow repre
senta uma linha, e cada componente, uma coluna. Neste exemplo a segunda coluna foi
congurada para expandir seu contedo, utilizando o atributo android : stretchCo1umns="1"
(lembre-se de que o ndice comea em O). Dessa forma, os campos do login e senha
da segunda coluna ocuparo todo o espao restante da linha.

/res/layout/exempIo_table_layout_form.xml
<?ml version="1.0" encoding="utf-8"?>
<Tab1eLayout xmins:android="http://schenas.android.con/apk/res/android"
android:1ayout_width="match_parent" android:1ayout_height="match_parent"
android:stretchCo1umns="1">

<TextView android:text="Usurio: " android:padding="3dip" />


<EditTet android:id="@+id/canpoLogin" android:padding="3dip" />

<TextView android:text="Senha: " />


<EditText android:id="@+id/campoSenha" android:inputType="textPassword" />

<TableRow android:gravity="right">
<Button android:id="@+id/login" android:text="Logn" />
168 Google Android - 4 edio
Lihserve qturziiihinia hria usa o atrvuto androd:graV1tY= flght Para al*
iihar o bcHtkrlogin direua.( can1pth:scr1a COHICH1 0 arrvuro
androd:nputType="tetPassword" para mostrar os no lugar do texto (Flgf -J.

Senha

Login

Figura 6.16 - TableLayout para a construo de um formulrio.

6.13 GridLayout
A classe androd.wdget.GrdLayout organiza as views em linhas e colunas; para isso
a view deve utilizar os atributos 1ayout_row e 1ayout_co1umn.

No exemplo a seguir vamos criar quatro botes. Veja que o layout foi denido
com 2 linhas e 2 colunas e cada view inserida em determinada posio.

/res/layout/eemp|o_grid_Iayout.mI
<?m1 verson="1.0" encodng="utf-8"?>
<GrdLayout xm1ns:androd="http://schemas.android.com/apk/res/androd"
androd:1ayout_wdth="match_parent" androd:1ayout_height="match_parent"
android:padding="16dp"
androd:co1umnCount="2" android:rowCount="2">
<Button

android:1ayout_wdth="wrap_content" androd:1ayout_height="wrap_content"
android:1ayout_co1umn="0" androd:1ayout_row="0"
android:tet="Boto 1" />
<Button

androd:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content"
android:1ayout_co1umn="1" androd:1ayout_row="6"
androd:tet="Boto 2" />
Captulo 6 n Interface grca - gerenciadores de layout 159
<Button
androd:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content"
androd:Iayout_co1umn="0" androd:1ayout_row="1"
androd:tet="Boto 3" />
<Button
androd:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content"
androd:1ayout_co1umn="1" androd:1ayout_row="1"
androd:tet="Boto 4" />
</GrdLayout>

O GrdLayout tambm contm alguns atributos que no usei nesse exemplo, como
os atributos androd:1ayout_co1umnSpan e androd:1ayout_rowSpan, os quais podem ser
utilizados para que a view ocupe mais de uma coluna ou linha, de forma similar ao
span em pginas I-ITML. Voc tambm pode usar o atributo androd:1ayout_gravty
para informar se a view deve esticar na vertical, horizontal ou ambas (fi11_vertca1,
11_horzonta1 e 11). O resultado do exemplo pode ser visualizado na gura 6.11

.............
,mni i-aowz_
*sim

Figura 6.17 - GridLayout organizando as views em linhas e colunas.

importante ressaltar que o GridLayout s est disponvel a partir do Android 4.0


(API Level 14), mas felizmente podemos utilizar a biblioteca de compatibilidade
compatvel com o Android 2.1 (API Level 7). Para isso basta adicionar a seguinte
dependncia no arquivo app/build.gradle:
comp1e 'com.androd.supportzgrdlayout-v7:21+'

Feito isso, podemos utilizar a classe androd . support.v7.wdget.GrdLayout. Observe que


por questes de compatibilidade, obrigatrio utilizar o prexo app nos atributos
do layout, pois eles no so reconhecidos nas verses anteriores do Android.

/res/layout/exempIo_grid_|ayout.xmI
<?xm1 version="1.0" encodng="utf-8"?>
<android.support.v7.widget.GrdLayout m1ns:androd="http://schemas.androd.com/apk/res/androd'
xmlns:app="http://schemas.androd.com/apk/res-auto"
androd:1ayout_width="match_parent" androd:1ayout_height="match_parent"
170 Google Android - 4 edio
androd:padding="16dp"
app:co1umnCount="2" app:rowCount="2">
<BUtt0n
androd:1ayout_width="wrap_content" androd:1ayout_height="WF3P_C"tt"
androtd:tet="Boto 1"
app:1ayout_co1umn="0" app:1ayout_row="0" /

</androd.support.v7.widget.GridLayout>

6.14 Relativelayout
A classe androd.widget.Re1atveLayout pode posicionar os componentes ao lado,
abaixo ou acima de outro componente j existente. Para isso necessrio denir
um id para cada componente da tela, pois o posicionamento de um componente
depende de outro. Os seguintes atributos podem ser utilizados para informar a
posio do novo componente inserido relativo ao componente j existente:
Atributo Descrio
anroztzyoutzbiori Posiciona abaixo do componente indicado.
androd/Iayoutzabove Posiciona acima do componente indicado.
android:1ayout:toRght0f Posiciona direita do componente indicado.
androd/1ayout:toLeftOf Posiciona esquerda do componente indicado.
androd:1ayout_a1gnParentTop Alinha no topo do layout-pai.
android:1ayout_a1ignParentBottom Ainha abaixo do layout-pai.
android:1ayout_a1gnParentRght Alinha direita do layout-pai.
android:1ayout_a1ignParentLeft Ainha esquerda do layout-pai.
android:1ayout_a1ignTop Alinha no topo do componente indicado.
androd:1ayout_a1gnBottom Ainha abaixo do componente indicado.
androdzlayout a1ignRight Alinha direita do componente indicado.
androidzlayout a1i.gnLeft Ainha esquerda do componente indicado.
androd:1ayout_margnTop Utilizado para denir um espao na margem superior
do componente.
androidzlayout margnBottom Utilizado para denir um espao na margem inferior
do componente.
android:1ayout_marginRight Utilizado para denir um espao direita do compo
nente.

androdzlayout margnLeft Utilizado para denir um espao esquerda do com


ponente.
Captulo 6 I Interface grca - gerenciadores de layout

A seguir podemos visualizar um exemplo para construir um formulrio

/res/layout/exempIo_reIative_|ayout_form.xml
<?nl version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schenas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:background="#8B8B83" android:padding="16dp">
<TetView android:id="@+id/labelUsuario"
android:layout_width="55dip" android:layout_height="wrap_content"
android:tet="@string/usuario"/>

<EditText android:id="@+id/canpoUsuario"
android:layout_width="natch_parent" android:layout_height="wrap_content
android:background="@android:drawable/editbox_background"
android:layout_toRight0f="@id/labelUsuario"
android:inputType="text"/>

<TextView android:id="@+id/labelSenha"
android:layout_width="55dip" android:layout_height="wrap_content"
android:layout_below="@id/campoUsuario"
android:gravity="left" android:tet="@string/senha"/>

<EditText android:id="@+id/canpoSenha"
android:layout_width="natch_parent" android:layout_height="wrap_content"
android:background="@android:drawable/editbox_background"
android:layout_toRight0f="@id/labelSenha"
android:layout_alignTop="@id/labelSenha"
android:inputType="textPassword" />

<Button android:id="@+id/btLogin" android:layout_narginTop="10dp"


android:layout_width="wrap_content" android:layout_height="35dip"
android:layout_below="@id/canpoSenha"
android:layout_alignParentRight="true"
android:tet="@string/login" />

A pr-visualizao desse arquivo pode ser vista na gura 6.18.


172 Google Android - 4 edio

usuario

Senha

Lql

Figura 6.18 - Relativclyout para criar um irmulrio.


Consideraes sobre o exemplo:
1. O label Usurio e o primeiro componente,justamente por isso, posicionado
acima, alinhado fi esquerda.
2 O campo de texto Usurio foi alinhado direita do label Usurio, com o atributo
android : iayout_toRight0f="@id/iabeiusuario". Observe que o campo de texto utiliza
o atributo iayout_width="match_parent" para preencher o restante da tela.
3 O label Senha foi alinhado abaixo do campo Usurio, com o atributo
android : 1ayout_be1ow="@id/campoUsuario". Observe que o campo Usurio foi utilizado
como referncia, no o label Usurio. Isso foi feito porque a altura do campo e
maior do que a do label, sendo assim o campo Usurio era um ponto de referncia
melhor. Como fica a direita, foi necessrio alinhar o label Senha esquerda para
voltar margem da pgina. Isso foi feito com o atributo android:gravity="1eft".
4. O campo de texto Senha foi alinhado direita do label Senha.
5. O boto de Login foi inserido abaixo do cainpo de Senha, com o atri
buto android:iayout_beiow. Para alinhar a direita foi utilizado o atributo
android:iayout_aiignParentRight="true", relativ ao campo Senha. Para deixar
um pequeno espao (margem) entre a linha do campo Senha e o inicio
do boto, foi utilizado o atributo android:1ayout_narginTop="10dip" com o
valor de 1Odp. Tambm existem os atributos android:iayout_marginLeft e
android:iayout_narginRight com funcionamento semelhante. l
O ReiativeLayout bem flexvel ao construir as telas, permitindo que um compo
nente seja inserido, sempre relativo a outro j existente. Mas isso pode tambm
aumentar a complexidade da construo da tela, u ma vez que necessrio dominar
todos os atributos utilizados para controlar as posies em que os componentes
so inseridos. Uma desvantagem desse gerenciador de layout que, se a localiza
o de um componente for alterada, pode quebrar o layout de toda a tela pois U
posicionamento de um componente depende de outro 3 1
Captulo 6 I Interface grca - gerenciadores de layout 173
Esse layout adorado por alguns desenvolvedores e criticado por outros, ento ca
ber a voc decidir us-lo ou no. Saiba que o Google recomenda esse layout, pois
possvel criar com menos cdigo as mesmas telas que se fariam com muitas linhas
aninhando vrios LnearLayout com vertical e horizontal. Atualmente o editor visual
bem eciente ao fazer o drag and drop dos componentes e gerar automaticamente
todos esses atributos do Re1atveLayout; portanto, faa o teste no editor visual.

6.15 Absolutelayout (deprecated)


A classe androd.wdget.Abso1uteLayout permite controlar exatamente a posio
dos componentes, fornecendo suas coordenadas x e yr utilizando os atributos
androd:layout_x e androd: layout_y.

O AbsoluteLayout foi descontinuado (deprecated), pois o layout da tela pode car


diferente ou totalmente errado em dispositivos com diferentes resolues de tela.
Isso acontece porque 100 pixels em uma tela pode ser uma coisa, mas em outro
dispositivo pode ser outra, tudo depende da densidade e resoluo da tela de
cada dispositivo. Este breve tpico serve apenas para avis-lo para nunca utilizar
o Abso1uteLayout, portanto, nenhum exemplo ser demonstrado.

6.16 Utilizando layouts aninhados para criar telas complexas


Neste prximo exemplo vamos demonstrar como utilizar layouts aninhados.
Digamos que precisamos construir um formulrio, em que cada campo aparea
logo abaixo do outro na vertical. Contudo, na ltima linha necessrio exibir
dois botes: cancelar e login, mas eles precisam ser exibidos lado a lado.

/res/layout/exemplo_linear_layout_form_aninhado.xml
<?xnl verson="1.0" encoding="utf-8"?>
<LinearLayout xmlns:androd="http://schenas.android.con/apk/res/android"
android:orentation="vertica1"
android:layout_wdth="natch_parent" android:1ayout_heght="match_parent" >
<TetVew
android:layout_width="wrap_content" androd:layout_height="wrap_content"
androd:text="@strng/none" />
<EdtTet
android:layout_width="match_parent" android:1ayout_height="wrap_content"
android:textColor="#ff0000" androd:inputType="text"/>
<TetVew
174 Google Android - 4 edio
android:layoutmwidthz"wrapucontent" androd:layout_he9hf:"WfaD~Ctet"
androd:text="@strng/senha" />
<EdtTet androd:inputType="textPassword
androd:layoutwdthz"match_parent" android:layout_heght="WF8D_Ct@t" />
LinearLayout android:orentation="horizonta1"
androd:layout_wdth="match_parent androd:layout_h9h="Wf6D_C0@t"
androd:background="#cccccc" androd:gravty=center">
<Button androd:layout_wdth="wrap_content" androd:layout_height="wrap_content"
androd:text="@string/cancelar />
Button androd:1ayout_wdth="wrap_content" androd:layout_he9ht="WFD_C0"@"
androd:text="@strng/login" />
</LnearLayout
</LnearLayout>

A pre-visualizao dessc layout pode ser vista na figu ra (mil). () LinearLayout principal
da tela e vertical, mas no final foi utilizado um LinearLayout horizontal para comer
s dois lvotes. Observe que layut que contem os dois botes foi definido corn
uma cr de fundo cinza para demonstrar seu tamanho.

F@mu%-Umuuymtmmmr

6.17 Criao de um layout pela API - LinearLayout


(onformc ja estudamos, para criar telas n Android e possvel definir os layouts
em arquivos XMI., ou criar toda a tela usando a API ]ava, o que na maioria dos
cxtss |1 recxrrier1latlr

A seguir, sera fornecido urn exemplo de criacao de um formulrio utilizando a


Cl1SSU LHGBFLHYOU Smlllk' W111 il API Java. Para isso basta criar urna instancia
de LinearLayout e chamar o mtodo setContentVew(view). Assim como no XMI.. .io
criar o layout pela API tambm hrigat'rio definir os atributos layout width
(largura) e layout__heght (altura), que geralmente recebem os valores match oarent
Captulo 6 I Interface grca - gerenciadores de layout 175
e wrap_content. Esses parmetros podem ser informados utilizando a classe
android.widget.LinearLayout.LayoutParams, que por sua vez recebe no construtor as
constantes LayoutParams.MATCH_PARENT e LayoutParams.wRAP_CONTENT.

Para adicionar uma View dentro do layout, utilizado o mtodo addView(view), que
recebe uma subclasse de android.view.View, como Textview, EditText, Inageview, Button
etc. Para testar essa activity abra o projeto deste captulo no Android Studio e
execute no emulador.

ExempIoLinearLayoutAP|Activity.java
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
public class ExemploLinearLayoutAPIActivity extends Activity {
@0verride
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Cria o layout
LinearLayout layout = new LinearLayout(this);
layout.set0rientation(LinearLayout.VERTICAL);
layout.setLayoutParans(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
layout.setPadding(10, 10, 10, 1@); // Espaanento em pixels
TetView nome = new TextView(this);
nome.setTet("None:");
nome.setLayoutParams(new LayoutParams(LayoutParans.wRAP_CONTENT,
LayoutParams.wRAP_CONTENT));
layout.addView(nome);
EditTet tnome = new EditText(this);
tnone.setLayoutParams(new LayoutParans(LayoutParans.MATCH_PARENT,
LayoutParams.wRAP_CONTENT));
layout.addView(tnome);
// Focus
tnome.requestFocus();
Textview senha = new TextView(this);
senha.setTet("Senha:");
senha.setLayoutParams(new LayoutParams(LyoutParams.wRAP_CONTENT,
LayoutParams.wRAP_CONTENT));
layout.addView(senha);
EditTet tsenha = new EditText(this);
tsenha.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.wRAP_CONTENT));
layout.addView(tsenha);
176 Google Android - 4 edio
// Boto alinhado a direita
Button ok = new Button(this);
ok.setLayoutParams(new LayoutParams(LayoutParans.NRAP_CONTENT,
LayoutParams.NRAP_CONTENT));
ok.setGravity(Gravity.RIGHT);
ok.setText("0K");
layout.addView(ok);
// Informa o layout que foi criado pela API
setContentView(layout);
}

Como executar esse exemplo vou deixar por sua conta, pois a nica coisa que ele
faz criar um simples formulrio. Mas saiba que possvel criar todas as telas
utilizando somente a API: basta usar as subclasses de View desejadas. Os mtodos
das classes so semelhantes (quase sempre) aos atributos do XML. Por exemplo, a
classe Textview tem o mtodo setText(x), que corresponde ao atributo android : text do
XML. Fica a seu critrio escolher a maneira mais adequada para criar a interface
grca. Entretanto, criar o layout em XML a forma recomendada pelo Google,
pois separa a interface grca da lgica de negcios.

Nota: para testar os prximos exemplos, recomendo abrir o projeto deste


captulo no Android Studio e executar no emulador. A MainActivity desse projeto
vai mostrar uma lista com cada exemplo que vamos estudar.

6.18 Criao de um layout pela API - Tablelayout


O prximo exemplo de cdigo mostra como criar um layout pela API com a classe
TableLayout. Observe que para cada linha criado um TableRow.

ExemploTabIeLayoutAPIAttivity.java
inport android.widget.Tab1eLayout;
import android.widget.TableLayout.LayoutParans;
public class EemploTableLayoutAPIActivity extends Activity {
@0verride
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
Captulo 6 I Interface grca - gerenciadores de layout

// Cria o layout
TableLayout tabela = new TableLayout(this);
tabela.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
// Expande a coluna 1
tabela.setColumnStretchable(1, true);
// Linha 1
TableRow linhal = new TableRow(this);
TetView nome = new TetView(this);
nome.setText("Nome:");
linha1.addView(nome);
EditTet tnome = new EditText(this);
// Focus no campo nome
tnome.requestFocus();
linha1.addView(tnome);
// Linha 2
TableRow linha2 = new TableRow(this);
Textview senha = new TetView(this);
senha.setTet("Senha:");
linha2.addView(senha);
EditTet tsenha = new EditTet(this);
tsenha.setTransformationMethod(new PasswordTransformationMethod());
linha2.addView(tsenha);
// Linha 3
TableRow linha3 = new TableRow(this);
linha3.setGravity(Gravity.RIGHT);
// Boto alinhado direita
Button ok = new Button(this);
ok.setText(" Login ");
linha3.addView(ok);
// Adiciona as linhas
tabela.addView(linha1);
tabela.addView(linha2);
tabela.addView(linha3);
// Informa o layout
setContentView(tabela);
}

Como exerccio, deixo para voc executar este exemplo no emulador.


178 Google Android - 4 edio
6.19 ScroIIView

Quando existem muitos elementos na tela, surge a fl eccssidade de fazer a rola


gem (scroll). Para isso, podemos utilizar a classe android.wid9@~5UuVleW~ A Classe
Scrollview deve conter apenas um componente-lho e conforme 0 seu tamanho ele
far a rolagem ou no. Portanto, deve-se adicionar um layOUI dentro do 5CfuV1@W
como por exemplo 0 LinearLayout, que por sua vez pode receber outros componentes.
A seguir demonstraremos a utilizao do Scrollviewz

/res/Iayout/actvity_exempIo_scroIIview.xm|
<ScrollView nlns:android="http://schenas.android.com/apk/res/android"
android:layout_width="natch_parent" android:layout_height:"wrap_content">
<LinearLayout android:id="@+id/layoutl"
android:layout_width="natch_parent" android:layout_height:"wrap_content"
android:orientation="vertical">

/LinearLayout
/ScrollView

Observe que o Scrollview contm um LinearLayout. Para simular a barra de rolagem,


ser criada uma activity que vai obter o LinearLayout denido pelo id layoutl e vai
adicionar dinamicamente pelo cdigo Java vrios Textview na tela. Como o LinearLayout
foi denido com 0 sentido vertical, cada Textview car embaixo do outro.

Exemp|oScroIIViewActivity.java
public class EenploScrollViewActivity extends Activity {
@0verride
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
getActionBar().setDisplayHoneAsUpEnabled(true);
setContentView(R.layout.activity_exenplo_scrollview);
LinearLayout layout = (LinearLayout) ndViewById(R.id.layout1);
for (int i = 0; i < 100; i++) {
Textview text = new TextView(this);
// obrigatrio o layout_width e layout_height
tet.setLayoutParams(new LayoutParams(LayoutParans.NRAP CONTENT,
LayoutParans.HRAP_CONTENT));
tet.setTet("Texto: " + i);
layout.addView(text);
}

}
Captulo 6 I Interface grca - gerenciadores de layout 179
A figura 6.20 mostra o resultado do exemplo, em que podemos ver que foi criada
a barra de rolagem devido grande lista de elementos adicionados no layout.
Esse exemplo tambm interessante, uma vez que mostra como recuperar o
LinearLayout do arquivo XML e adicionar vrias views dinamicamente pela API.
No prximo tpico vou explicar algo importante sobre a action bar e navegao
de telas, portanto preste ateno nestas duas guras. Voc deve ter percebido
que a primeira gura referente ao projeto de exemplo deste captulo, no qual a
ManActivty mostra todos os exemplos na lista.

Exemplos de layout Texto: 1


Texto: 2
Texto: 3
LinearLayout pela API
Texto: 4
| Texto: 5
TableLayout pela API remo: 6
Texto: 7
Texto: 8
Scrollview
Texto: 9

Gridview Textor 1 1 Texto: IO

Texto: T2

Gallery Texto: 14 Texto: 13

_ ex o 18
Texto: 15

Texto: 17

ImageSw|tcher Texto;TIQ
t
Texto; 20

Figura 6.20 - Exemplo de Scrolllew.

Dica: caso precise fazer a rolagem na horizontal, utilize o Horzonta1Scrol.1View.

6.20 Alguns detalhes sobre a ActionBar e o "up navigation"


Na gura do exemplo anterior, o ttulo da action bar da primeira tela o nome
do projeto, mas o ttulo da segunda activity Scrollvew.
Para entender a explicao deste cdigo, veja o cdigo-fonte do projeto de exemplo
deste captulo.

Isso acontece porque no AndroidManifest.xml eu cadastrei um label para a activitj e


esse label utilizado como o ttulo da action bar. Caso o label no esteja denido
utilizado o nome do projeto.
<activty android:name=".ExemploScro1lVewActvty" androd:label:"@string/scrollvew"
android:parentActvityName=".ManActvity"/>
180 Google Androld - 4' edio
, - - , - ' _ 'z f -` ` - L tie 3 ;
(lliscrve tambem que, ao declarar a activity, cu mloimci .t activity pt q c t
Haimictivity do projeto. lsso e leito cont a tag android:parentActivttYN3"\@=" -MWCVY
Por isso ao entrar no exemplo do Scrollvtew voc pode clicar no botao de P
uavigation`I que a sctinha para esquerda na action bar. e automaticamente o
sistema vai voltar para a tela anterior.
l.embra ndo que, conforme explicado no captulo 5, sobre action bar, para habilitar
o botao up navigation basta utilizar a seguinte linha de codigo:
getActionBar().setDisplayHomeAsUpEnabled(true);
// Ou com a biblioteca de compatibilidade v7
getSupportActtonBar().setDtsplayHomeAsUpEnabled(true);

6.21 Layoutlnater - inando arquivos XML


No exemplo anterior, vimos como adicionar views dinamicamente no Scrollview.
Para isso foi preciso instanciar no cdigo objetos do tipo Textview. Como j foi
explicado anteriormente, o recomendado sempre fazer o layout em XML. Ento
como fazer nos casos em que preciso criar views dinamicamente?
Para isso podemos criar um arquivo XML de layout com apenas a parte da view
que precisamos adicionar, que neste caso um Textview em cada linha do Scrollview.
Ento podemos ter um arquivo XML de layout como este:

/res/layout/inate_tetview.xmI
<TetView mlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/textview"
android:layout_width="wrap_content" android:layout_hetght="wrap_content"
/
Note que este arquivo de layout contm o Textview que estvamos instancianclo
por programao no exemplo anterior. Desta vez esse mesmo Textview ser ins-
tanciado diretamente por meio do arquivo XML, procedimento que conhecido
pelos desenvolvedores Android com inflar um XMI lsso feito cont a classe
Layoutlnater, conforme demonstrado a seguir:

tia ExempIoScroIIVlewActivity.java

public class EemploScrollViewActtvlty extends Activity {


@0verride
protected void onCreate(Bundle ictcle) {
super.onCreate(icicle);
Captulo 6 I Interface grca - gerenciadores de layout 181
getActionBar().setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.activity_exemplo_scrollview);
Linearlayout layout = (LinearLayout) ndViewById(R.id.layout1);
for (int i = 0; i < 100; i++) {
// Cria o Textview inando o arquivo de layout, "ina o xml".
Layoutlnater inater = LayoutInater.from(this);
Textview text = (Textview) inater.inate(R.layout.inate_textview, layout, false);
// Agora basta usar a view inada normalmente.
tet.setTet("Teto: " + i);
layout.addView(text);
}

Nota: recomendvel no criar o layout no cdigo Java, mesmo que sejam


poucas partes. Se for necessrio criar um objeto do tipo View no cdigo, utilize
o Layoutlnater para inflar um arquivo XML. Lembre-se de que nem sempre a
view inada ser to simples quanto neste exemplo. No arquivo XML podemos
denir um layout bem complexo, o que justifica utilizar um arquivo XML para
manter o cdigo organizado. _
Os parmetros do mtodo inate(resource, root, attachToRoot) so:
Valor Descrio
resource Arquivo XML com o layout que precisa ser inado. O retorno ser
o objeto View desse layout.
root Layout container no qual esta view ser adicionada. Deve ser
informado para a view conhecer o tamanho e posicionamento do
layout-pai.
attachToRoot Flag que indica se a view deve ser adicionada no layout automatica
mente. E recomendado informar false e chamar o mtodo addView(view)
manualmente para adicionar a view no layout.

6.22 Links teis


Para complementar sua leitura, segue o link da documentao oficial:
Android API Guides - Layouts

http://developer android.com/guide/topics/ui/declaring-layout. html


*sx CAPTULO
Interface grca - View
.\`
\
1

A classe androd.view.Vew a classe-me de todos os componentes visuais do


Android. Este capitulo explica vrias de suas subclasses. No inicio, explicaremos
como trabalhar com recursos de texto, cores e imagens do Android. Depois,
demonstraremos diversos componentes disponveis na API para criar interfaces
visuais ricas.

Tambm aprenderemos a criar uma subclasse de View e desenhar com a API de


Canvas, alm de criar exemplos interessantes, como movimentar objetos e imagens
pela tela.

7.1 Arquivo /res/values/strings.xmI


O arquivo /res/values/stringsxml contm as mensagens de texto do projeto, para
fazer a internacionalizao. Um conceito importante sobre os arquivos XML com
os recursos do projeto que eles podem ter qualquer nome. Se voc quiser criar o
arquivo /res/values/mensagensxml em vez de /res/values/stringsxml, perfeitamente
possvel. O Android sabe o tipo do arquivo pelo seu contedo; assim, no caso de
arquivos de mensagens, eles devem sempre iniciar com a tag <resources e conter
vrias tags <strng> com a chave e o valor do texto.
A seguir, temos alguns textos que vamos utilizar nos prximos exemplos. Para conti
nuar, crie o projeto Demo-Views, ou se preferir abra o projeto de exemplo deste capitulo.

/res/values/strings.xmI
<?xm1 version="1.G" encodng="utf-8"?>
<resources
strng name:"app_name"LvroAndrodCap7-View</strng
<strng name="he11o_wor1d">He11o worId!</strng
<strng name="acton_settngs">Settngs</5trn9>

182
Captulo 7 nilnterface grca - View 133
<strng name "msg_verde_e_branco">Teto verde e branco </strng>
<string name "msg_azu1_e_branco">Texto azul e branco</strng>
<strng name "msg_verme1ho_e_branco">Teto vermelho e branco</strng>
<strng name "teto1">Teto campo 1 azul

Para acessar essas mensagens no cdigo Java, utilize a classe R com a sintaxe
R.strng.chave_mensagem.

Textvew t = (Textview) ndViewById(R.d.tet);


t.setTet(R.string.msg_verde_e_branco);

j no caso de um arquivo XML, utilize a sintaxe (dstrng/chave_mensagem.


<TextView androd:text="@string/msg_verde_e_branco" . . . />

Para traduzir os textos para diferentes idiomas, basta criar uma pasta /res/values
-idioma.

/res/values/values-pt/stringsxml
Caso queira deixar claro que esta pasta para o portugus do Brasil, adicione
a regio.
/res/values/values-pt-rBR/stringsxml

7.2 Arquivo XML com as cores


Da mesma forma que criamos um arquivo para conter as mensagens, podemos
criar um arquivo com as cores. Esse arquivo tambm pode ter qualquer nome, mas
deve ter um formato especco. Cada tag tem o nome da cor e o cdigo RGB.

/res/values/coIors.xmI
<?xml verson="1.0" encodng="utf-8"?>

<color name:"vermelho">#ff0000
<color name="azul">#00@0ff
<color name="verde">#00ff00
<color name:"branco">#ffffff

Se o cdigo RGB tiver seis caracteres, so as cores normais: vermelho, verde e


azul. Mas, se tiver oito caracteres, a primeira dupla referente transparncia.
Por exemplo, o cdigo a seguir define uma cor azul.
<color name="azul">#G900ff
184 Google Android - 4 edio
lim seguida, temos a cor azul com 50% dc transparencl

. . , . z - f . etCo1or cor _
<color name="azu1">#500000ff
Para utilizar uma cor no codigo, utilize o metodo getRe50UrC'S() 9 ( )
Textvew t = (Textview) ndVewById(R.d.tet);
t.setTextCo1or(getResources().getCo1or(R.co1or.branco));
t.setBackgroundCo1or(getResources().getColor(R.co1or.verde));
t.setTet(R.string.msg_verde_e_branco);

Para utilizar as cores no arquivo XML, utilize a sintaxe @co1or/Cor. Podemos vi


sualizar a seguir um Textvew que mostra como deixar o texto branco com a cor
de fundo verde.
<TextView android:1ayout_wdth="match_parent" androd:1ayout_heght="wrap_content"
android:text:"@string/msg_verde_e_branco"
androd:tetColor="@co1or/branco" androd:background="@co1or/verde" />

Observe que nesse exemplo utilizamos os atributos androidzbackground e


androidztexttolor do Textvew para denir a cor de fundo e a cor do texto. Para 0
valor da cor foi usado um recurso denido no arquivo /res/values/colors.xml, mas
tambm poderamos ter usado a cor em RGB diretamente no cdigo.
<TetView android:1ayout_wdth="match_parent" android:1ayout_height="wrap_content"
androd:text:"@string/msg_verde_e_branco"
androd:textCo1or="#ffffff" androd:background="#@0ff00" />

De qualquer forma, recomendado deixar as cores separadas nos arquivos de


recursos, pois dessa forma a cor pode ser alterada de forma centralizada, facili
tando a manuteno do cdigo.

7.3 Arquivo XML para criar um estilo (SS

''I..,
ja ouviu falar de CSS em pginas para internet? No Android, existe algo parecido e so
chamados de esnlos. Um tema que estudamos anteriormente um conjunto de estilos
Com um arquivo de estilo, podemos denir de uma s vez determinado padro
de cor, assim como o tipo da fonte como negrito e itlico Dessa forma possvel
dar um nome a esse estilo e usa-lo no codigo. Um arquivo de estilos tambm pode
ter qualquer nome, desde que seja formado pelas tags <sty1e name="nomeEst1o" c a
tag <1tem> para compor cada elemento.
Captulo 7 I *Interface grca - View 185
/res/values/css.xml
<?ml version="1.0" encoding="utf-8"?>

<style name="estiloEemplo">
<item name android:textSize">14sp
<item name android:textColor">#ffffff
<item name "android:background">#ff00G0
<item name android:textStyle">italic

Para referenciar o estilo no cdigo, utilize a classe R com a constante R . style.nome_estilo.


Textview t = (Textview) ndViewById(R.id.tet);
t.setTetAppearance(this, R.style.estiloExemplo);

Para referenciar o estilo no arquivo XML, utilize a sintaxe (style/nome_estilo.


<TextView android:text:"@string/msg_vermelho_e_branco" style:"@style/estiloExemplo" ... />

7.4 Exemplo completo com estilos


Agora que estudamos como criar arquivos com os recursos de texto, cores e esti
los, criaremos uma tela com trs campos de texto para demonstrar como utilizar
os recursos.

Se voc quiser, possvel criar uma activity com o seguinte cdigo para testar os
exemplos. No entanto, como vou utilizar os arquivos XML de layout para demons
trar, a prpria pr-visualizao do editor j suficiente para entender os exemplos.

ExemploTextoCoresActivity.java

public class ExemploTextoCoresActivity extends Activity {


@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_exemplo_teto_cores);
}

A seguir, podemos visualizar o cdigo-fonte do arquivo de layout da activity


186 Google Android - 4 edio
=*=i~ /res/layout/activity, exemplo _teto.___tores.mI

`?ni version="1.0" encoding="utf-8"?>


<Linearlayout xmlns:android="http://schemas.android.com/apk/FGS/dfld"
android:iayout_width="match_parent" android:1ayout_height="matCh_DftH
android:orientation="verticai" android:padding="16dp" >

TetView android:iayout_width="match_parent" android:1ayout_height="wFD_C0"@"t"


android:text:"@string/msg_azui_e_branco"
android:background="@coior/azul" android:textCo1or="@coior/branco"
android:tetSty1e="bo1d" />
<TetView
android:iayout_width="match_parent" android:iayout_height="wrap_content"
android:layout_marginTop="10dp"
android:text:"@string/msg_verde_e_branco"
android:background="@coior/verde" android:tetCoior="@co1or/branco"
android:tetStyie="bo1d" />

TetView style:"@sty1e/estiloxempio"
android:iayout_width="match_parent" android:1ayout_height="wrap_content"
android:iayout_marginTop="10dp"
android:text:"@string/msg_verme1ho_e_branco" />
</LinearLayout

PJesse cochggi stiiinlizachas as snitaxes @string/chave_msg, @co1or/nome_cor e


@sty1e/nome_estiio para acessar as mensagens, cores e estilos definidos nos arquivos
de recursos. Na pr-visualizao do layout, podemos ver uma tela com trs textos
coloridos, conforme a gura 7.1. Devido impresso, no possvel visualizar
claramente as cores no livro; portanto, abra o arquivo no editor.

Figura Zi - Estilos 1']ont' e cor:

Nota: os estilos so utilizados em todos os componentes visuais (views) e nao


apenas para definir a cor dos textos. Mas isso e um pouco mais avanado e voc
ll 1'I'"*"lf mm "P<>- VOC se lembra dos temas Hoio e Material? Cada tema
e inn conjunto de estilos que e aplicado em cada view.
Captulo 7 I Interface grca - View 187
7.5 View - A classe responsvel por desenhar elementos na tela
A classe android.view.View utilizada como base para qualquer componente grfi
co, e toda subclasse de View precisa implementar o mtodo onDraw(Canvas canvas), o
qual responsvel por desenhar os elementos. Na lista a seguir, podemos verificar
alguns dos principais mtodos da classe View.
Atributo Descrio
requestFocus() Solicita o foco do componente. Para isso, os mtodos isFocusable()
ou isFocusableInTouchMode() precisam retornar true.
setPadding(esquerda cima, direita, baixo)
Informa o espao em pixels que deve ser inserido esquerda,
direita, acima e abaixo do componente antes de mostrar o seu
contedo. Isso muito utilizado em layouts que fazem padding
para dar uma pequena margem antes de inserir as views filhas.
O atributo correspondente no XML android : padding, o qual de
ne automaticamente o mesmo valor para todos os parmetros.
Caso seja necessrio, no XML, informar corretamente o padding
usado para a esquerda, direita, acima e abaixo da view podem
-se utilizar os atributos android:paddingLeft, android:paddingRight,
android : paddingTop e android : paddingBotton, respectivamente.
setVisibility(v) Pode receber trs valores, denidos pelas constantes View.VISIBLE,
View. INVISIBLE e View . GONE.Ambas as constantes INVISIBLE e GONE no
mostram a View na tela. A diferena que o INVISIBLE no mostra a
vievsg mas deixa o espao que ela ocuparia reservado (em branco).
J a constante GONE literalmente remove a view da tela. O atributo
no XML correspondente a esse mtodo o android:visibility, o
qual recebe os seguintes valores: visible, invisible e gone.
requestLayout() Solicita ao Android para refazer o layout da tela. Ser visto com
mais detalhes posteriormente, quando criarmos um exemplo
com uma.
invalidate() lnvalida a View, solicitando ao Android para desenhar a view
novamente. Ser visto com mais detalhes posteriormente quando
criarmos nossa prpria View customizada.
onSizeChanged(int largura, int altura, int larturaAntiga, int alguraAntiga)
Chamado pelo Android sempre que um componente altera seu
tamanho, informando as novas largura e altura, assim como os
valores antigos.
onDraw(Canvas) Mtodo responsvel por desenhar o componente na tela. Pode ser
implementado manualmente para controlar o que desenhado
na tela.
188 Google Android - 4 edio
Atnbuto Descaolrontj
onKeyDown(int keyCode, KeyEvent event) e onKeyu(t keyCode, KGYVH Vet)
Chamados quando o usurio pressiona uma tecla no caso de
dispositivos com teclado fsico. Voc pode ate sobrescrever esses
mtodos na sua classe de Activity para recuperar as teclas digi
tadas pelo usurio.
onTouchEvent(HotionEvent)
Chamado quando o usurio toca na view
Nos prximos tpicos, vamos estudar vrios tipos de views que podemos utilizar
para criar os layouts de tela no Android.

7.6 TextView e EditText - campo de texto para digitar informaes


A primeira e mais simples das subclasses de View 0 android.widget.TetVew, que
representa um texto/label. E a classe android.wdget.EditText uma subclasse de
Textvew utilizada para criar um campo de texto.
O EdtTet pode ser usado para entrada de texto normal, ou para aceitar apenas
nmeros ou campos de senha. A seguir, podemos visualizar um exemplo de um
formulrio de login, em que demonstrado como criar um campo de texto normal
para o login e um campo de senha.

/res/layout/exempIo_edittext.xmI
<?xn1 verson="1.G" encoding="utf-8"?
<Tab1eLayout xmlns:android="http://schenas.android.con/apk/res/android"
android:1ayout_width="natch_parent" android:1ayout_height="match_parent"
android:stretchCo1unns="1" android:padding="16dp">

<TetView android:text="@strng/usuario" android:padding="3dp" />


EdtText android:id="@+id/campoLogn" android:padding="3dip" android:nputType="text"/>

<TetView androd:tet="@strng/senha" />


<EdtText androd:d="@+id/canpoSenha" androd:inputType="textPassword" /
</TableRow
<Tab1eRow android:gravity="right">
<Button android:id="@+id/login" android:tet="@string/login" />
</Tab1eRow
Captulo 7 I Interface grca - View 189
O EditText precisa denir o tipo de entrada do texto. Isso feito pelo atri
buto android:inputType. O padro para texto normal android:inputType="text",
mas voc pode congurar para o modo de entrada de senha com o atributo
android:inputType="textPassword", ou android:inputType="number" para nmeros, dentre
outras conguraes.

7.7 AutoCompIeteTextView
A classe android.widget.AutoCompleteTetView um campo de texto que completa
automaticamente o texto que o usurio est digitando, e muito til em deter
minados casos. Existem dois parmetros que podem ser informados no momento
de criar essa classe.

android:conpletionThreshold - Nmero de letras que o usurio precisa digitar


para iniciar o autopreenchimento do texto.
android:completionHint - Texto utilizado para exibir uma dica sobre o preen
chimento do texto. O texto exibido na parte inferior do popup com as
opes quando este aberto.
Podemos visualizar a seguir um exemplo que cria um campo de texto que
vai sugerir os nomes dos estados do Brasil. Para preencher a lista, utiliza
da a classe android.widget.ArrayAdapter, que uma implementao da interface
android . widget. ListAdapter. Um adapter utilizado para fazer a ligao entre o contedo
e o componente, ou seja, ele fornece o contedo para preencher determinado compo
nente. Vamos estudar o conceito de adapters mais para frente; portanto, que tranquilo.

ExemploAutoCompleteTextViewActivity.java

public class EemploAutoCompleteTetViewActivity extends Activity {


private static nal String[] ESTADOS = new String[] { "Acre", "Alagoas", "Amap", "Amazonas",
"Bahia", "Cear", "...", "So Paulo", "Santa Catarina", "Sergipe","Tocantins" };
@0verride
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_exemplo_auto_complete_textview);
AutoCompleteTextView estados = (AutoCompleteTextView) ndViewById(R.id.estados);
// Adapter para preencher com os estados
ArrayAdapter adaptador = new ArrayAdapter(this,
android.R.layout.simple_dropdown_item_1line, ESTADOS);
estados.setAdapter(adaptador);
}
no Google Android - 4* edio
zftesiltiytittt/titttvity, mniploh auto rmttplete tt~tviw.mI
`?\nI version-t.@ encodinqutf-8?~
`tineartavout \n\ns:android`http:/Jsehens.ndroid.ron/D\lf@S/df\"
androidziavout_uidthz*nateh_parent andrtdilavouthet0htHwr0Pe0\@'
ndratd:orientationverttial" android:paddtn\odD"
etextriew
android:lavoutUuidthw'wrao_content android:1avout1he\ghtwfP.\@
android:re\tv`stados` ;~
~AutoonplereIe\tview android:td2"@+\d/estados"
android:layouthuidthznatch_parent android:Iavoutfheight="wraP,f0\@"'
ndroid:conp\etionThreshld1`
andraidzao pIetionHint=Digite o none de um estado lt
Butten
android:Iayout1width=wrap_eontent android:leyoutHheight="wrap,content
android:text=0k /
</Lineartayout

~
Nesse exemplo. o atributo attdroidzconplettonthreshold toi dettido mm o valor I.
indicando que o popup mm o autopteetteltiatento deve ser aberto quando o usa
ario digitar a primeira letra. U atributo androidzcompletionint delitte .t tttensagettt
que apate\\~ tia parte mt~z~o~ do popitix .~\ ligura 7.2 exibe o resultado. Como lot
digitado o texto l`ar` os estados Para. Paraiba e i`arati.i tiiram sugeridox
1a301
.QfW*a@
_,._~1.; \ :. zzt- _.'5.~~.zzwz.zirz:t@:zi;t~
ti .z'.~,f~,z'-.;,,_ t z -v..r .., z~-. -. :

....'3'
" _*
' 4_I
_.~_.z
_ `L * *f
-. . *L-~
* `N" \'Vll'*
,. ' 'z i, Six*
rz~.iii,
-.z; 5 -~.\. ..
;_-'*':: 5g"
' :g1Z
__..._ _.va ' V r -.,_. z

HKINU -3 `\`f`"|{'U da rlassc .-\utot `ontI^ti^ 2.\`t\`i'it:

os exemplos. `
pari! nvlhf UHPHhu\`l\\ da `\x(\`*utt\ `\ \\'i(\\ dv (\\(\`l\ln
deste capitulo no etnttlador. A aetwity ittieial eotttettt tuna Iist=wz.~tii ootit todos
Captulo 7 I Interface grca - View 191
7.8 Button e ImageButton
As classes android.widget.Button e android.widget.InageButton so utilizadas para criar
um boto na tela. A diferena que a classe InageButton permite usar uma imagem
para desenhar o boto. O exemplo a seguir utiliza a classe ImageButton, que exibe
um alerta quando o boto clicado.

ExempIoImageButtonActivity.java
public class ExemploInageButtonActivity extends Activity {
@0verride
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_exenplo_inage_button);
ImageButton botaolmageml = (InageButton) ndViewById(R.id.ing1);
nal Context context = this;
botaolmageml.set0nClickListener(new View.0nClickListener() {
public void onClick(View v) {
Toast.nakeTet(context, "Imagem 1 OK", Toast.LENGTH_SHORT).show();
}

});
InageButton botaoImagem2 = (ImageButton) ndViewById(R.id.img2);
botaoInagem2.setImageResource(R.drawable.snile2);
botaoImagem2.set0nClickListener(new View.0nClickListener() {
public void onClick(View v) {
Toast.makeText(contet, "Imagem 2 OK", Toast.LENGTH_SHORT).show();
}

});
}

/res/Iayout/activity_exempIo_imagem_button.xmI
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xnlns:android="http://schenas.android.con/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical">
<InageButton android:id="@+id/ingl" android:layout_width="natch_parent"
android:layout_height="wrap_content" android:src="@drawable/snilel" />
<ImageButton android:id="@+id/ing2" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
192 Google Android - 4 edio
Observe que a primeira imagem denida diretamente no QYQUIVO de layout COm
o atributo androd:src="@drawab1e/sm1e1". Entretanto, a segunda imagem e definida
dinamicamente no cdigo.
botaoImagem2 . setImageResource(R.drawab1e. smi1e2);

Os mtodos que podem ser utilizados para alterar a imagem dinamicamente


podem ser visualizados na lista a seguir. Esses mtodos esto denidos na classe
Imagevew, a superclasse de ImageButton.
Mtodo Descriao
'` g_ gw V, g
setImageBitmap(btmap) Recebe um androd.graphcs.Btmap para exibir a imagem.
setImageResource(id) Recebe o id da imagem utilizando a constante R .drawab1e. imagem.
setImageURI(ur) Recebe uma URI para exibir a imagem. Uma URI criada
com o mtodo Uri . parse(strng) e pode representar o caminho
para um arquivo ou um link para uma imagem na web.
A gura 73 demonstra o resultado deste exemplo executando no emulador. Ob
serve que a primeira imagem ocupou a largura da tela inteira, porque sua largura
foi denida como match_parent.

Figura Z3 - Exemplo de ImageButton.


Outro conceito importante sobre botes so os s eletores de estado (selectors),
utilizados para denir uma imagem diferente dependendo do estado do boto,
como, por exemplo, se o boto est clicado ou no. Par a isso, voc deve inserir
na Pasta /'65/dmwabla Um arquivo XML com a tag com cada estado da
imagem. Esse arquivo agrupa um con`unr0 d
J e imagens, e ser transformado em
uma imagem pelo compilador.
Captulo 7 I Interface grca - View 193
/res/drawable/exempIo_seIetores.xm|
<?xml verson="1.@" encoding="utf-8"?>
<selector xmlnszandrod="http://schemas.androd.com/apk/res/androd">

<tem androd:state_pressed="true" androd:drawab1e="@drawable/button_pressed" />

<tem androd:state_focused="true" android:drawable="@drawable/button_focused" />

<tem androd:state_hovered="true" androd:drawab1e="@drawable/button_focused" /


<tem androd:drawab1e="@drawab1e/button_norma1" />

O arquivo XML dene uma imagem para cada tipo de estado do boto. Portanto,
voc precisa pedir aos designers para criar essas imagens, ou pelo menos duas:
normal e selecionado. Com esse arquivo de seletores (selectors) em mos, basta
utiliz-lo como a imagem de fundo para o boto. Na prtica, o arquivo XML
vai virar uma imagem e voc pode utilizar as notaes @drawab1e e R.drawable para
acessar esse recurso.

<Button androd:layout_heght="wrap_content" androd:1ayout_wdth="wrap_content"


androd:background="@drawab1e/exemp1o_se1etores" />

7.9 CheckBox e ToggIeButton


Um checkbox pode ser criado no Android com a classe androd .wdget.CheckBo, que
pode ser inserida facilmente em um arquivo de layout conforme o exemplo a seguir.
<CheckBo androd:d="@+d/checkReceberEmal"
androd:layout_wdth="wrap_content" androd:layout_heght="wrap_content"
android:tet="Receber email" />

Para verificar se o checkbox est marcado ou no, utilize o mtodo sChecked().


CheckBox check = (CheckBox) ndViewById(R.d.checkReceberEma1);
boolean receberEmal = check.isChecked();

Outra classe que pode ser utilizada para selecionar uma opo, similar ao
checkbox, a androd.wdget.ToggleButton.

<ToggleButton androd:id="@+id/toggle"
androd:layout_wdth="wrap_content" androd:1ayout_heght="wrap_content"
android:textOn="Lgado"'android:tet0ff="Desligado" />
194 Google Android - 4 edio
Essa classe tambm contm o mtodo isChecked(). Com OS 8ITbUf05 '3dfd5tet9"
recem no boto quando ele
e androidztextff, possvel controlar os textos que apa I d 1
est selecionado ou no. A seguir, podemos visualizar um exemp o as C asses
CheckBo e ToogleButton.

/res/layout/activity_exempIo_toogIe_button.xmI
?nl version="1.6" encoding="utf-8"?
<LinearLayout mlns:android="http://schemas.android.com/apk/rES/dfd"
android:layout_width="match_parent" android:layout_height="matCh_P3rent"
android:orientation="vertical">
<TetView
android:layout_width="wrap_content" android:layout_height="wrap_content
android:text="Exemplo de CheckBox e ToggleButton" />
<CheckBo android:id="@+id/check1"
android:layout_width="wrap_content" android:layout_height="wrap_content
android:text="Check 1" />
<CheckBo android:id="@+id/check2"
style="?android:attr/starStyle"
II
android:layout_width="wrap_content" android:layout_height="wrap_content
android:text="Check 2" /
<TextView
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:tet="0 ToggleButton mostra os textos Ligado ou Desligado..." /
<ToggleButton android:id="@+id/toggle"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:tet0n="Ligado" android:tet0ff="Desligado" />
<Button android:id="@+id/bt0K"
android:layout_width="wrap_content" android:layout_height=wrap_content"
android:tet="0K />
</LinearLayout

ExempIoToggIeBut1onActivity.java

public class ExemploToggleButtonActivity extends Activity {


@0verride
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_exemplo_toogle_button);
nal ToggleButton toggle = (ToggleButton) ndViewById(R.id.toggle);
Button b = (Button) ndViewById(R.id.bt0K);
b.set0nClickListener(new View.0nClickListener() {
public void onClick(View v) {
Captulo 7 I Interface grca - View 195
boolean selecionado = toggle.isChecked();
Toast.makeText(Eemp1oToggleButton.this, "Selecionadoz " + selecionado,
Toast.LENGTH_SHORT).show();
}

});
}

A figura 7.4 demonstra o resultado desse exemplo. Observe que o segundo


checkbox est parecido com uma estrela porque foi definido um estilo customi
zado com o atributo style="?android:attr/starSty1e".
Esse um exemplo legal para explicar algo importante do Material Design: como
as cores so aplicadas no tema. Se voc executar o projeto de exemplo no emulador,
ver que a cor da action bar azul e a cor dos componentes vermelha. Por exemplo,
ao marcar o checkbox, a cor da seleo ca vermelha. Isso configurado de forma
simples no arquivo /res/values~1/21/styles.xml, que sobrescreve algumas propriedades
de cores. Veja que o projeto Demo-Views no utiliza a biblioteca de compatibilidade,
e por isso o tema Material foi congurado apenas para API Level 21 ou superior.

Exemplo de CheckBo e ToggIeButton


Check 1
Check 2
O ToggleButton mostra os textos Ligado ou
q Desligado...
i

' Desligadb

'mc
l

Figura 24 - Exemplo de ChecleBox e ToggleButton.

/res/values-v21/styIes.xmI
<?xml version="1.0" encoding="utf-8"?>

<style name="AppTheme" parent="android:Theme.Material.Light">

iten name="android:co1orPrinary">@co1or/primary
196 Google Android - 4 edio
_ _ . . . extual a bars -->
<!~- Vartaao escura da cor primaria para a status bar e cont PP
<iten nane="android:colorPrinaryDark"@color/prn8fY-fk<it">

<color nane="prinary">#63A9F4
<color name="prnary_dark">#61579B/color>~
<color nane="accent"#F44336 <!~- Vermelho -->

<color name="vermelho">#ff00G0
<color name="azul">#0@09ff
<color name:"verde">#00ff09
<color name="branco">#ffffff

Nota: no captulo 11, sobre Material Design, vamos voltar a estudar essas cores.
De qualquer forma, importante voc entender que a cor primria (primary)
representa a cor da marca do cliente ou do seu aplicativo, e a cor de acentuao
(accent) utilizada para destacar as views e determinados componentes na tela.

7.10 RadioButton

O componente radio button permite selecionar apenas uma nica opo de uma
lista. No Android, as classes androld.wdget.Radoroup e androd.wdget.RadioButton
so utilizadas para isso. A classe RadoGroup dene o grupo que contm a lista de
opes, na qual cada opo representada por um RadoButton.
O exemplo a seguir cria dois botes com os textos Sim e No, respectivamente:
<RadioGroup androd:layout_width="match_parent"
BHFO113)/U_h@9ht="W`6D_Content" androd:orientation="horizontal"
Captulo 7 n Interface grca - View 197
androd:d="@+d/group1">
<RadoButton androd:d="@+d/radoSm"
androd:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content"
androd:tet="Sm" androd:checked="fa1se" />
<RadoButton androd:d="@+d/radioNao"
androd:1ayout_width="wrap_content" androd:1ayout_heght="wrap_content"
androd:tet="No" androd:checked="fa1se"/>
</RadoGroup>

Observe que cada RadoButton tem um id, para que posteriormente o id do boto
selecionado possa ser recuperado, chamando o mtodo getCheckedRadoButtonId()
da classe Radoroup. Nesse exemplo, foram denidos os ids radoSim e radoNao. Isso
possibilita utilizar o seguinte cdigo para descobrir qual boto foi selecionado:
boolean sim = R.d.radoSm == group.getCheckedRadoButtonId();

Dessa forma, o id do RadoButton selecionado est sendo comparado com um id


conhecido que foi denido no arquivo XML de layout. Para demonstrar o uso do
RadoButton e do CheckBox, criaremos um exemplo de um formulrio.

/res/Iayout/activity_exempIo_check_radio_form.xmI
<?xml verson="1.0" encodng="utf-8"?>
<LnearLayout xmlns:androd="http://schemas.androd.com/apk/res/androd"
android:1ayout_wdth="match_parent" androd:1ayout_heght="match_parent"
androd:orientaton="vertca1">
<TetVew
android:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content
androd:text="Nome" />
<EdtText androd:d="@+id/tetNome"
androd:1ayout_wdth="match_parent" androd:1ayout_height="wrap_content" />
<TextView
androd:1ayout_wdth="wrap_content" androd:1ayout_height="wrap_content"
android:tet="Concorda?" />
<RadoGroup androd:1ayout_width="match_parent"
android:iayout_heght="wrap_content" androd:orentaton="horzonta1"
androd:d="@+d/group1">
<RadioButton androd:d="@+d/radoSim"
androd:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content
androd:text="Sm"
androd:checked="fa1se" />
<RadioButton android:d="@+d/radioNao"
androd:1ayout_wdth="wrap_content" android:1ayout_height="wrap_content"
android:tet="No"
androd:checked="fa1se"/>
198 Google Android - 4 edio

<TetView
android:layout_width="wrap_content" android:layout_height="wFD_C"t@"t"
android:tet="Receber Email ?" />
<CheckBo android:id:"@+id/checkReceberEmail" H
android:layout_width="wrap_content" android:layout_height= wFD_Cf9"t
android:tet="Receber email" />
<Button android:id="@+id/buttonEnviar"
android:layout_width="wrap_content" android:layout_height="wrP_C0t@"t
android:tet="Enviar" />

O seguinte cdigo mostra como vericar se o checkbox e radio button esto


selecionados:

ExemploCheckRadioFormActivity.java
public class EemploCheckRadioFormActivity extends Activity {
private static nal String TAG = "livro";
@0verride
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_eenplo_check_radio_form);
nal EditText tetNone = (EditTet) ndViewById(R.id.tetNone);
nal RadioGroup group = (RadioGroup) ndViewById(R.id.group1);
group.set0nCheckedChangeListener(new Radioroup.0nCheckedChangeListener() {
public void onCheckedChanged(RadioGroup group, int checkedld) {
boolean sim = R.id.radioSim == checkedldg
boolean nao = R.id.radioNao == checkedld;
if (sin) {
Log.i(TAG, "Marcou radio Sim: " + checkedld)
} else if (nao) {
Log.i(TAG, "Marcou radio No: " + checkedld)
}

});
nal CheckBo check = (CheckBo) ndViewById(R.id.checkReceberEnail);
// Dene um listener para executar quando alterar o check
check.set0nCheckedChangeListener(new CheckBo.0nCheckedChangeListener() {
public void onCheckedChanged(ConpoundButton buttonview, boolean isChecked) {
Log.i(TAG, "checkz " + isChecked);
1

});
Capitulo 7 I Interface grca - View 199
Button b = (Button) ndViewById(R.id.buttonEnviar);
b.set0nClickListener(new 0nC1ickListener() {
public void onC1ick(View v) {
Log.i(TAG, "0K");
// Compara o id do radioSin
booiean concorda = R.id.radioSim == group.getCheckedRadioButtonId();
boolean receberEmai1 = check.isChecked();
StringBuffer sb = new StringBuffer();
sb.append("Nome: ").append(tetNome.getText())
.append("\nReceber Email: ").append(receberEmai1 ? "Sim" : "No")
.append("\nConcorda: ").append(concorda ? "Sim" : "No");
Toast.makeTet(Exemp1oCheckRadio.this, sb.toString(), Toast.LENGTH_SHORT).show();
}

});
}

Observe que ambas as classes CheckBo e Radioroup contm o mtodo


setOnCheckedChangeListener(listener) para congurar o listener que deve ser executado
quando o estado do checkbox ou radio for alterado. Porm, como demonstrado
no exemplo, os mtodos recebem diferentes interfaces (tm os mesmos nomes,
mas esto em pacotes diferentes). Ao executar esse exemplo, podemos visualizar o
formulrio, conforme mostra a gura 15. Ao preencher o formulrio e pressionar
o boto, um alerta com as opes selecionadas exibido.

NOITIE

__ .,
Concorda?
{ ,,.,i Sim ,; No
Receber Email ?
[ Receber email

Enviar

Figura Z5 - Exemplo de CheclzBox e RadioButton.


200 Google Android - 4 edio
7.11 Spinner
A classe android.widget.Spinner e utilizada paracombo com. opes na tela.
criar um
Para denir a lista que deve ser exibida no combo, usada uma implementao
de android.widget.SpinnerAdapter que herda de android.widget.AdaDt@f

A seguir, podemos visualizar um exemplo que cria um combo na tela que lista
os nomes dos planetas do sistema solar. Ao selecionar algum plafl, sua foto e
exibida na tela.

i /res/Iayout/activity_eempIo_spinner.xmI
<?ml version="1.0" encoding="utf-8"?>
LinearLayout mlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="wFD_C"@"t"
android:orientation="vertical">
<TextView
android:layout_width="match_parent" android:layout_height="wrap_content"
android:tet="Selecione una opo" />
<Spinner android:id="@+id/conboPlanetas"
android:layout_width="natch_parent" android:layout_height="wrap_content"
android:drawSelector0nTop="true"
android:prompt:"@string/teto_combo" />
<InageView android:id="@+id/img"
android:layout_width="match_parent" android:layout_height="match_parent" />

ExempIoSpinnerActivity.java
public class EemploSpinnerActivity extends Activity {
// Planetas
private int[] imagens = { R.drawable.mercurio, R.drawable.venus, R.drawable.terra,
R.drawable.marte, R.drawable.jupiter, R.drawable.saturno, R.drawable.urano,
R.drawable.netuno, R.drawable.plutao };
private String[] planetas = new String[] { "Mercrio", "Vnus", "Terra", "Marte",
"Jpiter", "Saturno", "Urano", "Netuno", "Pluto"};
@0verride \
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_eemplo_spinner);
nal Inageview imagem = (ImageView) ndViewById(R.id.img);
nal Spinner combo = (Spinner) ndViewById(R.id.conboPlanetas);
ArrayAdapter adaptador = new ArrayAdapter<String(this,
android.R.layout.sinple_spinner_iten, planetas);
Captulo 7 I Interface grca - View 201
adaptador.setDropDownViewResource(android.R.layout.sinple_spinner_iten);
combo.setAdapter(adaptador);
// Se selecionar algun planeta atualiza a imagem
combo.set0nItenSelectedListener(new Adapterview.0nItemSelectedListener() {
@0verride
public void onItemSelected(AdapterView<?> parent, View v, int posicao, long id) {
// Atualiza a imagem
imagem.setInageResource(imagens[posicao]);
}

@0verride
public void onNothingSelected(AdapterView<?> parent) { }
});
}

Se for necessrio obter o item selecionado, utilize algum dos seguintes mtodos:
Mtodo Descrio
Object getSelectedItem() Retorna o item selecionado.
long getSelectedIternId() Retorna o id do item selecionado.
int getSelectedItenPosition() Retorna a posio do item selecionado. Essa posio
equivalente ao array fornecido para o spinner.
Nesse exemplo, preferimos monitorar o estado do Spinner em tempo de execuo.
Para isso, implementamos a interface Adapterview.OnItemSelectedListener e o mtodo
onItenSelected(parent,view,posicao,id), com o objetivo de atualizar a imagem auto
maticamente quando um planeta for selecionado. A gura 16 mostra o planeta
Terra selecionado no combo.

, . Terra
Selecione uma opo Selecione uma opo
' Mercuno gf
.
` Vnus
fe -;z . ,. .V W~ . ,um ~-_. 7_,, _.,x __y_ a , I,
$?* : ff?? ,..1 f.. ;.. 513
- f ~=. .~ =,=;:-";,_,..u.;s i. fz z,'.^z..;<1g z, z== ;. _z
zk
i z z f. pq, 4-3;z-
z-V Yzzzz .^z,=>-
;o....: .ez-^_zM=z^~.
:jaz .- zf -~ _,y,.
~ .rj:._fe%*3zf:i.:sfz- ';g;.*?i*z+2'^.r'E; 7:

Marte

,.
Jupiter

1 SBUITK)

UFGTID "__ Nr,

Figura 76 - Planeta Terra selecionado.


202 Google Android - 4 edio
Observe que foi utilizado o recurso nativo android.R.1By0U-Sl'lDl@_5P1""@"-1te"l Pam
criar o drop-down com a lista de planetas.
adaptador.setDropDownViewResource(android.R.layout.simple_SP@f_);

Voc pode criar seu prprio recurso XML se desejar customizar a interface,
ou at utilizar outro padro da plataforma com o 0 recurso android.R.layout.
simple_spinner_dropdown_iten. Altere o exemplo para esse cdigo e conra o resultado.
adaptador . setDropDownViewResource( android . R . layout . simple_spinner_droDdW"_t@f'\);

Nota: a classe android.R acessa os recursos nativos do Android. Cada projeto


contm sua prpria classe R com o seu pacote especco; portanto, sempre preste
ateno ao fazer os imports.

7.12 ProgressDialog -janela de progresso


Voc j deve ter visto aquela mensagem de Por favor, aguardem em alguma aplicao
que faz algum processamento demorado. No Android, existe uma classe especial
justamente para exibir uma janela na tela com uma mensagem para aguardar. Para
isso, usaremos a classe android.app.ProgressDialog, lha da classe android.app.Dialog.

A seguir, podemos ver um exemplo muito simples de como usar a classe Prog ressDialog.
ProgressDialog dialog = new ProgressDialog(this);
dialog.setTitle("Eemplo");
dialog.setMessage("Buscando imagem, por aguarde...");
dialog.setIndeterninate(true); // Indica para executar por tempo indeterminado
dialog.setCancelable(true); // Se pode cancelar caso pressione o voltar
dialog.show();

Esse cdigo exibir uma janela de progresso com a mensagem informada. O pr


prio Progressialog j exibe uma animao com uma imagem girando para encher
os olhos do usurio. A janela car aberta por um tempo indeterminado at que
O ITIOCO diSriSS(> Seja chamado para encerr-la. Um atalho para essas linhas
simplesmente chamar o mtodo esttico show(), conforme demonstrado a seguir.
que faz a mesma coisa que o exemplo anterior.
ProgressDialog dialog = ProgressDialog.show(this,"Exemplo" D

"Buscando imagem, por favor, aguarde...", false,true);

Essa janela de progresso extremamente til em aplicaes que acessam a in


ternet Para buSf1f0fma;0es,nas quais o tempo de resposta indeterminad0~
Captulo 7 I Interface grca - View 203
Demonstraremos um exemplo que faz o download de uma imagem da internet.
Enquanto o download est em andamento, um alerta de progresso exibido na
tela. O arquivo de layout a seguir contm apenas a imagem que ser atualizada
depois que o download terminar.

/res/layout/activity__exempIo_progress_diaIog.xmI
<?ml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent" >
<ImageView android:id="@+id/img" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:scaleType="tCenter" />

ExempIoProgressDiaIogActivty.java
public class EemploProgressDialogActivity extends Activity {
private static nal String URL = "http://livroandroid.com.br/imgs/livro_android.png";
private Progressbialog dialog;
@0verride
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_eemplo_progress_dialog);
// Abre a janela com a barra de progresso
dialog = ProgressDialog.show(this,"Exemplo",
"Buscando imagem, por favor, aguarde...", false,true);
downloadImagem(URL);
}

// Faz o download da imagem em uma nova thread


private void downloadImagem(nal String urlImg) {
new Thread() {
@0verride
public void run() {
try {
// Faz o download da imagem
URL url = new URL(urlImg);
Inputtream in = url.openStream();
// Converte a InputStream do Java para Bitmap
nal Bitmap imagem = BitmapFactory.decodeStream(in);
in.close();
// Atualiza a tela
204 Google Android - 4 edio
atualizaInagen(inagen);
} catch (IOEception e) {
// Una aplicao real deveria tratar este err0
Log.e("Erro ao fazer o download: ", E-9tM5S99()@)
}

}.start();
}

private void atualizaImagem(nal Bitmap imagem) {


run0nUiThread(new Runnable() { // Este cdigo necessrio, pois foi aberta uma thread
@0verride
public void run() {
// Fecha a janela de progresso
dialog.disniss();
Inageview ingview = (InageView) ndViewById(R.id.ing);
ingview . setInageBitnap(inagen) ;
}} );
}

Para o exemplo funcionar, declare a permisso INTERNET no arquivo AndroidManifest.xml.

AndrodManifest.xmI
<manifest . . . />
uses-permission android:nane="android.pernission.INTERNET" />
<application ... />
</manifest

A gura Z7 mostra a janela de progresso aberta enquanto a aplicao est fazendo


o download da imagem em segundo plano. Depois que o download concludo,
o mtodo disniss() da classe ProgressDialog chamado para fechar a janela e a
imagem exibida.
A parte do cdigo que faz o ProgressDialog teoricamente simples, mas esse exempl0
mostrou dois problemas que voc vai encontrar ao criar qualquer funcionalidade
que acesse a internet.
1. obrigatrio iniciar uma thread para fazer qualquer operao de I/O, como
acessar a internet, ler arquivos e consultar banco de dados, ou qualquer ope
rao demorada. Se a thread no for criada, dependendo do caso, o Android
pode lanar uma exceo ou a aplicao pode mostrar o erro ANR (Android
Not RSP0dig). Para mais detalhes, consulte o captulo 10, sobre threads.
Captulo 7 I Interface grca - View 205
2. No Android, cada aplicao executa em um nico processo, e cada processo
contm uma thread dedicada. Essa thread tambm responsvel por desenhar
e tratar todos os eventos da interface grca, conhecida popularmente como
UI Thread ou Main Thread. Existe uma regra no Android que diz: somente a
UI Thread pode atualizar a interface, ou seja, somente ela pode chamar qual
quer mtodo que vai atualizar uma view Por isso, neste exemplo foi utilizado
o mtodo run0nUiThread(runnab1e) para sincronizar o cdigo que vai atualizar
a view com a UI Thread. Na prtica o mtodo runOnUiThread(runnab1e) faz com
que o Runnable passado como parmetro execute na UI Thread. Se voc no
zer isso a aplicao vai lanar uma exceo. Para mais detalhes sobre esse
assunto, consulte o captulo 10, sobre a classe Handler.

., . l V

A
v.

Goo Ie
Aprenda a criar aplicaes para dispositivos mveis 5
com o Android SDK `

H OVGGC Ricardo R. Lncheta

Figura Z7 - Exemplo de Pr0gressDialog.

7.13 ProgressBar - barra de progresso


A classe android.wdget.ProgressBar utilizada para exibir uma barra de progresso
na tela, que pode durar por tempo indeterminado ou no. Com uma barra de
progresso, possvel incrementar o valor da barra, para ela ser preenchida aos
poucos, medida que o processamento vai terminando. Dessa forma, possvel
dar ao usurio uma ideia de quando determinada tarefa ser concluda.
A seguir, veremos um exemplo que utiliza a classe ProgressBar.
206 Google Android - 4 edio
Qi /res/layout/activity__exempIo_progressbar.mI
?ml version="1.B" encoding="utf-8"?>
<LinearLayout mlns:android="http://schemas.android.com/apk/FGS/3"dfd"
android:layout_width="match_parent" android:layout_height="wF6P_C"tet"
android:orientation="vertical" android:padding="16dp">
<TetView android:tet="Barra de Progresso"
android:layout_width="wrap_content" android:layout_height="wFD_C"t@t" />
ProgressBar android:id="@+id/barraProgresso"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent" android:layout_height="wfD_C0"@t"
android:nax="100" />
<Button android:id="@+id/bt0K" android:tet="Simular Tarefa"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
</LinearLayout

Nota: o atributo style="?android:attr/progressBarStyleHorizontal" no ProgressBar aplica


o estilo da barra de progresso. Caso esse estilo no seja adicionado, o ProgressBar
vai exibir uma animao de uma bolinha girando.

Observe que o atributo android:ma="100" dene o valor mximo da barra de pro


gresso. Por isso, no cdigo demonstrado a seguir, o valor ser incrementado de
O a 100. Para atualizar a barra de progresso, usado o mtodo setProgress(valor).

ExempIoProgressBarActivity.java
public class EemploProgressBarActivity extends Activity {
private static nal String TAG = "livro";
private ProgressBar mProgress;
@0verride
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_exemplo_progressbar);
// Barra de Progresso
nProgress = (ProgressBar) ndViewById(R.ld.barraProgresso);
Button b = (Button) ndViewById(R.id.bt0K);
b.set0nClickListener(new Button.0nClickListener() {
@0verride
public void onClick(View view) {
new Thread(new Runnable() {
public void run() {
for (int i = 0; i <= 100; ++) {
}

l
Captulo 7 I Interface grca - View 207

}});

i rl
}
}

}).start();
nal int progress = i;
// Atualiza a barra de progresso
run0nUiThread(new Runnable() {

});
try {
public void run() {

}
Log.d(TAG,">> Progress: " + progress);
mProgress.setProgress(progress);

Thread.sleep(200);
} catch (InterruptedEception e) {}

Log.d(TAG,"Fim.");

Nesse cdigo, uma thread criada para simular o processamento, e para demo
rar um pouco foi feito um Thread.sleep(200), que coloca a thread para dormir por
ZOO milissegundos a cada iterao. A gura 728 mostra o resultado com a barra
de progresso sendo atualizada. Lembre-se de que, se voc executar o projeto de
exemplo deste captulo no emulador, a barra de progresso ser vermelha, que foi

r
mag;is31zz l r
a cor definida para "accent color" do tema Material.

Progressor Progresslar
1.rV._i
Barra de Progresso Barra de Progresso l
s

r Simular Tarefa Simular Tarefa ;


1

J -_ ssss_ suuWsu,__-_______. _u_i

Figura Z8 - Exemplo de ProgressBa1:


4

4
208 Google Android - 4' edio
7.14 Toast - alertas rpidos
A classe androd.wdget.Toast utilizada para inostrarlcrtas
a S Para o usurio. Cada
alerta pode ser visualizado na tela por um tempo curto, especificado pela constante
Toast.LENGTH_SHORT, ou por um tempo longo se utilizar a constante Toast.LENGTH_LONG.
A forma mais simples de criar um alerta com o m todo Toast .makeTet(conteto,
mensagem, tempo):

Toast toast = Toast.makeText(ths, "Teste de Mensagem", Toast.LENGTH_5H0RT);


toast.show();

Na maioria dos casos, somente o mtodo anteriorj suciente para exibir men
sagens de alerta para o usurio. Entretanto, pode ser que seja necessrio exibir
um alerta com uma interface mais complexa. Para isso, a classe Toast contm o
mtodo setVew(vew), o qual pode ser chamado para congurar a View que ser
exibida no alerta, que pode ser simplesmente uma imagem definida pela classe
Imagevew ou mesmo uma tela com um layout complexo.
Por exemplo, para criar um alerta que no lugar de algum texto exiba uma imagem,
poderamos utilizar o seguinte trecho de cdigo:
Imagevew imagen = new ImageVew(ths);
imagen.setImageResource(R.drawab1e.smile);
Toast toast = new Toast(this);
toast.setVew(magen);
toast.setDuraton(Toast.LENGTH_LONG);
toast.show();

Observe que o mtodo setVew(vew) pode receber qualquer subclasse de View,


inclusive um gerenciador de layout, o que permite exibir um alerta com uma
interface bem customizada.

Nota: um toast aquele alerta rpido muito conhecido por desenvolvedores e


usurios do Android. Esse alerta no tem vnculo com o que foi ou est sendo
executado, de forma que o usurio pode continuar fazendo o que quiser no
celular. Por exemplo, no aplicativo do Gmail, logo depois de enviar um mal` um
toast mostra uma mensagem de que o email est sendo enviado. Mas voc pode
continuar usando o celular normalmente, pois o toast apenas uma mensagem
de informao sem estado.
Captulo 7 I Interface grca - View 209
7.15 AlertDialog - alertas para o usurio conrmar
A classe Toast que estudamos anteriormente mostra uma mensagem temporria
com a qual o usurio no pode interagir. Se for necessrio que o usurio pressione
no boto OK do alerta, ou responda uma pergunta do tipo Sim ou No, podemos
utilizar a classe AlertDialog.
Builder builder = new AlertDialog.Builder(this);
builder.setIcon(R.drawable.ic_launcher);
builder.setTitle("Titulo");
builder.setMessage("Mensagem");
builder.setPositiveButton("Sim", new Dialoglnterface.0nClickListener() {
public void onClick(DialogInterface dialog, int which) {
Toast.makeTet(getBaseContet(), "Clicou em Siml", Toast.LENGTH_SHORT).show();
return;
}});
builder.setNegativeButton("No", new Dialoglnterface.0nClickListener() {
public void onClick(DialogInterface dialog, int No) {
Toast.makeText(getBaseContet(), "Clicou em Sim!", Toast.LENGTH_SHORT).show();
return;
}});
AlertDialog dialog = builder.create();
dialog.show();

A gura Z9 mostra o resultado do alerta desse cdigo. O alerta obriga o usurio


a pressionar o boto Sim ou No, o que diferente do Toast, que exibe temporaria
mente a mensagem e desaparece.

Toggleutton '
t. mw
SpinnerMula: . , Check e Radio

Mensagem Progressialog .
No Sim, ProgressBar
AlertDialog
, . Clicou em Sim!
L|stV|ew -

Listview ~ exemplo imagem

Figura Z9 -Alerta com botes de sim e no.


210 Google Android - 4 edio
7.16 Layoutlnater - inando um arquivo XML
H' , H
A classe android.view. Layoutlnater e utilizada pa ra converter um arquivo XMLpara um
objeto do tipo view; o que conhecido pelos desenvolvedores como lnarum layout ,
O Layoutlnater um servio do sistema e deve ser recuperado com o seguinte codigo:
Layoutlnater inate = (Layoutlnater)
context.getSystemService(Contet.LAYOUT_INFLATER_SERVICE);

Nesse caso, o context uma referncia para a classe Activity, ou muitas vezes e o
this. Tambm podemos utilizar 0 seguinte atalho para obter 0 Layoutlnater.
Layoutlnater inate = Layoutlnater.from(context);

Depois de obter o Layoutlnater, basta chamar o mtodo inate(id,parent), o qual


recebe o id do arquivo XML desejado e retorna uma instncia de um objeto do
tipo View. O seguinte cdigo mostra como inar o arquivo /res/layout/inate_teste.xml
e retornar um objeto do tipo View que pode ser utilizado no cdigo. Isso permite
criar uma view como XML e inar o objeto, em vez de utilizar diretamente a API.
View view = (View) LayoutInater.from(this).inate(R.1ayout.inate_teste, layout, false);

O caso de uso mais comum do Layoutlnater para criar as views de um adapter;


por exemplo, para preencher os componentes ListView e ViewPager.

7.17 ListView

A classe android.widget.ListView um dos componentes visuais mais utilizados e


representa uma lista na tela. O exemplo a seguir mostra um arquivo de layout
com um ListView.

/res/layout/actvity_exempIo_|istview.xmI
<?xn1 version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:1ayout_width="match_parent" android:1ayout_height="match_parent"
android:orientation="vertica1" android:padding="16dp" >
<ListView android:id="@+id/listview"
android:layout_width="match_parent" android:1ayout_height="0dp"
android:1ayout_weight="1"
android:1ayout_margin="10dp" /
<Vew

android:1ayout_width="natch_parent" android:1ayout_height="z@dp"
android:background="@co1or/primary" /
</LinearLayout
Captulo 7 I Interface grca - View 2"
Quem fornece os dados para preencher o Listview um adapter, que uma classe que
implementa a interface android .widget . ListAdapter. Opcionalmente podemos estender
a classe android.widget.BaseAdapter que j implementa essa interface e deixa poucos
mtodos abstratos para terminarmos a implementao. O cdigo a seguir mostra um
adapter que vai preencher o ListView com uma lista que tem os nomes dos planetas.
Para cada planeta ser criada uma vievig que nesse exemplo um simples Textview.
Veja os comentrios no cdigo para entender o que faz cada mtodo do adapter.

SimpIesAdapter.java
public class SimplesAdapter extends BaseAdapter {
private String[] planetas = new String[] { "Mercrio", "Vnus", "Terra", "Marte",
"Jpiter","Saturno", "Urano", "Netuno", "Pluto"};
private Context context;
public SimplesAdapter(Context context) {
SUDer();
this.contet = context; // O context necessrio para criar a view
}

@0verride
public int getCount() {
return planetas.length; // Retorna a quantidade de items do adapter
}

@0verride
public Object getItem(int position) {
return planetas[position]; // Retorna o objeto para esta posio
}
@0verride
public long getItemId(int position) {
return position; // Retorna o id do objeto para esta posio
}

@0verride
// Retorna a view para esta posio
public View getView(int position, View convertview, ViewGroup parent) {
String planeta = planetas[position];
Textview t = new TextView(context);
oat dip = 56;
oat densidade = context.getResources().getDisplayMetrics().density; // Densidade
// da tela
int px = (int) (dip * densidade + 0.5f);
t.setHeight(px);
t.setTet(planeta);
return t;
}

}
212 Google Android - 4 edio
. _ , - .-, .. zo e definindo a
~ 1 ` ` ado diretamente
-.. ..-.-.-.. - s, conforme
U codigo do adapter esta criando um Textview por Pmffama

. -u 50
altura como 5Odp. Veja no codigo que 0 numero 50 nao L utilll
para definir a altura do Textview, pois isso traria resultados Cllffemff fl
resoluao e densidade da tela do dispositivo. Por isso, essc calculo converte dip
para 5Opx. Mas nem sempre 5Odp 5Opx, pois 0 f5Ulf3d0 da 0nVf5a0 P) C
ser lOOpx, l50px, 200px etc., conforme a densidade da tela. Por isso a conversao e
necessaria. Mas no se preocupe com isso agora, estou apenas alertando sobre um
problema comum. Ns vamos estudar esse assunto em mais detalhes no capitulo
30, sobre como criar aplicativos compatveis com diferentes tamanhos de telas.
Para nalizar o exemplo, segue o cdigo-fonte da activity Para preencher a lista,
preciso chamar o mtodo setAdapter(adapter) do Listview informando o adapter.
A lista ter a quantidade de linhas que o adapter retornar no metodo getCount().

ExempIoListViewActivity.java
public class EenploListViewActivity extends Activity inplements 0nItemClickListener {
protected static nal String TAG = "livro";
private Listview listview;
@0verride
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_exenplo_listview);
// Listview
listview = (tistview) ndViewById(R.id.listview);
listView.setAdapter(new SinplesAdapter(this));
listview.set0nItenClickListener(this);
}

public void onItemClick(AdapterView<? parent, View view, int idx, long id) {
// Objeto selecionado, que neste caso era de um array de strings
String s = (String) parent.getAdapter().getItem(idx);
Toast.makeTet(this, "Texto selecionado: " + s + ", posio: " + idx,
Toast.LENGTH_SHORT).show();
}

Ao clicar em algum item da lista, o mtodo onItenClick() ser chamado, informan


do a posio e o id do objeto selecionado. Com base nisso, podemos recuperar o
objeto selecionado no cdigo. Ao executar esse exemplo, voc ver o Listview no
centro e na parte interior da tela uma view quadrada que preenchi com o fundo
azul (mesma cor da action bar), conforme
a figura 7.lO. No cdigo do arquivo de
layout, veja que a altura do Listview foi definida co mo Gdp, para o Listview respeitar
Captulo 7 n Interface grca - View 213
o peso que lhe foi atribudo e esticar at onde ele pode, respeitando essa view
que est localizada na parte inferior do layout. Se o Lstvew estivesse com a altura
como match_parent, ele iria esticar sem respeitar os outros componentes, e a view
de baixo seria jogada para fora da tela.

* 1. I
Parabns! Voc acabou de fazer o primeiro exemplo de ListViev\g um dos compo

.-. .
nentes mais utilizados em aplicativos.

1 I
-.. _ _zll
1 Mefcm
Vnus
Q H... ,la. .l_pop.. r,,, _.-, 1

, gtn,
Jgne-

5 Urano

l Texto selecionado: Terra, posio; 2

l
I

Figura Z10 - Listlew.

No cdigo desse ltimo exemplo, o mtodo getVew() da classe Simp1esAdapter que


zemos est criando o TextVieW pela API, o que no o recomendado. O ideal
sempre criar uma view utilizando um arquivo XML e inflar esse layout com a
classe LayoutInater. Vamos ento criar o seguinte layout para o adapter:

/res/layout/adapter_simpIes.xmI
<?xml version="1.0" encoding="utf-8"?>
<LnearLayout xmlns:android="http://schemas.androd.com/apk/res/android"
android:1ayout_width="match_parent" androd:1ayout_heght="wrap_content" >
<TextView android:id="@+id/text"
android:layout_width="wrap_content" android:layout_height="50dp" />

Feito isso, altere o cdigo do mtodo getVew() para inflar o layout. Depois de fazer
isso, o resultado ser o mesmo de antes, mas desse jeito o cdigo ca bem mais
organizado. Nem sempre o layout do adapter ser to simples; o recomendado
sempre separar a interface em arquivos XML.
214 Google Android - 4 edio
gfu SimpIesAdapter.java

public class SimplesAdapter extends BaseAdapter {

@Override
public View getView(int position, View convertview, VIGWGFOUD Df@t) {
String planeta = planetas[position]; .
View view = Layoutlnater.fron(context).inate(R.layout.adapter_siD1S P3f@t flS);
Textview t = (Textview) view.ndViewById(R.id.tet);
t.setTet(planeta);
return view;
}

Note que no cdigo XML do arquivo /res/layout/adapter_simples.xml foi denida a


altura do TextView como 5Odp, que a notao da medida de densidade do Android.
Dessa forma, conforme a resoluo da tela do dispositivo, 5Odp ser convertido
para 5Opx, 75px, 100px etc. Foi isso que zemos no cdigo quando utilizamos a
API, mas aqui no XML basta utilizar a notao dp e tudo feito automaticamente.

7.18 ListVew com adapter customizado


No prximo exemplo, vamos criar uma lista de objetos e exibi-la no Listview com um
adapter customizado. A classe android .widget . Listview um dos componentes visuais
mais utilizados e representa uma lista na tela. Entender esse exemplo vital para seu
futuro como desenvolvedor Android, at porque demonstra a utilizao de adapters.
O exemplo a seguir mostra um arquivo de layout com um ListView:

/res/Iayout/activity_exempIo_Iistview.xmIz
<?ml version="1.0" encoding="utf-8"?>
<LinearLayout nlns:android="http://schenas.android.com/apk/res/android"
android:layout_width="natch_parent" android:layout_height="match_parent"
android:orientation="vertical" android:padding="16dp"
<ImageView android:src="@drawable/ic_launcher"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
<ListView android:id="@+id/listview"
android:layout_width="match_parent" android:layout_height="Gdp"
android:layout_weight="1"
android:layout_margin="10dp" />
<InageView android:src="@drawable/ic_launcher"
android:layout_width="wrap_content" andro`d:l h
1 ayout_ eight="wrap_content" />
Captulo 7 n Interface grca - View

Para preencher a lista do Listview, vamos criar uma lista de planetas, entao crie a
classe Planeta. Para o exemplo funcionar, copie as guras de cada planeta e 1ns1ra na
pasta /res/drawable. Elas podem ser encontradas no projeto de exemplo deste capitulo

P|aneta.java
public class Planeta {
public String nome;
public int img; // R.drawable.xx
public Planeta(String nome, int img) {
this.nome = nome;
this.img = img;
}

public static List getPlanetas() {


List planetas = new ArrayList();
I
panetas add \ I`lW P-aneta(" Mercrio", R.drawable.planeta_01_mercurio))
planetas addl [new P-aneta(" Vnus", R.drawable.planeta_02_venus));
planetas add\ HGW P-aneta(" Terra", R.drawable.planeta_03_terra));
p-anetas addl\ HGW P-aneta(" Marte", R.drawable.planeta_04_marte));
I
panetas add \ new P-aneta(" Jpiter", R.drawable.planeta_05_jupiter));
p-anetas add(new P.aneta(" Saturno", R.drawable.planeta_06_saturno));
panetas add(new Paneta(" Urano", R.drawable.planeta_07_urano));
p.anetas add(new P-aneta(" Netuno", R.drawable.planeta_08_neptuno));
planetas add( new P-aneta(" Pluto", R.drawable.planeta_09_plutao));
return planetas;
}

A classe Planeta permite criar a lista de planetas. No cdigo-fonte da activity basta


criar essa lista e congurar o adapter no Listview.

ExempIoListViewActivity.java
public class EemploListViewActivity extends Activity implements 0nItemClickListener {
protected static nal String TAG = "livro";
private Listview listview;
private List planetas;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_eemplo_listview);
// Listview
listView = (Listview) ndViewById(R.id.listview);
planetas = Planeta.getPlanetas();
216

}
}. listView.setAdapter(new PlanetaAdapter(this, planetas))
listview.set0nItemClickListener(this);
Google Android - 4 edio

public void onItemClick(AdapterView<?> parent, View VEW, Int 1d 1"9 ld) {

}
Planeta p = this.planetas.get(id);
Toast.nakeTet(this, "Planetaz " + D.0W, TOGS-LENGTH_5H0RT)-5h0W();

Para 0 cdigo compilar, precisamos criar a classe de adapter.

PIanetaAdapter.java
public class PlanetaAdapter extends BaseAdapter {
private nal Context context;
private nal List planetas;
public PlanetaAdapter(Context context, List planetas) i
this.contet = context;
this.planetas = planetas;
}

@0verride
public int getCount() {
return planetas != null ? planetas.size() : 0;
1

@0verride
public Object getIten(int position) {
return planetas.get(position);
}

@0verride
public long getItenId(int position) {
return position;
}

@0verride
public View getView(int position, View convertview, ViewGroup parent) {
// Ina a view
View view = Layoutlnater.fron(contet).inate(R.layout.adapter_planeta, parent, false);
// Faz ndViewById das views que precisa atualizar
Textview t = (Textview) view.ndViewById(R.id.tNonePlaneta)
Inageview img = (lnageview) view.ndViewById(R.id.ingPlaneta);
// Atualiza os valores das views
Planeta planeta = planetas.get(position);
t.setTet(planeta.nome);
img.setImageResource(planeta.img);
Captulo 7 nz Interface grca - View

// Retorna a view deste planeta


return view;
}

O arquivo de layout do adapter pode ser visualizado a seguir:

/res/layout/adapter_pIaneta.xmI
<?xml version="1.0" encoding="utf-8"?>
<LnearLayout xmlns:android="http://schemas.androd.com/apk/res/androd"
android:layout_width="natch_parent"
androd:layout_height="?android:attr/listPreferredItemHeight"
android:gravtty="center_vertcal"
android:orientation="horlzontal">

<ImageView android:id="@+id/ingPlaneta"
android:layout_wdth="0dp" android:layout_height="wrap_content"
android:layout_weight="3"
android:src="@drawable/planeta_03_terra" />

<TetVew android:id="@+id/tNomePlaneta"
androd:layout_wdth="0dp" android:layout_hetght="wrap_content"
android:layout_weight="7"
android:layout_marginLeft="10dp" android:textColor="#000G00" />

Dica: no cdigo do layout XML, a altura da view do adapter foi denida como
androd:layout_height="?android:attr/lstPreferredItenHeight". Isso acessa um atributo de
dimenso nativo do Android, que retorna a altura recomendada pela plataforma
para uma linha do ListVieW.

A figura Z11 mostra o resultado desse exemplo com a lista de planetas.

Nota: existe uma classe especial de activity que a ListActivtty, a qual j declara
seu prprio layout com um nico Listview. Mas eu prefiro sempre estender minhas
classes diretamente de activity e adicionar um Listview no layout, pois assim
o layout ca mais exvel e voc tem controle do que est fazendo. Para sua
consulta, a MainActivity do projeto de exemplo deste captulo filha de ListActivity.
218 Google Android - 4 edio

* M
V

" l Marte

z . ..- ~
-, z.i___.T-.
"z~
-z zV z.~- ~i..
_ -..M

Figura ZH - ListView.

7.19 GridVew

A classe androd.wdget.GrdVew utilizada para exibir os componentes em formato de


grid com linhas e colunas. Seu uso mais clssico para exibir vrias imagens como em
um lbum de fotos. A seguir, podemos ver um exemplo de como utilizar um Grdvew.

/res/Iayout/activity_exempIo_gridview.xmI
<?m1 verson="1.0" encodng="utf-8"?>
<LnearLayout m1ns:androd="http://schemas.androd.com/apk/res/androd"
androd:1ayout_wdth="match_parent" androd:layout_heght="match_parent"
androd:orentation="vertca1" android:paddng="16dp" >
<TetVew

androd:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content"
androd:text="Eemp1o de GrdVew:" />
GridView android:d="@+id/grd1"
androd:1ayout_wdth="match_parent" android:layout_heght="match_parent"
androd:paddng="1@dp" androd:gravty="center"
androd:vertca1Spacng="1Gdp" BDFO2h0FZOt81SDCg:"ldp"
android:numCo1umns="auto_t" android:co1umnwidth="40dp" />
</LnearLayout>

Na tag <GrdVew> so denidos alguns parmetros de espaamento e nmero de


colunas. Nesse exemplo, os parmetros relevantes so:
Captulo 7 1 Interface grca - View 219
Parmetro Descrio
columnwidth Largura de cada coluna do grid. Sempre utilize a notao com dp
(densyindependentrnxekl
numColuns Nmero de colunas do grid. Nesse caso, foi informado o valor auto_fit
para ajustar automaticamente o nmero de colunas com base na largura
da coluna.

Para exibir as imagens no Gridview, necessrio criar um adapter que retorne uma
lista com as imagens necessrias. Sendo assim, foi denido no arquivo XML um
id para o Gridview, para que ele possa ser recuperado no cdigo.
A seguir, temos uma classe de adapter que recebe um array de imagens e cria um
Imageview para cada uma.

ImagemAdapter.java
public class ImagemAdapter extends BaseAdapter {
private Context ctx;
private nal int[] imagens;
public AdaptadorImagem(Context c, int[] imagens) {
this.ctx = c;
this.imagens = imagens;
}
@Override
public int getCount() { return imagens.length; }
@0verride
public Object getItem(int posicao) { return posicao; }
@0verride
public long getItemId(int posicao) { return posicao; }
@Override
public View getView(int posicao, View convertview, ViewGroup parent) {
// Ina a view que est no XML
View view = LayoutInater.from(this.ctx).inate(R.layout.adapter_imagem_gridview,
parent,false);
// Utiliza o ndViewById para obter o Imageview
Imageview img = (ImageView) view.ndViewById(R.id.img);
// Altera a imagem (baseado na posio do array)
img.setImageResource(imagens[posicao]);
// Retorna a view
return view;
}

Para o cdigo compilar, crie este arquivo XML de layout que ser inado pelo
cdigo do adapter. Veja que o nome do arquivo segue a notao adapter_nome.xml.
no Google Android - 4' edio
f /res/layout/adapter_imagem.xml
<?ml version="1.9" encoding="utf-8"?
<LinearLayout mlns:android="http://schemas.android.com/apk/FGS/"dfd" H
android:layout_width="wrap_content" android:layout_hei9ht="wrap-C"te"t >
<ImageView android:id="@+id/img" android:layout_width="wFD_Ct@"t"
android:layout_height="wrap_content" />

Nota: observe que o mtodo getView(posicao,view,parent) deve retornar a View que vai ser
inserida em determinada posio do Gridview. O conceito de adapters (adaptadores)
muito utilizado no Android, e quanto antes voc entender isso melhor. Note que
para criar a view foi inflado um layout XML com ajuda da classe Layoutlnater.

Para nalizar o exemplo, este o cdigo da activity que vai preencher o Gridview
com um array de imagens. A classe ImagemAdapter deve retornar a quantidade de
imagens que precisam ser adicionadas no Gridview.

ExempIoGridViewActvity.java
public class EemploGridViewActivity extends Activity {
// Array com os ids das imagens
private int[] imagens = { R.drawable.smile1, R.drawable.smile2,
R.drawable.smile1, R.drawable.smile2, R.drawable.smile1,
R.drawable.smile2, R.drawable.smile1, R.drawable.smile2 };
@0verride
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
getActionBar().setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.activity_eemplo_gridview);
Gridview grid = (Gridview) ndViewById(R.id.grid1);
grid.set0nItemClickListener(onGridViewItemClick());
// Informar o adapter para preencher o Gridview
grid.setAdapter(new ImagemAdapter(this, imagens));
}
// Evento ao clicar no item do grid
private 0nItemClickListener onGridViewItemClick() {
return new 0nItemClickListener() {
public void onItemClick(AdapterView<? pargnt, View V, int poScao,10ng id) {
_ Y IS, magem selecionada: " +
Toast.makeText(EemploGridViewActivit .th` "I
posicao, Toast.LENGTH_SHORT).show();
}

};
}

}
Captulo 7 I Interface grca - View 221
Observe que o mtodo set0nItemC1ckLstener(lstener) da classe Grdvew pode ser
utilizado para tratar os eventos gerados caso o usurio selecione e pressione al
guma imagem. No mtodo onItemC1ck(parent,vew,poscao,d), possvel recuperar
qual imagem foi selecionada. A gura 112 exibe o resultado desse exemplo.

G
00 0
Exemplo de GridView:

Figura Z12 - Exemplo de Gridl/iew.

Nota: durante o livro, vamos estudar outros exemplos sobre os adapters. Se voc
perceber, uma simples classe que deve implementar o mtodo getCount() para
informar quantas views existem, e depois o mtodo getVew() chamado N vezes
para criar cada view. Seja para criar um grid com Grdvew ou uma lista com Lstvew
, os adapters so gurinhas carimbadas no desenvolvimento para Android e so
responsveis por fornecer o contedo e preencher esses componentes.

7.20 Gallery
Sabe quando voc abre o lbum de fotos no Android e faz o gesto de swipe (deslizar)
para os lados para ver as fotos? A classe androd.wdget.GaU.ery faz justamente isso.
Nesse exemplo, criaremos uma galeria de imagens com as fotos de alguns planetas.

/res/Iayout/activity_exempIo_gaIIery.xm|
<?xml verson="1.0" encodng="utf-8"?>
<LnearLayout m1ns:android="http://schemas.androd.com/apk/res/androd"
222 Google Android - 4 edio
android:layout_width="match_parent" android:layout_hei9ht="match-parentH
android:orientation="vertical" >
<TetView
android:layout_width="wrap_content"androidzlayout _h 01 9ht="wrap_content"
android:text="Eemplo de Gallery" android:gravity="centF" />
<Gallery android:id="@+id/gallery"
android:layout_width="match_parent" androidzlayout _h 6i ht="match_parent"
9
android:gravity="center" />

A forma de usar o Gallery idntica do Gridview. Este prximo exemplo cria uma
galeria de fotos a partir de um array de imagens.

ExempIoGaIIeryActivty.java
public class ExemploGalleryActivity extends Activity {
// Planetas
private int[] imagens = { R.drawable.mercurio, R.drawable.venus,
R.drawable.terra, R.drawable.marte, R.drawable.jupiter,
R.drawable.saturno, R.drawable.urano, R.drawable.netuno,
R.drawable.plutao };
@0verride
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_exemplo_gallery);
Gallery g = (Gallery) ndViewById(R.id.gallery);
g.setAdapter(new ImagemAdapter(this, imagens));
9.set0nItemClickListener(onGalleryItemClick(this));
}

private 0nItemClickListener onGalleryItemClick(nal Context context) {


return new 0nItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int posicao,long id) {
// Exemplo de alerta com Toast com uma view dentro
// Geralmente o Toast apenas um texto
Imageview imgview = new ImageView(contet);
imgview.setImageResource(imagens[posicao]);
Toast t = new Toast(context);
t.setView(imgView);
t.show();
}

};
}

}
Captulo 7 I Interface grca - View

Observe que, para deixar o exemplo mais completo, o mtodo onItemC1ick( parent
v1ew,poso,d) foi implementado para recuperar a posio da imagem selecio
nada. Nesse caso, a classe Toast foi utilizada para exibir um alerta na tela, que na
verdade desenhado pelo Imagevew da imagem selecionada.

Nota: a mesma classe ImagemAdapter que utilizamos para preencher as imagens


do Grdvew foi utilizada agora com o Gallery, exatamente da mesma forma. Isso
mostra a grande utilidade dos adapters. Outro detalhe importante sobre a classe
Gallery que ela foi recentemente descontinuada (deprecated) pelo Google, que
recomenda utilizar a classe ViewPager que tem o mesmo comportamento, mas
bem mais flexvel. Demonstrei o Gallery para seu aprendizado, mas vamos
sempre usar o ViewPager na prtica.

A gura 113 mostra a galeria de fotos com o planeta Terra selecionado. Para testar
os exemplos, navegue na galeria fazendo o gesto de swipe para os lados.

Lxemplo de Gallery

Figura ZJ3 - Exemplo de Gallery.

7 21 ViewPager
A classe androd . support.v4.vew.VewPager faz parte da biblioteca de compatibilidade
No Android Studio, a biblioteca de compatibilidade configurada no arquivo
app/buildgradle.
Lembrando que a biblioteca de compatibilidade baixada pelo SDK Manager pelo
item Android Support Library e recomenda~se sempre mant-la atualizada. Depois de
224 Google Android - 4 edio
. . o as c . - - f ~ ~ / d `d_sdk/ext
baixar o item Android Support library, a biblioteca sera instalada em an~ roz biblioterzzz/
android/support. L, voce vai encontrar as pastas v4 v7 C v13 que Sa 714 HS
dc compatibilidade com cada API Level, conforme mostra a gura .

A ideia bsica sobre as bibliotecas de compatibilidld QU _*42@1<f;ff*V@l


com Android 1.6 (API Level 4), a v7 compativel com o An roi I . . eie
7), e por a vai. A classe android.support.v4.vew.Vi.ewPager, como 0 proprio nome 0
pacote j informa, est na biblioteca v4.
H /\n<l:ii <lK ~'lf!!ld(i^Y
'
liiiz i ._ l
Willi l"|`

i 5. 4
\*\(l'll*(l l<1`vv A

pc fi Il i C instiiieti
/\Yii`lf(`iil 4-' (`\l l l

L1p.
1T1lfl
l install llcl
I _ '1l!`il
l lv Q i il <)f`l(l''l('l l 'll fl
l

l
l

V1 `

~ ' woiict zw
hi
\ bixo-x!~af\ V I I 1 b L' Rigrpitg. H;
\p\[( \,_. 3 \.i\.*"t"
l 5 `^.i(\~.l lt?

Figura Z14 - Biblioteca de compatibilidade.

A dependncia da biblioteca de compatibilidade v4 deve ser adicionada no arquivo


app/buildgradle. Feito isso voc poder utilizar as classes da biblioteca de suporte
que cam no pacote android.support.v4, como por exemplo a classe android.support.
v4.view.VewPager.

app/buiId.grad|e
apply plugin: 'con.android.appllcation'

dependencias {
conpile leTree(dir: 'libs', include: ['*.jar']) // Adiciona arquivos .jars da pasta
I/ libs como dependncia
Captulo 7 I Interface grca - View 225
// Dependncia da biblioteca de compatibilidade v4
compile "com.android.supportzsupport-v4:21+"
l

Com a biblioteca de compatibilidade v4 congurada no projeto, vamos partir


para a prtica, portanto crie o seguinte arquivo de layout.

/res/layout/activity_exempIo_view_pager.xmI
<?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" >
<TetView
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:tet="Eemplo de ViewPager" />
<android.support.v4.view.ViewPager android:id="@+id/viewPager"
android:layout_width="match_parent" android:layout_height="wrap_content" />

Note que a tag precisa conter o nome completo da


classe, pois esse componente no faz parte dos nativos do Android. Para preencher
as views do ViewPager, deve-se informar um tipo especial de apdater, que uma imple
mentao da classe android.support.v4.view.PagerAdapter. Lembre-se de que um adapter
apenas retorna uma view para determinada posio. Dessa forma, se o adapter disser
que existem dez pginas, ele dever retornar uma view para cada uma delas.
No prximo exemplo, vamos criar a classe ImagemPagerAdapter que estende
android.support.v4.view.PagerAdapter e retorna a view que ser utilizada para criar a
galeria de fotos, da mesma forma que zemos com o Gallery.

|magemPagerAdapter.java
public class AdaptadorImagem_ViewPager extends PagerAdapter {
private Context ctx;
private nal int[] imagens;
public ImagemPagerAdapter(Context c, int[] imagens) {
this.ct = c;
this.imagens = imagens;
}

@0verride
public int getCount() { // Quantidade de views do adapter
return imagens != null ? imagens.length : 0;
l
226 Google Android - 4 edio
@Override _ _
// Ina a view ,
public Object instantiateltem(ViewGroup container, int D51t1") {

View view = Layoutlnater.from(this.ct).inate(R-lYU-adapter-Imagem'


container,false);
Imageview img = (lmageview) view.ndViewById(R.id.im9);
img.setImageResource(imagens[position]); .
((ViewGroup) container).addView(view); // Adiciona ao layout ViewGrouD

@Override _
}
return view;

public void destroyItem(ViewGroup container, int position, Object view) { // Remove a


// view do container
((ViewPager) container).removeView((View) view);
}

@0verride
public boolean isViewFromObject(View view, Object object) {
// Determina se a view informada igual ao object retornado pelo instantiateltem
return view == object;
}

cada mtodo:
Mtodo ` Descriao p
Para auxiliar o entendimento do cdigo-fonte dessa classe, segue a explicao de

getCount Retorna a quantidade de elementos do adapter.


instantiateltem Retorna um objeto-chave chamado de key object, que utilizado
internamente para controlar o ViewPager. Durante a implementao
do mtodo instantiateltem, voc deve adicionar a view criada no
container, que o ViewGroup informado como parmetro. Para sim
plicar, voc pode retornar diretamente a view neste mtodo 011
outro objeto-chave qualquer.
isViewFromObject Nesse mtodo, voc deve validar se a view informada como par
metro corresponde ao objeto-chave informado. Esse objeto-chav
aquele que foi retornado do mtodo instantiateltem. i
destroyltem Este mtodo chamado para destruir uma view associada a um
objeto-chave. Portanto, as views que foram adicionadas ao container
devem ser removidas aqui. importante que esse mtodo seja S0
brescrito e o super.destroyItem() da classe-me no seja chamado. A0
navegar pelo ViewPager, o Android pode ir destruindo as views que
nao estao sendo utilizadas para economizar memria.
Vamos Finalizar o exemplo e escrever o cdigo da activity que vai utilizar o ViewPa9@f~
Captulo 7 I Interface grca - View 227
ExempIoVewPagerActivity.java
public class EemploViewPagerActivity extends Activity {
// Planetas
private int[] imagens = { R.drawable.mercurio, R.drawable.venus,
R.drawable.terra, R.drawable.marte, R.drawable.jupiter,
R.drawable.saturno, R.drawable.urano, R.drawable.netuno, R.drawable.plutao };
@0verride
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_exemplo_view_pager);
ViewPager g = (ViewPager) ndViewById(R.id.viewPager);
g.setAdapter(new ImagemPagerAdapter(this, imagens));
g.set0nPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {// Informa que determinada pgina
// foi selecionada
Toast t = Toast.makeTet(getBaseContext(), "Imagem: " + position,
Toast. LENcTH_sHoRT);
t.show();
}

@Override
public void onPageScrolled(int position, oat position0ffset,
int position0ffsetPiels) {
}

@Override
public void onPageScrollStateChanged(int state) {
}

});
}

Ao executar esse exemplo, o funcionamento ser idntico ao do componente


Gallery. Note que, ao navegar de uma pgina para outra no ViewPager, um alerta
exibido com o Toast, porque o mtodo onPageSelected(position) chamado. Dessa
forma, podemos realizar alguma ao sempre que o usurio navegar entre as
views desse componente.
A classe ViewPager uma das mais utilizadas no desenvolvimento para Android, e
se integra muito bem com a famosa API de Fragments que ainda vamos estudar
durante o livro. Lembre-se de que a classe Gallery foi descontinuada pelo Google,
e o recomendado sempre utilizar o ViewPager.
228 Google Android - 4 edio
Provavelmente voc ja deve ter visto alguns aplicativos que usam t2lbS, C0m0 por
exemplo: o Google Play, o qual permite navegar pelas tabs utilizando os gestos de
swipc lateral. lsso tambm feito com o ViewPager, inclusive vamos fazer exatamente
isso ao desenvolver o aplicativo dos carros.

Dica: uma biblioteca muito conhecida por desenvolvedores Android a


VewPagerIndcator (http://viewpagerindicator.com). Ela funciona em conjunto com o
ViewPager e contm vrias views utilitrias. Por exemplo, bem comum em aplicativos
ter aquele marcador com bolinhas em baixo do ViewPager, pa ra indicar a pgina que
voc est visualizando. Essa biblioteca contm esse marcador e muito mais.

7.22 ViewPager + TitIeStrip ou TabStrip


No exemplo anterior, mostramos a gura de cada planeta no ViewPager, mas no
mostramos o nome do planeta em lugar nenhum.
Para mostrar o nome do planeta, podemos implementar a interface
OnPageChangeLstener para monitorar a troca de pginas do ViewPager, e nesse caso
mostrar 0 nome do planeta em algum Textvew. Mas 0 ViewPager j tem duas classes
que facilitam justamente esse trabalho, a classe androd.support.v4.vew.PagerTt1eStrp
e androd.support.v4.vew.PagerTabStrp.

Para ter uma ideia do que estou falando, a gura Z15 mostra o resultado ao utilizar

'ile1
O ViewPager com o PagerTt1eStrp.

.
Rf,'lj}`~* :II \v.Ic":f\ zT `
.. .- M -` .... _
..._j
f'~.,~.v,@_ 3`_Qg~;_.. _. .!Z<._\_;>'_f. > sz _,w ,, -,.;; z. j

Figura 115 - PagertleStrip e PagerTabStrip.


Captulo 7 I Interface grca - View 229
A classe android . support.v4.view.PagerTitleStrip mostra um ttulo acima do ViewPager
facilitando o entendimento do usurio. J a classe android . support.v4.view. PagerTabStrip
mostra um indicador com uma tab e inclusive permite ao usurio clicar na tab para
navegar entre as pginas. Para utilizar um desses componentes, basta inclu-lo como
lho do ViewPager no layout. O exemplo a seguir mostra como utilizar o PagerTabStrip.

/res/layout/activity_exempIo_view_pager__tab_strip.xmI
<?ml version="1.0" encoding="utf-8"?>
<LinearLayout . . . >
<android.support.v4.view.ViewPager android:id="@+id/viewPager"
android:layout_width="match_parent" android:layout_height="wrap_content" >
<android.support.v4.view.PagerTabStrip android:id="@+id/viewPagerTabStrip"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_gravity="top" android:background="#33b5e5"
android:textColor="#fff" />

Para mostrar o ttulo acima do ViewPager, preciso que a classe do adapter imple
mente o mtodo getPageTitle(int page) que deve retornar o ttulo da pgina. Nesse
exemplo, vamos usar novamente a classe Planeta, a qual tem o nome do planeta
e o inteiro com o recurso da imagem. A classe do adapter recebe uma lista de
planetas e retorna a view que contm a foto do planeta, tambm retorna o nome
do planeta no mtodo getPageTitle(int page).

PlanetasPagerAdapter.java
public class PlanetasPagerAdapter extends PagerAdapter {
private Context ctx;
private nal List planetas;
public PlanetasPagerAdapter(Context c, List planetas) {

// Para o cdigo completo veja nos exemplos do livro. Esse um adapter simples.
// O importante o mtodo getPageTitle(page) retornar o titulo.
@0verride
public CharSequence getPageTitle(int page) {
// Titulo para mostrar no PagerTitleStrip ou PagerTabStrip
Planeta planeta = planetas.get(page);
return planeta.nome;
}

}
230 Google Android - 4' edio
, . . . - -. _ . . . a ~ ` a acia
O codigo da activity somente cria a lista dc planetas c configura ptcr no
ViewPager. O resto tudo automatico, c o ttulo retornado pelo adapter sera mos
trado na tah do viewPager.

i'=fi MainActivity.java

public class EenploViewPagerTabStripActivity extends Activity {


@0verride
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_eenplo_view_pager_tab_strip);
getActionBar().setDisplayHoneAsUpEnabled(true);
// Planetas
List<Planeta planetas = Planeta.getPlanetas();
// ViewPager
ViewPager g = (ViewPager) ndViewById(R.id.viewPager);
g.setAdapter(new PlanetasPagerAdapter(this, planetas));
}

Dlca: para alterar por programao a pgina que o ViewPager est mostrando,
utilize o metodo setCurrentIten(int page).

7.23 lmageSwitcher
Outra classe bastante til a android.widget.ImageSwitcher, utilizada para mostrar
uma imagem aps outra de forma animada.

) /res/Iayout/activity_eempIo_image_switcher.mI
<?nl version="1.0" encoding="utf-8"?>
LinearLayout nlns:android="http://schenas.android.con/apk/res/android"
android:layout_width="match_parent" android:layout_height="natch_parent"
android:orientation="vertical" android:padding="10dp" >
Button android:id="@+id/btProina"

BHVO21Y0Ut_wldth="wrap_content" android:layout_height="wrap content"


android:tet="@string/proxima" / _
<ImageSwitcher android:id="@+id/inageSwitcher"
6f\dI'd=165/out_width="natch_parent" android:layout_height="natch parent"
android:layout_nargin="10dp" /> _
/LinearLayout>
Captulo 7 I Interface grca - View 231
ExemplolmageSwtcherActivity.java
public class ExemploImageSwitcherActivity extends Activity {
// Planetas
private int[] imagens = { R.drawable.mercurio, R.drawable.venus,
R.drawable.terra, R.drawable.marte, R.drawable.jupiter,
R.drawable.saturno, R.drawable.urano, R.drawable.netuno, R.drawable.plutao };
private ImageSwitcher imageSwitcher;
private int idx = 0;
@0verride
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.activity_eemplo_image_switcher);
// Congura o ImageSwitcher e os efeitos
imageSwitcher = (ImageSwitcher) ndViewById(R.id.imageSwitcher);
imageSwitcher.setFactory(new ImageSwitcher.ViewFactory(){
@0verride
public View makeView() {
Imageview img = new ImageView(getBaseContet());
img.setScaleType(ImageView.ScaleType.FIT_CENTER);
img.setLayoutParams(new ImageSwitcher.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
return img;
}

});
imageSwitcher.setInAnimation(Animationtils.loadAnimation(this,android.R.anim.fade_in));
imageSwitcher.set0utAnimation(Animationtils.loadAnimation(this,android.R.anim.fade_out));
View btProima = ndViewById(R.id.btProima);
btProxima.setOnClickListener(new 0nClickListener() {
@0verride
public void onClick(View arg0) {
if(idx == imagens.length) { idx = 0; }
imageSwitcher.setImageResource(imagens[idx++]);
}

});
}

Para a classe ImageSwitcher funcionar, necessrio chamar o mtodo setFactory(viewFactory)


informando uma implementao de android .widget.ViewSwitcher .ViewFactory. Essa
interface dene o mtodo makeView() que deve retornar uma View, que a imagem
que deve ser exibida. Ao chamar o mtodo setImageResource(imagem) no ImageSwitcher,
232 Google Android - 4 edio
e _ , _ _ , - , . . -ala sem re ue o bom)
a .animacao c realizada. Neste exemplo .i imagem L altci e P Q t
Prxima foi' clicado. contiorinc a ligura 7.l(w.

PXME

Figura 7.l - Excnzplo dc IrnageSwitchex

7.24 WebView

Se por algum motivo voc precisar exibir uma pgina web dentro do aplicativo. a
classe androd .webktwebvew pode ser til. O funcionamento desse componente iden
tico ao browser do Android, isso porque internamente utilizada a engine \VebKit.
Essa e uma das views mais utilizadas nos aplicativos, principalmente pelos adeptos
da criao de aplicativos hbridos que utilizam HTML5 e JavaScript para criar a
interface grca. Primeiramente, para ter acesso a internet, declare a permisso
INTERNET no arquivo AndridMani>st..\m1. Quando o usurio baixar o aplicativo dd
Google Play; sero mostradas para ele todas as permisses que o aplicativo precisa
utilizar, e baseado nisso o usuario pode aprovar ou no a instalaao.

AndroidManifest.xmI
<manfest . . . />
uses-permission android:name="android.permission.INTERNET" /
<applcaton ... />
</manfest>

Para demonstrar 001110 exibir uma pgina de internet usando o Nebvew, vamo
criar um simples exemplo que exibe a pgina www_1W(,a,,dm(_mm_,,_
Captulo 7 I Interface grca - View 233
/res/Iayout/activity_exempIo_webview.xmI
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xnlns:android=http://schemas.android.com/apk/res/android" ... />
<FraneLayout android:layout_width="match_parent" android:layout_height="match_parent" >
<webView android:id="@+id/webview" android:layout_nargin="10dp"
android:layout_width="natch_parent" android:layout_height="match_parent" />
ProgressBar android:id="@+id/progress" android:layout_gravity="center"
android:layout_width="wrap_content" android:layout_height="wrap_content" />

ExempIoWebViewActivity.java
public class EemplowebViewActivity extends Activity {
@0verride
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_eemplo_webview);
nal Nebview webview = (webview) ndViewById(R.id.webView);
nal View progress = ndViewById(R.id.progress);
progress.setVisibility(View.INVISIBLE);
webview.loadUrl("http://www.livroandroid.com.br");
webview.setwebViewClient(new webViewClient(){
@Override
public void onPageStarted(webView view, String url, Bitmap favicon) {
progress.setVisibility(View.VISIBLE); // pgina comeou a ser carregada
}

@Override
public void onPageFinished(webView view, String url) {
progress.setVisibility(View.INVISIBLE); // pgina foi carregada
}

@Override
public void onReceivedError(webView view, int errorCode,String description,
String failingUrl) {
// Erro ao carregar a pgina do webview (endereo errado, ou erro de conexo)
}

});
}

A gura Z17 mostra a pgina do site do livro aberta dentro do webview. Veja que
utilizamos o FrameLayout para inserir o ProgressBar por cima do webview. Enquanto
a pgina est sendo carregada, o ProgressBar ca visvel para mostrar a animao.
234 Google Android - 4 edio
l wmpiu de Wvbvrrw """l'k"1"W"hV""'
Google \
di o Android 3
E nbqoig
livro campeao em vendas e
i no Android
l mcgmondado para iniciantes
jTpau, qugm deseja aprender
concertos principais doos
desenvolvimento para Andr0d
Explica do bsnco ao avanado.
confira o sumalio

Figura Z17 - Exemplo do WebView.

Nota: lembre-se de que necess rio declarar a permisso INTERNET para o WebView
funcionar.

O WebView realmente muito simples de ser utilizado. Nem vou me estender


muito nos exemplos porque muito fcil encontrar material sobre o webvew. Ape
nas para ter uma ideia, voc at pode enviar um HTML em string e pedir para o
webvew renderizar a pgina.
webvew.loadDataNthBaseURL( " ", "<font color=' blue' >HTML aqu" ,
Iltext/htm1'II,IIUTF_8II, Illl);

Geralmente os aplicativos deixam esse cdigo HTML em arquivos texto dentro


do projeto, ento basta ler o arquivo e converter para string. Outra tcnica que e
muito utilizada injetar cdigo JavaScript no Nebvew, para os mais variados ns,
e isso pode ser feito assim:
webVew.getSettings( ) . setJavaScrptEnabled(true);
webVlew.loadUrl( "javascrpt:alert( 'Oi leitor ' ); " );

E5525 tcnicas de injetar cdigo HTML ejavaScript no Nebvew esto fazendo a festa
dos adeptos de HTML5 e aplicativos hbridos, e com base nelas que populares
frameworks como o PhoneGap funcionam. Esse tipo de abordagem permite que
desenvolvedores com vasta experiencia em web entrem no mercado dos aplicativos
IUVS, C UfiliZ1n cdigo HTML para criar a interface grca

1e,_.
Mas no estou aqui para discutir sob re este assunto nativo vs. HTML. O objetivo
deste livro ensinar a criar aplicativos nativos para Android alm de eitplieir o
principais conceitos da plataforma.
Captulo 7 I Interface grca - View 235
7.25 Movimentando uma imagem pela tela com touch
Neste prximo exemplo, vamos movimentar uma imagem pela tela, utilizando
touch screen. No emulador voc poder utilizar o mouse para movimentar a ima
gem e naturalmente em um celular real voc vai arrastar a imagem com o dedo.
A classe View contm o mtodo onTouchEvent(MotionEvent), que sempre chamado
quando um toque na tela realizado. Como parmetro temos um objeto do tipo
MotionEvent, com o qual possvel recuperar as posies x e y do toque.
public boolean onTouchEvent(MotionEvent event) {
oat x = event.getX();
oat y = event.getY();
return true;
}

Esse mtodo deve retornar true caso a view tenha tratado o evento, ou false se
para delegar a tarefa para as outras views da tela. Se nenhuma view tratar o
evento, o mesmo mtodo ser chamado na activity responsvel pela tela. A seguir
podemos ver um exemplo completo que permite mover a imagem do boneco do
Android pela tela. A gura foi inserida em /res/drawable/android.png.

TouchScreenView.java
public class TouchScreenView extends View {
private static nal String TAG = "livro";
private Drawable img;
int x, y;
private boolean selecionou;
private int larguraTela;
private int alturaTela;
private int larguralmg;
private int alturalmg;
public TouchScreenView(Context context) {
super(context, null);
// Recupera a Imagem
img = context.getResources().getDrawable(R.drawable.android);
// Recupera a largura e altura da imagem
larguralmg = img.getIntrinsicwidth();
alturalmg = img.getIntrinsicHeight();
// Congura a View para receber foco e tratar eventos de teclado
setFocusable(true);
}

@0verride
Google Android - 4 edio

// Chamado quando a tela redimensionada, ou iniciada...


protected void onSizeChanged(int width, int height, int oldw, int oldh) {
super.onSizeChanged(width, height, oldw, oldh);
this.larguraTela = width;
this.alturaTela = height;
= width / 2 - (larguralmg / 2);
y = height / 2 (alturalmg / 2);
Log.i(TAG, "onSizeChanged x/y: " + + "/" + y);
}

@0verride
// Desenha a tela
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Fundo branco
Paint pincel = new Paint();
pincel.setColor(Color.wHITE);
canvas.drawRect(0, 0, larguraTela, alturaTela, pincel)
// Dene os limites/rea para desenhar
img.setBounds(x, y, + larguralmg, y + alturalmg);
// Desenha a imagem
img.draw(canvas);
}

@0verride
// Move a imagem
public boolean onTouchEvent(MotionEvent event) {
oat = event.getX();
oat y = event.getY();
Log.i(TAG, "onTouchEvent: x/y > " + x + "/" + y);
switch (event.getAction()) {
case MotionEvent.ACTION_DONN:
// Inicia o movimento se pressionou a imagem
selecionou = img.copyBounds().contains((int) x, (int) y);
break;
case MotionEvent.ACTION_MOVE:
// Arrasta o boneco
if (selecionou) {
thS = (t) X - (larguralmg / 2);
thS-Y = (t) y - (alturalmg / 2);
}

break;
case MotionEvent.ACTION_UP:
// Finaliza o movimento
selecionou = false;
Captulo 7 n Interface grca - View 237
break;
}

// O invaiidate vai chamar o mtodo onDraw(canvas) novamente


inva1idate();
return true;
}

Feito isso, crie uma activity e congure esta view no mtodo setContentView(view):

TouchScreenViewActivity.java
public class TouchScreenViewActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new TouchScreenView(this));
}

Nota: neste exemplo, ao tocar na tela a coordenada x/y da gura atualizada.


Ao chamar o mtodo invaiidate(), o Android vai desenhar a view novamente
chamando o mtodo onDraw(canvas).

Ao testar o exemplo no emulador, utilize o mouse para simular o touch screen e


mover a imagem (Figura 718).

e cz 1
Mova o objeto com o touch
l

_l

Figura Z18 - Exemplo de touch screen.


238 Google Android - 4 edio
_ ._. _ .,,.-.f z esnatelae
7.26 Desenho manual com a classe Canvas

s criar nossa r 1
O Android tem varias classes prontas para desenhar compm Cada
uma dessas classes e uma subclasse de V1.ew.Scra que podLm0 P Pfld
classe-lha de View? A resposta sim.

Neste prximo exemplo, criaremos um componente customizado que ser uma


subclasse direta de android.view.View e aprenderemos a desenhar quadrados, ci rculos
e linhas coloridas na tela. Para isso, sobrescreveremos 0 mtOd0 eDI'W(CVS), 0
qual chamado pelo Android para desenhar um componente (VICW). As classes
Textview, EditText, Imageview, Button etc. j implementam esse mtodo, mas chegou
a hora de criarmos nosso prprio componente do zero e desenhar tudo na tela.
Para isso CI`aI'ITlOS uma classe chamada Mlhvlew, COfOI`I`l1 demonstrado a SgLllI'I

MinhaView.java

package br.com.livroandroid.cap07_view.canvas
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class Minhaview extends View {
// Para denir a cor RGB
private Paint pincelvermelho;
private Paint pincelPreto;
private Paint pincelAzul;
public MinhaView(Context context) {
this(context,null);
}

public MinhaView(Context context, AttributeSet attrs) {


super(context, attrs);
setBackgroundColor(Color.LTGRAY);
// Vermelho
pincelvermelho = new Paint();
pincelvermelho.setARGB(2SS, 255, 0, 0)
// Preto
pincelPreto = new Paint();
pincelPreto.setARGB(255, 0, 0, 0);
// Azul
pincelAzul = new Paint();
pincelAzul.setARGB(255, 0, 0, ZSS);
Captulo 7 I Interface grca - View 239
// Congura a View para receber foco e tratar eventos de teclado
setFocusable(true);
}

@0verride
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Desenha um quadrado
canvas.drawRect(20, 20, 200, 200, pincelAzul);
// Desenha uma linha
canvas.drawLine(200, 200, 400, 400, pincelPreto);
// Desenha um circulo
canvas.drawCircle(400, 400, 100,pincelVermelho);
}

Observe que existem dois construtores na classe: um que recebe apenas o


android.content.Context e outro que tambm recebe o android.util.AttributeSet. Se
essa classe for utilizada diretamente pela API Java, o construtor com apenas o
parmetro android.content.Context chamado; caso contrrio, se for utilizada pelo
XML, o Android chamar o construtor com os dois parmetros. Se for necessrio, a
classe android . util.AttributeSet utilizada para ler os parmetros denidos no XML.
A classe Minhaview implementa o mtodo onDraw(Canvas) e desenha um retngulo, uma
linha e um crculo, utilizando os mtodos da classe android.graphics.Canvas. Alm das
coordenadas x e y para desenhar as formas geomtricas, foi criado um objeto do
tipo android.graphics.Paint, o qual dene as cores do desenho. Para isso, foram cria
dos trs objetos Paint (pincel) e para cada um foi atribuda uma cor RGB diferente.
Para utilizar essa nova classe em algum arquivo de layout, basta inserir uma tag
com seu nome completo, neste caso: .
/res/Iayout/activity_exempIo_minha_view.xmI
<?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" >
<br.com.livroandroid.cap07_view.canvas.MinhaView
android:id="@+id/canvas"
android:layout_width="match_parent" android:layout_height="match_parent" />
240 Google Android - 4 edio
._~. .~~~ .a izaaoaeaaer
editor, mesmo com um

_ _' ~'
te' a voce. acnv' ~
A gura 7.19 mostra a pr-visualizao dessa tela pelo ll ._ d t I 'I I
componente desenhado manualmente. Como a pre visua li; 1 / J 1 u o
suficiente para entender o exemplo, nao criaremos aqui nen uma^ ir;
que utilize esse arquivo de layout. Isso ca como exercicio par

Figura Z19 - Componente customizado desenhado manualmente.

7.27 Nunca utilize pixels


j foi falado anteriormente para nunca utilizar pixels ao definir tamanhos de
views e espaamentos em arquivos de layout XML. O mesmo conceito vale ao
desenhar cdigos utilizando a API de Canvas.
g P CI
No exem lo anterior, utilizamos o se uinte cdi o ara desenhar um uadrado:
// Desenha um quadrado
canvas.drawRect(20, 20, 200, 200, pnceIAzu1);

No entanto, esse cdigo que desenha o quadrado tem um problema, pois esta
usando valores xos em pixels. Isso vai trazer resultados diferentes em telas qu
apresentem diferentes resolues e densidade. O correto seria utilizar valores em
dp (density independent pixel) e converter o valor para pixel utilizando a den
sidade de cada tela. Por exemplo, 100px pode ser convertido para 75px, 100px.
15Opx, 200px, 300px, conforme a densidade da tela do aparelho. Essas converse
PfC5am SCF feiras HO COdig0 para garantir que o resultado ser o mesmo ind
pendentemente da resoluo e densidade da tela.

A 5gU1f,P0dm05 VU Uma funo que converte o valor de dp para pixel.


Captulo 7 n Interface grca - View 241
// Converte um valor em dp para pixels
public oat toPixels(oat dip) {
Resources r = getContet().getResources();
oat densidade = r.getDisplayMetrics().density; // Densidade da tela
int px = (int) (dip * densidade + 0.5f);
return dip;
}

Portanto, o correto para desenhar um quadrado utilizar um cdigo assim:


// Desenha um quadrado
canvas.drawRect(toPiels(20), toPiels(20), toPiels(200), toPiels(200), pincelAzul);

Acredito que talvez seja cedo para explicar por que isso necessrio. Prero
continuar o livro com conceitos simples e focar no que voc vai utilizar no dia a
dia. Ainda temos alguns captulos essenciais pela frente e logo vamos comear o
desenvolvimento do aplicativo dos carros.
A metodologia do livro explicar cada conceito de uma vez. Quero focar nos
conceitos principais, aqueles de que, tenho certeza, voc vai precisar no dia a dia.
Conheo muitos desenvolvedores que fazem aplicativos e no sabem explicar o
que dp (density independent pixel), por isso creio que esse assunto possa car
para depois. Para mais detalhes, leia o captulo 30, sobre como suportar diferentes
tamanhos de telas.
f . CAPTULO
Fragments
\_`_
`

Um fragment um componente de cdigo reutilizavel, responsavel por criar sua


prpria view, tratar os eventos e gerenciar o seu proprio c0ntUClO.
Uma activity pode conter um ou mais fragments que podem ser adicionados no
layout como se fossem views, porm os fragments tm comportamento proprio
e so autogerenciveis.

8.1 Como surgiram os fragments no Android 3.0 Honeycomb


Com a popularizao dos tablets e a grande busca dos usurios por esses dispo
sitivos, surgiu a necessidade de otimizar e customizar o Android para usufruir ao
mximo do tamanho de tela disponvel nesses dispositivos. Foi assim que surgiu
o Android 3.0 Honeycomb, a primeira verso do Android otimizada para tablets.
E com o Honeycomb, nasceu a API de fragments, originalmente utilizada para
organizar a grande tela dos tablets em pequenos componentes, mas aos pouc0S
todos perceberam que fragments eram muito mais do que isso.
Ao desenvolver para smartphones, geralmente temos uma tela simples, pois 0
espao disponvel limitado. Dessa forma, o modelo tradicional com uma activity
e uma view, no qual a activity controla toda a lgica da tela, sempre atendeu HS
necessidades. Mas criar aplicaes para tablets uma arte, e vrios fatores precisam
ser levados em Considerao. O mais importante de todos o tamanho da tela.
que dv ser 3Pf0ViI8Cl0 ao mximo. Muitas vezes, necessrio preencher a rel
com varias views, cada uma com um contedo diferente

A gura 8.1 compara o modelo tradicional de uma aplicao do tipo lista e dl'
lhes, executando no smartphone Qu tablet N o smartphone, duas telas precisam
ser utilizadas para fazer a navegao da lista para a tela de detalhes No tablet
podemos utilizar uma nica tela, aproveitando ao mximo o espag disponvel.

242
. * si 5
(aPtuIo 8 n Fragments 243
_jp.rAA
^V"Y ^ Avify B Activity A mm aos fragmems
Figura 8.1 - Fragment que divide a tela em pedaos.

Dica: se quiser ver um aplicativo com duas telas de lista e detalhes, abra o projeto
Planetas-Activity no Android Studio. Neste projeto, temos uma lista de planetas
e ao clicar na lista o planeta mostrado em outra_tela. Durante este captulo,
vamos trabalhar em cima deste exemplo.

Nesta gura podemos ver que a aplicao para smartphone utiliza a Activity A
e a Activity B como de costume. Na aplicao para tablet, como existe somente
uma tela, ou seja, apenas uma activity dentro dela o contedo separado em dois
fragments. Basicamente um fragment um componente que pode ser inserido
dentro da activity e esse componente ca responsvel por:
1. Criar a view para preencher determinado espao, alm de controlar o seu
estado e tratar os eventos.
2. Pela lgica de negcios para buscar os dados de um web service ou banco
de dados.

3. Por atualizar a sua view de forma independente da activity e de qualquer


outro fragment da tela.
Eu costumo dizer que um fragment uma mnactvty, que tem sua prpria view e
lgica, alm de ser responsvel por gerenciar seu prprio conteudo.

Nota: talvez este captulo seja um pouco avanado neste momento, tudo depende
do seu perl. O fato que antes de comearmos a desenvolver o aplicativo dos
carros euaproveito
assunto 7
preciso explicar o que alguns
para abordar um Fragment. E como
topicos mais vou ter de
avanados, explicr
como ta etso
e gerenciamento de estado do fragment. Mesmo que o assunto seja um pouco
avanado continue estudando, pois o livro servira de consulta mais tarde.
7
244 Google Android - 4 edio
8.2 Fragments muito mais do que dividir a tela em duas partS
lista explicao de duas activities no smartphone C llP"5 Ulflil 1lL`UVll)' corn
dois lragments no tablet e classica. inclusive a documentacao ohctal do Androitl
utiliza este exemplo. Mas isso mttitas vezes confunde quem esta ilPl`L`ll(iL`ll\ii>. e
alguns desenvolvedores acham que liragments servem para dividir a teia em duas
partes nos tablets.
Na verdade, os lragments sao componentes que ficam espalhados na tela. sendo
qtte um de setis principais objetivos e reutilizar a logica entre a versao 1i.}Til"ii\I`;
e tablet. Para comearmos bem, vamos acabar com o mito de que um if' fiflift
serve para dividir a tela do tablet em duas partes. A ligura 8.2 mostra algo z_litt-tarte.
a tela do tablet dividida em tres partes.
:rf

{' l,ivtoAnlrt-id

imgnwnt' Tivxt 2

Frqmentl TQIIO 1.

Frqmontl Tutu 3.

if' sz-i~*'
:guru i em tres ttrres rom rttgrnenls.
t z ttn tt_v ivididti

lisse tipo de tela e bem connnn nos tablets, pois assim voc consegue mostrar
varias iniormat`es ao mesmo tempo para o usuario, /\ principal razo de quebrar
a tela em pedaos e para simplihcar o codigo da activity, pois podemos dizer que
cada tragment e responsavel por determinada parte do layout.
A figura 83 mostra um dos meus primeiros projetos para tablets, qurmdti Qgmdei
lragments pela primeira vez. Neste aplicativo, cada pedao da tela e um fragment.
1 .' \ \_' .. t \-~, , ',_ `f .:. . _ _ _
cmo a lista de indices, lista de notcias, lista de videos. area central. grtilice
etc ( s beneltuos dessa organizaeao sao imensos, pois os lragments deixam tt
Captulo 8 n Fragments

cdigo muito mais lim o e o '


I' z
P 8an1Zad0 P018 Cada componente faz apenas o que
tem de fazer. Cada parte da tela um gm
245

P0nente separado e independente dos


outros. Por exemplo, a lista de ndices busca os d d os em um web service e cria

, pois e a no f
o Lstview de forma independente do resto da tel a. No nal, o cdigo da activity
fica bastante reduzido ou talvez vazio ` 1 8
de1ga do aos fragments. az nada, e todo o trabalho e

,,
f,ml-...-_.zz
,,:*~Ef- 2 ff yr,

Ponrusus
A TUTORIAL

saem:
wasrts j

3M&FBO'E.

Figura 8.3 - Dividindo a tela em fragments.

A gura 8.4 mostra outro aplicativo para tablet, em que mais uma vez este conceito
de dividir a tela em partes foi utilizado. Cada parte um fragment, e novamente
isso ajudou a separar as responsabilidades e organizar o cdigo. Se um aplicati
vo desse tamanho fosse criado apenas 'com uma activity o XML de layout seria
imenso e o cdigo-fonte para gerenciar toda a lgica tambm. No entanto, com
fragments a activity apenas divide o seu layout em partes e insere cada fragment
no seu devido espao. Cada fragment por sua vez vai criar a view e gerenciar o
contedo. Simples, no ?
Trabalhar com fragments, porm, muito mais do que apenas separar a tela em
pedaos, pois um dos principais objetivos da API criar um componente de c
digo reutilizvel. Afigura
8.5 mostra uma aplicao compatvel com smartphones
d d afiaura
e tablets. A parte esquer g mostra a verso para tablets. Veja que o
tablet est mostrando a lista de ndices ein determinado local da tela. E na parte
da direita podemos ver a mesmaaplicao no smartphone, corn a mesma lista
h (iooqlv Android 4-'1111W
_\, \ \ _ \ . . 1..1 1 114 1.11.
1

, 1 1 .. . 1 .`\.1..1~1.
1 1 ._
11~111111111~ l'~l1' 1' 11111 1~\1'1111 '111 1111 \I1I 11 11~. 11.11 HH '111 ~' UI 1 ""~11

11
\ "\ 1 `\ \|(. `\( "
111111111111111111' 11-111111 .1\111~1\1.111|1111111|11.1111.1111111111`.11111 -HU 1 * 111111

111\1
1 111111 1 |`1l 1 1111 1 11 111111|11~ 1111 \\1~11~1~1\111 11111111-1'|'|l "1`1'1
1
1

1111 111 1\111111 11 11\ 111111111111 |111~1 1~..1 1111111111111 .11 11 1.l\1'111 |\.l|-1 1 111111111 1111 111
1

V" ` ' V 7 V N
1|n,. '
E1' kd 1
111.11 11111111111 1111 1.11111'l.

nu-zum-.~un.~..,..

vlmm UUOL (11I110\ -..... ,,A

^1`
______ _ _ ___ ___- --f_ ; ~ ~-_ ::f1;_^^

otl
' ` ,1zz1z
1 n-. :O
1;-:.\.fz
A Mvwuz..
>|11.11

u.u-4.1.4 14.z~-' -1 .5
PM (em H 1muu11u111\|- 111\M1 111111111 "\.'|l'\ 1111 _1gu~v- 1111 Riu ,mmu
lap 13
I\0\11~1 "I '\ 1 l 1 *" *' 7`<\ ` ` `\,\1; 1
x ` ` ' 1 1\\I\\\ \ ....
.nu - ' .`,,,,___,,,_,,,_,.. ,_ ,,._ _. _ _ _ ,.;,.1,__,. M`
7 h1num1 `
1 11.
A Mmh.
_11.1 \ h.
` ` 1.. \n:;\`..=Q1.
v 'up ,,_1._g,1,_ __, _ .J. ;
\l.J1I4y|J1 qm
1m11v~1oJ~ 1o111~ . ,_ ,, . . . .
NI11|n1|111
^ = ' "' "" ""*"1- 1 ' *' `V , pru
_ . ~ 11
1
:r-:~:_~ ~'~' ' Y-~fl\~_~^_~ ' _ _ _ _ :_ 7 _ _____v__

11111114
NUM:-u
'OHMm1\u
0.=q141w x4s111.
vuguw rw-.14|1\vu 111!
x mqu||4h1N\\vJ1 I1
1114 11.1 zmkmu O 11 1 Vnw u1.zz1vu 1 V'
_ ' ''"'
"'"
1ih\ll
um Bmw Jtanvoiudia ` 1-,
10.1 qzuu dr|||\wn\11 nv
.,,,
mniy npnu
r1qyn\u _, 41h-quo:
. _ 1nUudumm!-cilcul ' 11- ~
1- 1. AbAvzwuL\u
1hm.\h&-1
new
In--up U1 um k11donbc1| vou hn pano 00"'~*
111- 1 uvunwu anti 1'' L ml Hbaciu.
I uR\\$"M

11g11.11\.-1 1)11'111111111.!1'1.11'111111\1;1111'n1

1*1_Q11118.$ R1'11!111;.1111l.HW,(.,,,, .\. . ,_


^\111;111111~
(\ \\]`) z~_
I`h\\- l"`
- . `l`_*CI\\_"I\'iI`\`\Hl"
.-1 / 111. 111111 tl 111..111111111111'.111.1111l111111'.

`|
\ ` `\ \ ' 1 \ 1 \\
1

l[11|\.lll\11s lI11111\III11.11411115I11;1I`l|1|111 U h,u. Hb mU`. U uxh .u\1 111


.\
Captulo 8 I Fragments 247
Google Play que utiliza tabs na action bar. Ao selecionar uma tab, o contedo
do centro atualizado, as semvoce^ reparar ng f ~ entre telas.
eita a navegaao
J aprendemos no livroque
criar uma nova activi - .
Sempf que for aberta uma nova tela, necessrio
_ I I o ty mas neste caso o aplicativo permanece na mesma tela,
Pois e necessario
apnas O conteudotrocar
centralfque mostra a tab selecionada.
Por isso, ao utilizar tabs na action bar, o contedo da tela precisa ser um fragment,
ois um fra ment um co ~ . _
P g mP0nH que pode ser inserido, removido e substi

fl _
tudo de determ inado local do layout. Ao selecionar uma tab, basicamente um

9 ._
fragment substitudo por outro,

za W Q.
` ( z
Aws._ ~. z z- O* ~aeza
ll- iii!P P _ ` z~
CTERORS HOM roppggg mpmes WES ~
w
waities GAMES _ Io
i M *I afff*
i?zumz=@s
,_ ,HH,
Hacks ieferemce , _ _
1 ECE _
' ws.. L.
Hom "f'&...f...'; ;1-._ ,f
- ~ - _ ` _ _ _ ._ _ . . __ _ ,m ,a;z,,.z mp mn wma 7 PN0 TOP Fm rovoaossmc mv NEWPMI

Crzmfcs
., _, ` _ ~ . zw* Aplicativos Sociais 2 What Asp M g

Euction
***** -mw .nn _, _
.....

CIz.mmumz,atcn mstagram mzszme whatzzzp z


P (Twuter E Mssengcf

e r wtndfi. ._
Elhmmm T F! commendedfo You 5 F b < vi g

Figura 8.6 -Aplicativo do Google Play.

A figura 8.7 mostra o padro de navegao Navigation Drawer, muito utilizado nos apli
cativos modernos. S para dar uma ideia, o Gmail eYouTube utilizam esse padro,
que conhecido popularmente por menu lateral' Tal padro de navegao, da
mesma forma que as tabs, representam a navegao top-level do aplicativo com as
sees mais comuns. Nesse caso existe apenas uma activity pois, ao abrir o menu
lateral e selecionar uma opo, apenas o contedo central alterado, sem fazer a
navegao de telas. Na prtica, ao selecionar uma opo do menu, um fragment
substitudo por outro.
A gura 8.8 mostra outro caso no qual podemos utilizar um fragment, para
solucionar o problema de i nserir o banner na parte inferior da tela. Como esse
e ser inserido em todas as telas, o ideal que ele
banner um componente e dev
-lo no layout. O fragment sozinho vai criar a
seja um fragment, pois basta inseri
view e buscar o contedo necessrio para desenhar O b21Y1nf
Google Android -- 4 edio

zh
uu- """"" 1 n
"' `,:.
i
.z.2., "*"i**^~>.

Q 0(iVa' 1
O nV Q 4

|(\V n H --

._ vf

' #'=_ .
..$;.

!iAqum 8.7 ~- Mwm mm mL'(QUlI (IIIWUIL

'll{lll' 8.8 - /\l1..:!i1''nunumms.

a:cs~.;\;I ~ ._
h \F 'm
~. \1_lll\5 xnnplm um qu.u m1cnm5 uulwdl. A \l)I kh.
~ . .1 .\@\\*|'l. SIl\II`l|)hUHL' uu p.n.\
K ' 'm` sc ;\ w;~;
\ H \ m`m'/" h!
` ` ` ( , L` | ~
lulull/..n'u111px\c1m~. /\lllLlIIl\L'I\lL` |1\cs1\\s\z(,ux ,. W um] H ix l 1 U M
. Hk`UIH\'Il\l.l l -n ' ~ ' ~ ~' z z .
` '|I"' ~\1:~l.1 IL`Il\'Il)' cm um I`;\gl1\L`I\l' ;\ssim\ W
um Im vmc )I`k`\`I8.lI` r ~.\ w' V- - .~. o . . ..
* I 'U\Lll.\| x asa u|\1p|\c|1lc,nd<L~- |UmU_
Captulo 8 I Fragments 2 49
8.3 API de Fragments

Antes de comearmos a estudar os exemplos com cdigo-fonte, vamos aprender


as principais classes da API de Fragments,

android.app.Fragment

Classe que o fragment deve estender. necessrio sobrescrever o mtodo


onCreateView(inater, container,bundIe)}para.criar a vievv

android.app.FragmentManager

Classe que gerencia os fragments pela API. Contm os mtodos


findFragmentById(id) e findFragmentByTag(tag) utilizados para encontrar os
fragments no layout, de forma similar ao mtodo findviewById(id) que uma
activity utiliza para buscar uma view

android.app.FragmentTransaction

Classe utilizada para adicionar, remover ou substituir os fragments dina


micamente no layout.
Essas trs classes s podem ser utilizadas no Android 3.0 ou superiores, por isso
foi criada a biblioteca de compatibilidade v4, compatvel com Android 1.6 (API
Level 4) ou superior. Para congurar a dependncia para a biblioteca v4, basta
adicionar uma linha no arquivo app/builzigradle.

app/buiId.gradIe

dependencies {

// Dependncia da biblioteca de compatibilidade v4


compiie "com.android.supportzsupport-v4:21+"
I

.. - inavas.
Feito isso, podemos utilizar as classes da biblioteca de suporte que cam HO
ara manter a compatibilidade com verses anteriores,
pacote android.support.v4. P
recomenda-se utilizar as seguintes Cl21SSS, U0 lugar das
~ android.support.v4.app.FF9|@t

android.support.v4.app.FF9F\@tMaa9er

android.support.v4.DP-Ffa9etTra"SaCton
250 Google Android - 4' edio
. .__....de,.z
A hihlioteca
-_-._z,, ,..z
compatibilidade
`na
e dtstribuida
ere
existem odere~
pelo SDK M3 8 v `
.P Wber
atualizaoes, por isso recomendo que vote sempre verif-lue se HSOS
novas da hihlioteca.

Nota: neste livro, todos os exemplos de fragments utilizam a classe androtd.support_


v4.app.Fragment; lemhre-se desse detalhe ao escrever o codigo e testar os exemplos.

Para fechar o assunto, falta um pequeno detalhe. A classe Fragmentanager e uma


das principais classes da API e ela recuperada com o seguinte codigo dentro de
uma activity ou fragment.
android.app.FragmentManager fm = getFragmentManager();

O mtodo getFragmentManager() retorna a verso nativa da classe, ento no


podemos utiliz-lo. Por isso, todas as activities do projeto devem estender
android.support.v4.app.FragmentActvty ou android.support.v7.app.AppCompatActvty, que
contm o mtodo getSupportFragmentManager(), o qual retorna a classe de compatibilidade

androd.support.v4.app.Fragmentllanager fm = getSupportFragmentHanager();

Nota: a classe FragmentActi.vty me de AppCompatActivty. Portanto, sempre que voc


utilizar a classe AppCompatActivty para utilizar a action bar de compatibilidade,
ganhamos de brinde o acesso biblioteca dos fragments.

8.4 Hello World fragment


Para car mais fcil de entender o assunto, vamos ver um pouco de cdigo-fonte
e brincar um pouco com os fragments. Crie o projeto com o nome HelloFragments.
com a activity ManActvty e o template Blank Attivity.

Na activity principal no vamos fazer nada, e seu cdigo ser simples


conforme demonstrado a seguir. Note, porm, que ela dgvg ser filha de
androd.support.v4.app.FragmentActvty. Se voc quiser, pode configurar a depen
dncia da biblioteca v7 da action bar de compatibilidade e utilizar a classe
androd.support.v7.app.AppCompatActvity, pois a classe AppCompatActvty lha de
FragmentActvity. Ento, para estes exemplos, tanto faz_
Captulo 8 I Fragments
251

MainActivity.java
public class MainActivity extends d '
@0Verrde an r1d-SUPPOF-V4-pp.FragmentActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity nain)~
// 0 FragnentManager nececessrio para brincar com os fragnents

} android'supprtV4'app'Fragmentaaef fm = getSupportFragnentManaqer()~
}

Para utilizar a biblioteca de compatibilidade V4, congure o arquivo build gmdle


app/buiId.gradIe

dependencies {

conpile "con.android.support:support-v4:21+"
}

Feito isso, crie a classe Fragnentl conforme demonstrado a seguir.

Fragment1.java
public class Fragmentl extends android.support.v4.app.Fragnent {
@0verride
public View onCreateView(Layoutlnater inater, ViewGroup container,
Bundle savedlnstancetate) {
View view = inater.inate(R.layout.fragnent_1, container, false);
// O fragnent livre para ter qualquer lgica aqui
return view;
}

Note que essa classe lha de android.support.v4.app.Fragnent. Um fragment deve


criar e retornar a view no mtodo onCreate iew - ,
V' (inater, container,bundle) Aseguir
podemos ver o arquivo de layout que o fragment vai inar para retornar a view

/res/layout/fragment_1.xml
<?ml version="1.0"
tf-8"?> encoding="U _ N
<LinearLayout xmlns:android="hD// _HH
schenas.android.con/apk/res/android

andr0d_1ay0Ut wdth:"matCh parent" andr0id:layout_height= match_parent


252 Google Android - 4 digo
androd:orientaton="vertica1" androd:gravty="center">
<TextView
androd:id="@+d/text"
1 t ayou
android:1ayout_wdth="match_parent" androd: hei ht="wraD_Ct@f"
_9
android:gravity="center"
android:text="Fragment 1" />
</LnearLayout>

Com o fragment criado, basta adiciona-lo no layout da activity seja de lorma


esttica no XML ou dinamicamente pela API. Para adicionar um fragment no
arquivo XML de layout da activity utilizada a tag <fF9I'\t> f0fm9Cl0 a
largura e altura do fragment como se fosse uma view O atributo class recebe 0
nome completo da classe do fragment.
Nota: Eu particularmente no gosto de utilizar 0 Re1atveLayout.Veja que nos exem
plos do livro voc vai encontrar o LnearLayout ou FrameLayout como a raiz do layout.

/res/layout/activity_main.xml
<LnearLayout xmlns:androd="http://schemas.androd.com/apk/res/androd"
mlns:too1s="http://schemas.androd.com/tools"
androd:1ayout_width="match_parent" android:1ayout_heght="match_parent"
fragment android:id="@+d/fragi"
android:1ayout_width="match_parent" android:1ayout_heght="match_parent"
c1ass="br.con.Iivroandrod.cap09_he11ofragnents.Fragment1"
tools:1ayout="@1ayout/fragment_1" />
</LnearLayout>

Ateno: cuidado ao digitar o nome da classe do fragment no arquivo XML


da activity. Se voc errar o nome, a aplicao vai lanar um erro em tempo de
execuo. Note que o Android Studio inclusive ajuda a completar o nome da
classe para evitar erros. Outra dica , sempre depois de digitar o nome da classe.
segure a tecla Ctrl e clique com o mouse para abrir o arquivo. Se o arquivo da
classe abrir, est tudo ok.

A gura 8.9 mostra a pr-visualizao do arquivo da activity O segredo da pf'


-visualizao do layout o atributo tools:1ayout="@1ayout/fragment_1", que utilizadv
somente pelo editor visual e faz com que o layout do fragment seja inserido neste
local, apenas para fazer a pr-visualizao.
Captulo 8 I Fragments
253

HGU W Id? g

Figura 8.9 - Pr-visualizao.

Pronto! Se voc executar o projeto no emulador, deve ver a mensagem Hello World
Fragment na tela. Para fechar esse tpico, veja que o fragment tem um identificador
que foi declarado no layout.
<fragment androd:id="@+d/fragl" ...

Isso signica que em qualquer local do cdigo podemos recuperar esse fragment
com o mtodo fndFragmentById(d) da classe androd.support.v4.app.FragmentManager. O
cdigo a seguir demonstra como encontrar um fragment pelo id.

ManActvity.java
public class MainActtvty extends androd.support.v4.app.FragmentActivty {
@0verride
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentVew(R.layout.activty_ma);
F ntMana er();
androd.support.v4.app.Fragmentanager fm = 9f5UPPf"`t "a9' 9
Fr3gment1 frag1 = (Fragmenti) fm.ndFragmentById(R.td.frag1);
f rag1 ..vocePodeChama r0MetodoQuePrecsarA<IU( )5
}

}
254 Google Android - 4' edio
.. ,_.ultimo
komo _. , __exemplo,v:1mos
'vz]
r1APl ara adicionaru
Qdcmonstrarcomo
za do utiliza
la ouPm
lragment dinamicamente no layout. Nesse caso, fCm0 * g Y . . . ~ _ . radoa se uir.
da activity e dcixc o layout vazio, conforme demonst z 8

t /res/layout/activity_main.xml
<FrameLayout minszznr0i="hiipz//szhemz.anroi.com/pk/res/dfd"
mlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" androidzlayou _ 619
android:id="@+id/layoutFrag">
</span></span> <span class='ocr_word' id='word_1_80' title="bbox 804 1149 996 1200"><span class='xocr_word' id='xword_1_80' title="x_wconf -3">Fragment</span></span> <span class='ocr_word' id='word_1_81' title="bbox 1027 1147 1120 1190"><span class='xocr_word' id='xword_1_81' title="x_wconf -2">ser</span></span> <span class='ocr_word' id='word_1_82' title="bbox 1150 1144 1344 1189"><span class='xocr_word' id='xword_1_82' title="x_wconf -1">inserido</span></span> <span class='ocr_word' id='word_1_83' title="bbox 1374 1144 1468 1196"><span class='xocr_word' id='xword_1_83' title="x_wconf -1">aqui</span></span> <span class='ocr_word' id='word_1_84' title="bbox 1498 1154 1544 1185"><span class='xocr_word' id='xword_1_84' title="x_wconf 0">no</span></span> <span class='ocr_word' id='word_1_85' title="bbox 1573 1141 1718 1194"><span class='xocr_word' id='xword_1_85' title="x_wconf 0">layout</span></span> <span class='ocr_word' id='word_1_86' title="bbox 1751 1125 2170 1188"><span class='xocr_word' id='xword_1_86' title="x_wconf -8">"@+d/YOUFFHQ"</span></span> <span class='ocr_word' id='word_1_87' title="bbox 2235 1137 2304 1161"><span class='xocr_word' id='xword_1_87' title="x_wconf -5">"></span></span></span>
</p>
<p class='ocr_par'>
<span class='ocr_line' id='line_1_14' title="bbox 590 1227 934 1283"><span class='ocr_word' id='word_1_88' title="bbox 590 1227 934 1283"><span class='xocr_word' id='xword_1_88' title="x_wconf -3"></FraneLayout></span></span></span>
</p>
</div>
<div class='ocr_carea' id='block_1_7' title="bbox 1900 948 2479 1008">
<p class='ocr_par'>
<span class='ocr_line' id='line_1_15' title="bbox 1900 948 2479 1008"><span class='ocr_word' id='word_1_89' title="bbox 1900 969 1918 1008"><span class='xocr_word' id='xword_1_89' title="x_wconf -6">t</span></span> <span class='ocr_word' id='word_1_90' title="bbox 1950 962 1969 1006"><span class='xocr_word' id='xword_1_90' title="x_wconf -5">h</span></span> <span class='ocr_word' id='word_1_91' title="bbox 2005 962 2011 970"><span class='xocr_word' id='xword_1_91' title="x_wconf -6">'</span></span> <span class='ocr_word' id='word_1_92' title="bbox 2051 948 2479 1005"><span class='xocr_word' id='xword_1_92' title="x_wconf -6">ht="natch_parent"</span></span></span>
</p>
</div>
<div class='ocr_carea' id='block_1_8' title="bbox 590 1328 2881 1594">
<p class='ocr_par'>
<span class='ocr_line' id='line_1_16' title="bbox 590 1329 2880 1414"><span class='ocr_word' id='word_1_93' title="bbox 590 1349 704 1414"><span class='xocr_word' id='xword_1_93' title="x_wconf -3">Veja</span></span> <span class='ocr_word' id='word_1_94' title="bbox 732 1365 835 1414"><span class='xocr_word' id='xword_1_94' title="x_wconf -2">que</span></span> <span class='ocr_word' id='word_1_95' title="bbox 862 1366 894 1399"><span class='xocr_word' id='xword_1_95' title="x_wconf 0">o</span></span> <span class='ocr_word' id='word_1_96' title="bbox 921 1354 1226 1408"><span class='xocr_word' id='xword_1_96' title="x_wconf -1">LinearLayout</span></span> <span class='ocr_word' id='word_1_97' title="bbox 1255 1343 1468 1397"><span class='xocr_word' id='xword_1_97' title="x_wconf -3">recebeu</span></span> <span class='ocr_word' id='word_1_98' title="bbox 1496 1361 1587 1395"><span class='xocr_word' id='xword_1_98' title="x_wconf -1">um</span></span> <span class='ocr_word' id='word_1_99' title="bbox 1615 1334 1985 1393"><span class='xocr_word' id='xword_1_99' title="x_wconf -2">identicador</span></span> <span class='ocr_word' id='word_1_100' title="bbox 2009 1329 2772 1388"><span class='xocr_word' id='xword_1_100' title="x_wconf -2">android:id="@+id/layoutFrag",</span></span> <span class='ocr_word' id='word_1_101' title="bbox 2794 1347 2880 1398"><span class='xocr_word' id='xword_1_101' title="x_wconf -7">que</span></span></span>
<span class='ocr_line' id='line_1_17' title="bbox 590 1416 2881 1505"><span class='ocr_word' id='word_1_102' title="bbox 590 1439 702 1488"><span class='xocr_word' id='xword_1_102' title="x_wconf -2">ser</span></span> <span class='ocr_word' id='word_1_103' title="bbox 728 1435 979 1489"><span class='xocr_word' id='xword_1_103' title="x_wconf -3">utilizado</span></span> <span class='ocr_word' id='word_1_104' title="bbox 1004 1455 1126 1505"><span class='xocr_word' id='xword_1_104' title="x_wconf -2">para</span></span> <span class='ocr_word' id='word_1_105' title="bbox 1151 1435 1418 1489"><span class='xocr_word' id='xword_1_105' title="x_wconf -2">adicionar</span></span> <span class='ocr_word' id='word_1_106' title="bbox 1440 1433 1887 1487"><span class='xocr_word' id='xword_1_106' title="x_wconf -2">dinamicamente</span></span> <span class='ocr_word' id='word_1_107' title="bbox 1912 1445 1945 1479"><span class='xocr_word' id='xword_1_107' title="x_wconf -1">o</span></span> <span class='ocr_word' id='word_1_108' title="bbox 1971 1423 2235 1493"><span class='xocr_word' id='xword_1_108' title="x_wconf -2">fragment</span></span> <span class='ocr_word' id='word_1_109' title="bbox 2262 1438 2416 1473"><span class='xocr_word' id='xword_1_109' title="x_wconf -2">nesse</span></span> <span class='ocr_word' id='word_1_110' title="bbox 2441 1416 2622 1487"><span class='xocr_word' id='xword_1_110' title="x_wconf -2">layout</span></span> <span class='ocr_word' id='word_1_111' title="bbox 2648 1416 2761 1486"><span class='xocr_word' id='xword_1_111' title="x_wconf -2">pela</span></span> <span class='ocr_word' id='word_1_112' title="bbox 2781 1424 2881 1476"><span class='xocr_word' id='xword_1_112' title="x_wconf -2">API.</span></span></span>
<span class='ocr_line' id='line_1_18' title="bbox 591 1511 2794 1594"><span class='ocr_word' id='word_1_113' title="bbox 591 1528 640 1578"><span class='xocr_word' id='xword_1_113' title="x_wconf -1">O</span></span> <span class='ocr_word' id='word_1_114' title="bbox 664 1525 852 1594"><span class='xocr_word' id='xword_1_114' title="x_wconf -2">cdigo</span></span> <span class='ocr_word' id='word_1_115' title="bbox 874 1525 940 1579"><span class='xocr_word' id='xword_1_115' title="x_wconf -2">da</span></span> <span class='ocr_word' id='word_1_116' title="bbox 963 1530 1167 1594"><span class='xocr_word' id='xword_1_116' title="x_wconf -2">activity</span></span> <span class='ocr_word' id='word_1_117' title="bbox 1189 1545 1292 1594"><span class='xocr_word' id='xword_1_117' title="x_wconf -2">que</span></span> <span class='ocr_word' id='word_1_118' title="bbox 1315 1530 1479 1578"><span class='xocr_word' id='xword_1_118' title="x_wconf -2">insere</span></span> <span class='ocr_word' id='word_1_119' title="bbox 1501 1544 1534 1576"><span class='xocr_word' id='xword_1_119' title="x_wconf -1">o</span></span> <span class='ocr_word' id='word_1_120' title="bbox 1557 1522 1816 1591"><span class='xocr_word' id='xword_1_120' title="x_wconf -3">fragment</span></span> <span class='ocr_word' id='word_1_121' title="bbox 1838 1538 1909 1572"><span class='xocr_word' id='xword_1_121' title="x_wconf -1">no</span></span> <span class='ocr_word' id='word_1_122' title="bbox 1932 1516 2112 1586"><span class='xocr_word' id='xword_1_122' title="x_wconf -1">layout</span></span> <span class='ocr_word' id='word_1_123' title="bbox 2135 1511 2280 1584"><span class='xocr_word' id='xword_1_123' title="x_wconf -1">pode</span></span> <span class='ocr_word' id='word_1_124' title="bbox 2302 1530 2386 1565"><span class='xocr_word' id='xword_1_124' title="x_wconf -2">ser</span></span> <span class='ocr_word' id='word_1_125' title="bbox 2405 1525 2543 1563"><span class='xocr_word' id='xword_1_125' title="x_wconf -3">visto</span></span> <span class='ocr_word' id='word_1_126' title="bbox 2566 1529 2592 1563"><span class='xocr_word' id='xword_1_126' title="x_wconf -1">a</span></span> <span class='ocr_word' id='word_1_127' title="bbox 2617 1529 2794 1579"><span class='xocr_word' id='xword_1_127' title="x_wconf -3">seguir.</span></span></span>
</p>
</div>
<div class='ocr_carea' id='block_1_9' title="bbox 594 1688 1153 1767">
<p class='ocr_par'>
<span class='ocr_line' id='line_1_19' title="bbox 594 1688 1153 1767"><span class='ocr_word' id='word_1_128' title="bbox 767 1701 1153 1767"><span class='xocr_word' id='xword_1_128' title="x_wconf -2">MainActivity.java</span></span></span>
</p>
</div>
<div class='ocr_carea' id='block_1_10' title="bbox 591 1826 2660 2804">
<p class='ocr_par'>
<span class='ocr_line' id='line_1_20' title="bbox 591 1827 2468 1890"><span class='ocr_word' id='word_1_129' title="bbox 591 1835 735 1889"><span class='xocr_word' id='xword_1_129' title="x_wconf -1">public</span></span> <span class='ocr_word' id='word_1_130' title="bbox 764 1836 884 1881"><span class='xocr_word' id='xword_1_130' title="x_wconf -1">class</span></span> <span class='ocr_word' id='word_1_131' title="bbox 912 1838 1207 1890"><span class='xocr_word' id='xword_1_131' title="x_wconf -3">HainActivity</span></span> <span class='ocr_word' id='word_1_132' title="bbox 1235 1836 1404 1880"><span class='xocr_word' id='xword_1_132' title="x_wconf -1">extends</span></span> <span class='ocr_word' id='word_1_133' title="bbox 1433 1830 2418 1889"><span class='xocr_word' id='xword_1_133' title="x_wconf -3">android.support.v4.app.FragnentActivity</span></span> <span class='ocr_word' id='word_1_134' title="bbox 2451 1827 2468 1883"><span class='xocr_word' id='xword_1_134' title="x_wconf -2">{</span></span></span>
</p>
<p class='ocr_par'>
<span class='ocr_line' id='line_1_21' title="bbox 678 1919 898 1971"><span class='ocr_word' id='word_1_135' title="bbox 678 1919 898 1971"><span class='xocr_word' id='xword_1_135' title="x_wconf -3">@0verride</span></span></span>
</p>
<p class='ocr_par'>
<span class='ocr_line' id='line_1_22' title="bbox 678 2001 1968 2056"><span class='ocr_word' id='word_1_136' title="bbox 678 2003 898 2056"><span class='xocr_word' id='xword_1_136' title="x_wconf -1">protected</span></span> <span class='ocr_word' id='word_1_137' title="bbox 926 2003 1021 2047"><span class='xocr_word' id='xword_1_137' title="x_wconf -3">void</span></span> <span class='ocr_word' id='word_1_138' title="bbox 1050 2002 1419 2055"><span class='xocr_word' id='xword_1_138' title="x_wconf -2">onCreate(Bundle</span></span> <span class='ocr_word' id='word_1_139' title="bbox 1449 2002 1916 2054"><span class='xocr_word' id='xword_1_139' title="x_wconf -2">savedInstanceState)</span></span> <span class='ocr_word' id='word_1_140' title="bbox 1951 2001 1968 2056"><span class='xocr_word' id='xword_1_140' title="x_wconf -1">{</span></span></span>
</p>
<p class='ocr_par'>
<span class='ocr_line' id='line_1_23' title="bbox 768 2086 1625 2139"><span class='ocr_word' id='word_1_141' title="bbox 768 2086 1625 2139"><span class='xocr_word' id='xword_1_141' title="x_wconf -2">super.onCreate(savedInstanceState);</span></span></span>
</p>
<p class='ocr_par'>
<span class='ocr_line' id='line_1_24' title="bbox 768 2169 1726 2224"><span class='ocr_word' id='word_1_142' title="bbox 768 2169 1726 2224"><span class='xocr_word' id='xword_1_142' title="x_wconf -3">setContentView(R.layout.activity_main);</span></span></span>
</p>
<p class='ocr_par'>
<span class='ocr_line' id='line_1_25' title="bbox 768 2251 1880 2309"><span class='ocr_word' id='word_1_143' title="bbox 768 2251 811 2305"><span class='xocr_word' id='xword_1_143' title="x_wconf 0">//</span></span> <span class='ocr_word' id='word_1_144' title="bbox 840 2252 1035 2296"><span class='xocr_word' id='xword_1_144' title="x_wconf -2">Adiciona</span></span> <span class='ocr_word' id='word_1_145' title="bbox 1064 2266 1085 2297"><span class='xocr_word' id='xword_1_145' title="x_wconf 0">o</span></span> <span class='ocr_word' id='word_1_146' title="bbox 1115 2252 1308 2307"><span class='xocr_word' id='xword_1_146' title="x_wconf -3">fragment</span></span> <span class='ocr_word' id='word_1_147' title="bbox 1336 2253 1656 2298"><span class='xocr_word' id='xword_1_147' title="x_wconf -3">dinamicamente</span></span> <span class='ocr_word' id='word_1_148' title="bbox 1686 2254 1781 2309"><span class='xocr_word' id='xword_1_148' title="x_wconf -2">pela</span></span> <span class='ocr_word' id='word_1_149' title="bbox 1809 2259 1880 2299"><span class='xocr_word' id='xword_1_149' title="x_wconf -1">API</span></span></span>
</p>
<p class='ocr_par'>
<span class='ocr_line' id='line_1_26' title="bbox 767 2335 1555 2391"><span class='ocr_word' id='word_1_150' title="bbox 767 2335 1283 2388"><span class='xocr_word' id='xword_1_150' title="x_wconf -2">if(savedInstanceState</span></span> <span class='ocr_word' id='word_1_151' title="bbox 1312 2354 1357 2372"><span class='xocr_word' id='xword_1_151' title="x_wconf -1">==</span></span> <span class='ocr_word' id='word_1_152' title="bbox 1387 2336 1503 2390"><span class='xocr_word' id='xword_1_152' title="x_wconf -1">null)</span></span> <span class='ocr_word' id='word_1_153' title="bbox 1538 2336 1555 2391"><span class='xocr_word' id='xword_1_153' title="x_wconf -2">{</span></span></span>
</p>
<p class='ocr_par'>
<span class='ocr_line' id='line_1_27' title="bbox 854 2418 2660 2482"><span class='ocr_word' id='word_1_154' title="bbox 854 2418 1795 2477"><span class='xocr_word' id='xword_1_154' title="x_wconf -3">android.support.v4.app.FragnentHanager</span></span> <span class='ocr_word' id='word_1_155' title="bbox 1824 2423 1872 2468"><span class='xocr_word' id='xword_1_155' title="x_wconf -3">fn</span></span> <span class='ocr_word' id='word_1_156' title="bbox 1899 2441 1921 2461"><span class='xocr_word' id='xword_1_156' title="x_wconf -1">=</span></span> <span class='ocr_word' id='word_1_157' title="bbox 1950 2428 2660 2482"><span class='xocr_word' id='xword_1_157' title="x_wconf -3">getSupportFragnentHanager();</span></span></span>
<span class='ocr_line' id='line_1_28' title="bbox 856 2503 2016 2563"><span class='ocr_word' id='word_1_158' title="bbox 856 2504 1321 2555"><span class='xocr_word' id='xword_1_158' title="x_wconf -3">FragnentTransaction</span></span> <span class='ocr_word' id='word_1_159' title="bbox 1352 2503 1396 2547"><span class='xocr_word' id='xword_1_159' title="x_wconf -3">ft</span></span> <span class='ocr_word' id='word_1_160' title="bbox 1425 2522 1446 2539"><span class='xocr_word' id='xword_1_160' title="x_wconf 0">=</span></span> <span class='ocr_word' id='word_1_161' title="bbox 1475 2504 2016 2563"><span class='xocr_word' id='xword_1_161' title="x_wconf -3">fm.beginTransaction();</span></span></span>
</p>
<p class='ocr_par'>
<span class='ocr_line' id='line_1_29' title="bbox 856 2585 1688 2643"><span class='ocr_word' id='word_1_162' title="bbox 856 2588 1073 2638"><span class='xocr_word' id='xword_1_162' title="x_wconf -3">Fragmentl</span></span> <span class='ocr_word' id='word_1_163' title="bbox 1103 2585 1221 2639"><span class='xocr_word' id='xword_1_163' title="x_wconf -2">frag1</span></span> <span class='ocr_word' id='word_1_164' title="bbox 1251 2604 1272 2621"><span class='xocr_word' id='xword_1_164' title="x_wconf 0">=</span></span> <span class='ocr_word' id='word_1_165' title="bbox 1301 2599 1372 2630"><span class='xocr_word' id='xword_1_165' title="x_wconf -3">new</span></span> <span class='ocr_word' id='word_1_166' title="bbox 1402 2590 1688 2643"><span class='xocr_word' id='xword_1_166' title="x_wconf -3">Fragment1();</span></span></span>
</p>
<p class='ocr_par'>
<span class='ocr_line' id='line_1_30' title="bbox 855 2667 1914 2731"><span class='ocr_word' id='word_1_167' title="bbox 855 2667 1416 2724"><span class='xocr_word' id='xword_1_167' title="x_wconf -3">ft.add(R.id.layoutFrag,</span></span> <span class='ocr_word' id='word_1_168' title="bbox 1451 2671 1914 2731"><span class='xocr_word' id='xword_1_168' title="x_wconf -3">frag1,"Fragment1");</span></span></span>
</p>
<p class='ocr_par'>
<span class='ocr_line' id='line_1_31' title="bbox 856 2750 1141 2804"><span class='ocr_word' id='word_1_169' title="bbox 856 2750 1141 2804"><span class='xocr_word' id='xword_1_169' title="x_wconf -4">ft.connit();</span></span></span>
</p>
</div>
<div class='ocr_carea' id='block_1_11' title="bbox 590 2831 2879 3210">
<p class='ocr_par'>
<span class='ocr_line' id='line_1_32' title="bbox 767 2833 785 2887"><span class='ocr_word' id='word_1_170' title="bbox 767 2833 785 2887"><span class='xocr_word' id='xword_1_170' title="x_wconf -3">}</span></span></span>
</p>
<p class='ocr_par'>
<span class='ocr_line' id='line_1_33' title="bbox 678 2917 696 2972"><span class='ocr_word' id='word_1_171' title="bbox 678 2917 696 2972"><span class='xocr_word' id='xword_1_171' title="x_wconf -3">}</span></span></span>
<span class='ocr_line' id='line_1_34' title="bbox 678 3000 696 3054"><span class='ocr_word' id='word_1_172' title="bbox 678 3000 696 3054"><span class='xocr_word' id='xword_1_172' title="x_wconf -3">}</span></span></span>
</p>
<p class='ocr_par'>
<span class='ocr_line' id='line_1_35' title="bbox 590 3116 2879 3209"><span class='ocr_word' id='word_1_173' title="bbox 590 3121 713 3170"><span class='xocr_word' id='xword_1_173' title="x_wconf -1">Para</span></span> <span class='ocr_word' id='word_1_174' title="bbox 747 3120 946 3178"><span class='xocr_word' id='xword_1_174' title="x_wconf -2">inserir,</span></span> <span class='ocr_word' id='word_1_175' title="bbox 974 3116 1256 3170"><span class='xocr_word' id='xword_1_175' title="x_wconf -2">substituir</span></span> <span class='ocr_word' id='word_1_176' title="bbox 1285 3138 1354 3172"><span class='xocr_word' id='xword_1_176' title="x_wconf -1">ou</span></span> <span class='ocr_word' id='word_1_177' title="bbox 1388 3140 1621 3178"><span class='xocr_word' id='xword_1_177' title="x_wconf -2">remover</span></span> <span class='ocr_word' id='word_1_178' title="bbox 1651 3147 1743 3183"><span class='xocr_word' id='xword_1_178' title="x_wconf -2">um</span></span> <span class='ocr_word' id='word_1_179' title="bbox 1777 3130 2042 3204"><span class='xocr_word' id='xword_1_179' title="x_wconf -2">fragment</span></span> <span class='ocr_word' id='word_1_180' title="bbox 2074 3140 2194 3209"><span class='xocr_word' id='xword_1_180' title="x_wconf -1">pela</span></span> <span class='ocr_word' id='word_1_181' title="bbox 2224 3146 2330 3197"><span class='xocr_word' id='xword_1_181' title="x_wconf -2">API</span></span> <span class='ocr_word' id='word_1_182' title="bbox 2365 3148 2393 3198"><span class='xocr_word' id='xword_1_182' title="x_wconf -2"></span></span> <span class='ocr_word' id='word_1_183' title="bbox 2425 3144 2682 3200"><span class='xocr_word' id='xword_1_183' title="x_wconf -3">utilizada</span></span> <span class='ocr_word' id='word_1_184' title="bbox 2715 3163 2741 3198"><span class='xocr_word' id='xword_1_184' title="x_wconf -2">a</span></span> <span class='ocr_word' id='word_1_185' title="bbox 2772 3140 2879 3195"><span class='xocr_word' id='xword_1_185' title="x_wconf -2">clas-</span></span></span>
</p>
</div>
<div class='ocr_carea' id='block_1_12' title="bbox 590 3212 2881 3307">
<p class='ocr_par'>
<span class='ocr_line' id='line_1_36' title="bbox 590 3214 2880 3306"><span class='ocr_word' id='word_1_186' title="bbox 590 3226 645 3260"><span class='xocr_word' id='xword_1_186' title="x_wconf -1">se</span></span> <span class='ocr_word' id='word_1_187' title="bbox 679 3214 1236 3270"><span class='xocr_word' id='xword_1_187' title="x_wconf -5">Fragnenransaction,</span></span> <span class='ocr_word' id='word_1_188' title="bbox 1268 3228 1295 3261"><span class='xocr_word' id='xword_1_188' title="x_wconf -1">e</span></span> <span class='ocr_word' id='word_1_189' title="bbox 1328 3229 1360 3262"><span class='xocr_word' id='xword_1_189' title="x_wconf -1">0</span></span> <span class='ocr_word' id='word_1_190' title="bbox 1395 3214 1619 3270"><span class='xocr_word' id='xword_1_190' title="x_wconf -2">mtodo</span></span> <span class='ocr_word' id='word_1_191' title="bbox 1653 3230 1875 3287"><span class='xocr_word' id='xword_1_191' title="x_wconf -3">connit()</span></span> <span class='ocr_word' id='word_1_192' title="bbox 1913 3226 2106 3285"><span class='xocr_word' id='xword_1_192' title="x_wconf -2">efetiva</span></span> <span class='ocr_word' id='word_1_193' title="bbox 2142 3251 2200 3287"><span class='xocr_word' id='xword_1_193' title="x_wconf -1">as</span></span> <span class='ocr_word' id='word_1_194' title="bbox 2235 3234 2553 3306"><span class='xocr_word' id='xword_1_194' title="x_wconf -2">alteraes.</span></span> <span class='ocr_word' id='word_1_195' title="bbox 2589 3241 2639 3292"><span class='xocr_word' id='xword_1_195' title="x_wconf -1">O</span></span> <span class='ocr_word' id='word_1_196' title="bbox 2676 3228 2880 3291"><span class='xocr_word' id='xword_1_196' title="x_wconf -5">mtodo</span></span></span>
</p>
</div>
<div class='ocr_carea' id='block_1_13' title="bbox 589 3295 2880 3400">
<p class='ocr_par'>
<span class='ocr_line' id='line_1_37' title="bbox 590 3297 2880 3399"><span class='ocr_word' id='word_1_197' title="bbox 590 3302 923 3359"><span class='xocr_word' id='xword_1_197' title="x_wconf -5">add(1y0U'C,ff</span></span> <span class='ocr_word' id='word_1_198' title="bbox 929 3303 1104 3358"><span class='xocr_word' id='xword_1_198' title="x_wconf -6">9.'C9)</span></span> <span class='ocr_word' id='word_1_199' title="bbox 1134 3297 1311 3351"><span class='xocr_word' id='xword_1_199' title="x_wconf -2">recebe</span></span> <span class='ocr_word' id='word_1_200' title="bbox 1336 3319 1493 3356"><span class='xocr_word' id='xword_1_200' title="x_wconf -1">como</span></span> <span class='ocr_word' id='word_1_201' title="bbox 1519 3312 1814 3373"><span class='xocr_word' id='xword_1_201' title="x_wconf -2">parmetro</span></span> <span class='ocr_word' id='word_1_202' title="bbox 1840 3336 1873 3370"><span class='xocr_word' id='xword_1_202' title="x_wconf -1">o</span></span> <span class='ocr_word' id='word_1_203' title="bbox 1900 3318 2277 3380"><span class='xocr_word' id='xword_1_203' title="x_wconf -2">identicador</span></span> <span class='ocr_word' id='word_1_204' title="bbox 2301 3327 2375 3382"><span class='xocr_word' id='xword_1_204' title="x_wconf -1">do</span></span> <span class='ocr_word' id='word_1_205' title="bbox 2402 3328 2584 3399"><span class='xocr_word' id='xword_1_205' title="x_wconf -2">layout</span></span> <span class='ocr_word' id='word_1_206' title="bbox 2610 3329 2677 3384"><span class='xocr_word' id='xword_1_206' title="x_wconf -2">de</span></span> <span class='ocr_word' id='word_1_207' title="bbox 2702 3324 2834 3383"><span class='xocr_word' id='xword_1_207' title="x_wconf -6">ond</span></span> <span class='ocr_word' id='word_1_208' title="bbox 2855 3336 2880 3370"><span class='xocr_word' id='xword_1_208' title="x_wconf -3">0</span></span></span>
</p>
</div>
<div class='ocr_carea' id='block_1_14' title="bbox 591 3382 2880 3491">
<p class='ocr_par'>
<span class='ocr_line' id='line_1_38' title="bbox 591 3384 2880 3489"><span class='ocr_word' id='word_1_209' title="bbox 591 3386 848 3455"><span class='xocr_word' id='xword_1_209' title="x_wconf -8">ffagmem</span></span> <span class='ocr_word' id='word_1_210' title="bbox 871 3384 997 3438"><span class='xocr_word' id='xword_1_210' title="x_wconf -7">deve</span></span> <span class='ocr_word' id='word_1_211' title="bbox 1020 3405 1100 3438"><span class='xocr_word' id='xword_1_211' title="x_wconf -7">Sf</span></span> <span class='ocr_word' id='word_1_212' title="bbox 1122 3387 1365 3451"><span class='xocr_word' id='xword_1_212' title="x_wconf -5">lSr1d0,</span></span> <span class='ocr_word' id='word_1_213' title="bbox 1386 3410 1412 3444"><span class='xocr_word' id='xword_1_213' title="x_wconf -4">a</span></span> <span class='ocr_word' id='word_1_214' title="bbox 1439 3395 1693 3454"><span class='xocr_word' id='xword_1_214' title="x_wconf -1">instncia</span></span> <span class='ocr_word' id='word_1_215' title="bbox 1716 3402 1788 3458"><span class='xocr_word' id='xword_1_215' title="x_wconf -1">do</span></span> <span class='ocr_word' id='word_1_216' title="bbox 1812 3406 1993 3477"><span class='xocr_word' id='xword_1_216' title="x_wconf -2">objeto</span></span> <span class='ocr_word' id='word_1_217' title="bbox 2017 3412 2090 3467"><span class='xocr_word' id='xword_1_217' title="x_wconf -1">do</span></span> <span class='ocr_word' id='word_1_218' title="bbox 2116 3414 2382 3488"><span class='xocr_word' id='xword_1_218' title="x_wconf -3">fragment</span></span> <span class='ocr_word' id='word_1_219' title="bbox 2405 3441 2433 3476"><span class='xocr_word' id='xword_1_219' title="x_wconf -1">e</span></span> <span class='ocr_word' id='word_1_220' title="bbox 2458 3441 2584 3477"><span class='xocr_word' id='xword_1_220' title="x_wconf -2">uma</span></span> <span class='ocr_word' id='word_1_221' title="bbox 2610 3425 2774 3489"><span class='xocr_word' id='xword_1_221' title="x_wconf -2">string</span></span> <span class='ocr_word' id='word_1_222' title="bbox 2794 3426 2880 3484"><span class='xocr_word' id='xword_1_222' title="x_wconf -6">qUf</span></span></span>
</p>
</div>
<div class='ocr_carea' id='block_1_15' title="bbox 590 3473 1689 3632">
<p class='ocr_par'>
<span class='ocr_line' id='line_1_39' title="bbox 590 3474 1689 3544"><span class='ocr_word' id='word_1_223' title="bbox 590 3481 615 3529"><span class='xocr_word' id='xword_1_223' title="x_wconf -2"></span></span> <span class='ocr_word' id='word_1_224' title="bbox 638 3495 665 3529"><span class='xocr_word' id='xword_1_224' title="x_wconf -2">a</span></span> <span class='ocr_word' id='word_1_225' title="bbox 691 3491 787 3544"><span class='xocr_word' id='xword_1_225' title="x_wconf -2">tag.</span></span> <span class='ocr_word' id='word_1_226' title="bbox 806 3479 851 3527"><span class='xocr_word' id='xword_1_226' title="x_wconf -1">A</span></span> <span class='ocr_word' id='word_1_227' title="bbox 871 3490 956 3543"><span class='xocr_word' id='xword_1_227' title="x_wconf -1">tag</span></span> <span class='ocr_word' id='word_1_228' title="bbox 978 3474 1118 3543"><span class='xocr_word' id='xword_1_228' title="x_wconf -1">pode</span></span> <span class='ocr_word' id='word_1_229' title="bbox 1140 3495 1221 3528"><span class='xocr_word' id='xword_1_229' title="x_wconf -2">ser</span></span> <span class='ocr_word' id='word_1_230' title="bbox 1242 3477 1488 3535"><span class='xocr_word' id='xword_1_230' title="x_wconf -2">utilizada</span></span> <span class='ocr_word' id='word_1_231' title="bbox 1551 3505 1689 3544"><span class='xocr_word' id='xword_1_231' title="x_wconf -6">oszer</span></span></span>
<span class='ocr_line' id='line_1_40' title="bbox 590 3564 1441 3632"><span class='ocr_word' id='word_1_232' title="bbox 590 3586 621 3619"><span class='xocr_word' id='xword_1_232' title="x_wconf 0">o</span></span> <span class='ocr_word' id='word_1_233' title="bbox 644 3564 861 3618"><span class='xocr_word' id='xword_1_233' title="x_wconf -2">mtodo</span></span> <span class='ocr_word' id='word_1_234' title="bbox 882 3570 1441 3632"><span class='xocr_word' id='xword_1_234' title="x_wconf -3">ndFragnentByTag(tag).</span></span></span>
</p>
</div>
<div class='ocr_carea' id='block_1_16' title="bbox 1514 3495 2879 3587">
<p class='ocr_par'>
<span class='ocr_line' id='line_1_41' title="bbox 1514 3496 2879 3586"><span class='ocr_word' id='word_1_235' title="bbox 1514 3504 1547 3554"><span class='xocr_word' id='xword_1_235' title="x_wconf -4">P</span></span> <span class='ocr_word' id='word_1_236' title="bbox 1696 3496 1954 3555"><span class='xocr_word' id='xword_1_236' title="x_wconf -7">OTITICHC</span></span> <span class='ocr_word' id='word_1_237' title="bbox 1979 3523 2104 3573"><span class='xocr_word' id='xword_1_237' title="x_wconf -1">para</span></span> <span class='ocr_word' id='word_1_238' title="bbox 2129 3527 2414 3566"><span class='xocr_word' id='xword_1_238' title="x_wconf -5">I1COU`8I`</span></span> <span class='ocr_word' id='word_1_239' title="bbox 2437 3533 2470 3567"><span class='xocr_word' id='xword_1_239' title="x_wconf -1">O</span></span> <span class='ocr_word' id='word_1_240' title="bbox 2496 3513 2756 3586"><span class='xocr_word' id='xword_1_240' title="x_wconf -5">fI'3gITl(I1</span></span> <span class='ocr_word' id='word_1_241' title="bbox 2779 3518 2879 3561"><span class='xocr_word' id='xword_1_241' title="x_wconf -5">COITI</span></span></span>
</p>
</div>
<div class='ocr_carea' id='block_1_17' title="bbox 678 3698 2245 3794">
<p class='ocr_par'>
<span class='ocr_line' id='line_1_42' title="bbox 678 3699 2245 3793"><span class='ocr_word' id='word_1_242' title="bbox 678 3704 896 3754"><span class='xocr_word' id='xword_1_242' title="x_wconf -3">Fragmentl</span></span> <span class='ocr_word' id='word_1_243' title="bbox 927 3699 1045 3754"><span class='xocr_word' id='xword_1_243' title="x_wconf -3">fragl</span></span> <span class='ocr_word' id='word_1_244' title="bbox 1074 3717 1096 3735"><span class='xocr_word' id='xword_1_244' title="x_wconf -1">=</span></span> <span class='ocr_word' id='word_1_245' title="bbox 1127 3700 1390 3758"><span class='xocr_word' id='xword_1_245' title="x_wconf -3">(Fragmentl)</span></span> <span class='ocr_word' id='word_1_246' title="bbox 1423 3706 2245 3793"><span class='xocr_word' id='xword_1_246' title="x_wconf -6">fn.ndFragmentByTag("Fra9ment1~).</span></span></span>
</p>
</div>
</div>
</body>
</html>
(api
I 8 F uo
t n ragmen s 255
Repare que, antes de inserir o fra gmt pela API foi validada a condi o
lsavedlnstancestate == "u) Para ter Certeza de que a activity estava sendo crida
nesse instante. Se o Bundle no estiver nulo signica ue a act- _t f . d ,d
criada novamente. Isso pode acontecer a q M y O1 estrul a 6

I ' o , ,. ,, .
O girar o dispositivo trocando a orientao
de vertical para horizontal, ou vice-versa
mesmo Bundl ' , . Quando uma activity destruda, o m
todo onSaveInstanceState(bundle) chamad O para o aplicativo salvar o estado da tela.
E556 C Pa55ad0 C0m0 argumento para o metodo onCreate(bundle) ao
facflaf a aCt1V1tY Por 1550, devemos testar a condio if(savedInstanceState == null)
para ter Certeza de que a activity est sendo criada pela primeira vez pois caso
contrario o fragment seria adicionado duas vezes no layout Portanto lembre~se
a transao criada pl0 F"H9P1entTransaction persistida durante o ciclo de vida da
activity e qualquer troca de orientao.

8.5 Utilizando fragments com action bar + tabs


No captulo 5, sobre action bar, zemos um exemplo que mostrou como criar
as tabs. Agora vamos criar outro exemplo que vai utilizar action bar + tabs +
fragments. Embora as tabs com action bar estejam deprecated (depois falamos
mais sobre isso), aprender a utiliza-las muito importante para o seu aprendizado.
No Android, no importa se voc utiliza as tabs ou o menu lateral (Navigation
Drawer) como a navegao top-level do seu aplicativo, sempre que voc selecionar
alguma tab ou opo do menu, o contedo da tela precisa ser atualizado sem
trocar de activity E isso feito com fragments.
O prximo exemplo que vamos estudar o projeto Fragments-ActionBarTabs, disponvel
nos exemplos deste captulo. Neste projeto, foi congurada a action bar com tres
tabs, e ao clicar numa tab um fragment ser substituido por outro dentro do layout.

Nota: lembre~se de que a classe android.support.v7.app.AppCcrfipatACtV)' lha de


demos utilizar os fragments e a
android.support.v4.app.FragmentActvity; por isso, P0
action bar de compatibilidade.

MainActivity.java
Dublc class MainActivity extends android.support.v7.app.AppCompatActtv1.ty {
@0verride
protected void onCreate(Bundl e savedInstance5tate) {
super.onCreate(savedInstance5tate);.
setContentView(R.layout.actvity_matn);
256 Google Android - 4 edio
ActionBar actionBar = getSupportActionBar(); MODE TABS).
actonBar.setNavgationHode(androd.app.ActionBar.NAVIGATION_ _ ,
// Tab 1
ActionBar.Tab tab1 = actionBar.newTab().setTet("Fra9 1 );
tab1.setTabLstener(new MyTabLstener(ths, new Fra9@t1()));
actonBar.addTab(tab1);
// Tab 2
ActonBar.Tab tab2 = actonBar.newTab().setTet("Frag 2");
tab2.setTabListener(new MyTabLstener(ths, new Fragnent2()));g
actonBar.addTab(tab2);
// Tab 3
ActionBar.Tab tab3 = actonBar.newTab().setText("Frag 3");
tab3.setTabLstener(new MyTabLstener(ths, new Fragment3()));
actonBar.addTab(tab3);
}

No cdigo da activity a classe MyTabLi.stener recebe no construtor a instncia do


fragment que deve ser substitudo no layout. Para este exemplo criei as classes
Fragmentl, Fragnent2 e Fragnent3. No arquivo de layout da activity mais uma vez
vamos deixar apenas o layout de marcao, pois os fragments sero inseridos
dinamicamente.

/res/layout/activity_main.xmI
<FrameLayout m1ns:android="http://schemas.android.com/apk/res/android"
xnlns:too1s="http://schemas.androd.com/tools"
androd:layout_wdth="match_parent" android:1ayout_heght="natch_parent"
androd:id="@+id/1ayoutFrag">
</span></span> <span class='ocr_word' id='word_1_118' title="bbox 817 2714 1010 2763"><span class='xocr_word' id='xword_1_118' title="x_wconf -3">Fragment</span></span> <span class='ocr_word' id='word_1_119' title="bbox 1041 2708 1135 2752"><span class='xocr_word' id='xword_1_119' title="x_wconf -2">ser</span></span> <span class='ocr_word' id='word_1_120' title="bbox 1165 2706 1360 2751"><span class='xocr_word' id='xword_1_120' title="x_wconf -4">inserido</span></span> <span class='ocr_word' id='word_1_121' title="bbox 1389 2707 1484 2759"><span class='xocr_word' id='xword_1_121' title="x_wconf -4">aqui</span></span> <span class='ocr_word' id='word_1_122' title="bbox 1513 2719 1559 2750"><span class='xocr_word' id='xword_1_122' title="x_wconf -1">no</span></span> <span class='ocr_word' id='word_1_123' title="bbox 1588 2706 1735 2760"><span class='xocr_word' id='xword_1_123' title="x_wconf -4">layout</span></span> <span class='ocr_word' id='word_1_124' title="bbox 1768 2705 2189 2761"><span class='xocr_word' id='xword_1_124' title="x_wconf -4">"@+id/1ayoutFrag"</span></span> <span class='ocr_word' id='word_1_125' title="bbox 2254 2731 2266 2737"><span class='xocr_word' id='xword_1_125' title="x_wconf -1">-</span></span> <span class='ocr_word' id='word_1_126' title="bbox 2302 2721 2323 2746"><span class='xocr_word' id='xword_1_126' title="x_wconf 0"></span></span></span>
</p>
<p class='ocr_par'>
<span class='ocr_line' id='line_1_29' title="bbox 603 2795 949 2849"><span class='ocr_word' id='word_1_127' title="bbox 603 2795 949 2849"><span class='xocr_word' id='xword_1_127' title="x_wconf -2"></FrameLayout</span></span></span>
</p>
</div>
<div class='ocr_carea' id='block_1_14' title="bbox 603 2887 2899 3275">
<p class='ocr_par'>
<span class='ocr_line' id='line_1_30' title="bbox 604 2905 2895 2981"><span class='ocr_word' id='word_1_128' title="bbox 604 2916 675 2965"><span class='xocr_word' id='xword_1_128' title="x_wconf -1">As</span></span> <span class='ocr_word' id='word_1_129' title="bbox 699 2910 882 2964"><span class='xocr_word' id='xword_1_129' title="x_wconf -1">classes</span></span> <span class='ocr_word' id='word_1_130' title="bbox 908 2919 1150 2972"><span class='xocr_word' id='xword_1_130' title="x_wconf -3">Fragnentl,</span></span> <span class='ocr_word' id='word_1_131' title="bbox 1174 2917 1398 2970"><span class='xocr_word' id='xword_1_131' title="x_wconf -2">Fragnent2</span></span> <span class='ocr_word' id='word_1_132' title="bbox 1423 2927 1450 2960"><span class='xocr_word' id='xword_1_132' title="x_wconf -1">e</span></span> <span class='ocr_word' id='word_1_133' title="bbox 1475 2918 1701 2971"><span class='xocr_word' id='xword_1_133' title="x_wconf -2">Fragnent3</span></span> <span class='ocr_word' id='word_1_134' title="bbox 1728 2916 1830 2962"><span class='xocr_word' id='xword_1_134' title="x_wconf -1">no</span></span> <span class='ocr_word' id='word_1_135' title="bbox 1855 2917 2004 2964"><span class='xocr_word' id='xword_1_135' title="x_wconf -2">sero</span></span> <span class='ocr_word' id='word_1_136' title="bbox 2029 2910 2267 2965"><span class='xocr_word' id='xword_1_136' title="x_wconf -2">exibidas</span></span> <span class='ocr_word' id='word_1_137' title="bbox 2292 2914 2418 2981"><span class='xocr_word' id='xword_1_137' title="x_wconf -1">aqui</span></span> <span class='ocr_word' id='word_1_138' title="bbox 2443 2929 2568 2980"><span class='xocr_word' id='xword_1_138' title="x_wconf -2">para</span></span> <span class='ocr_word' id='word_1_139' title="bbox 2594 2905 2895 2963"><span class='xocr_word' id='xword_1_139' title="x_wconf -2">economizar</span></span></span>
<span class='ocr_line' id='line_1_31' title="bbox 607 2997 2895 3072"><span class='ocr_word' id='word_1_140' title="bbox 607 3020 791 3070"><span class='xocr_word' id='xword_1_140' title="x_wconf -3">espao</span></span> <span class='ocr_word' id='word_1_141' title="bbox 819 3019 888 3052"><span class='xocr_word' id='xword_1_141' title="x_wconf -1">no</span></span> <span class='ocr_word' id='word_1_142' title="bbox 915 2998 1049 3061"><span class='xocr_word' id='xword_1_142' title="x_wconf -1">livro,</span></span> <span class='ocr_word' id='word_1_143' title="bbox 1074 3002 1189 3067"><span class='xocr_word' id='xword_1_143' title="x_wconf -1">pois</span></span> <span class='ocr_word' id='word_1_144' title="bbox 1215 2997 1318 3050"><span class='xocr_word' id='xword_1_144' title="x_wconf -1">elas</span></span> <span class='ocr_word' id='word_1_145' title="bbox 1343 3005 1434 3051"><span class='xocr_word' id='xword_1_145' title="x_wconf -1">so</span></span> <span class='ocr_word' id='word_1_146' title="bbox 1460 2998 1671 3068"><span class='xocr_word' id='xword_1_146' title="x_wconf -1">simples</span></span> <span class='ocr_word' id='word_1_147' title="bbox 1697 3019 1855 3054"><span class='xocr_word' id='xword_1_147' title="x_wconf -1">como</span></span> <span class='ocr_word' id='word_1_148' title="bbox 1882 3021 1909 3054"><span class='xocr_word' id='xword_1_148' title="x_wconf -1">a</span></span> <span class='ocr_word' id='word_1_149' title="bbox 1936 3001 2099 3056"><span class='xocr_word' id='xword_1_149' title="x_wconf -1">classe</span></span> <span class='ocr_word' id='word_1_150' title="bbox 2127 3013 2359 3067"><span class='xocr_word' id='xword_1_150' title="x_wconf -3">Fragnentl</span></span> <span class='ocr_word' id='word_1_151' title="bbox 2387 3022 2493 3072"><span class='xocr_word' id='xword_1_151' title="x_wconf -1">que</span></span> <span class='ocr_word' id='word_1_152' title="bbox 2520 3000 2820 3056"><span class='xocr_word' id='xword_1_152' title="x_wconf -6">estudamos</span></span> <span class='ocr_word' id='word_1_153' title="bbox 2844 3004 2895 3042"><span class='xocr_word' id='xword_1_153' title="x_wconf -1">no</span></span></span>
<span class='ocr_line' id='line_1_32' title="bbox 608 3087 2897 3165"><span class='ocr_word' id='word_1_154' title="bbox 608 3089 841 3159"><span class='xocr_word' id='xword_1_154' title="x_wconf -1">exemplo</span></span> <span class='ocr_word' id='word_1_155' title="bbox 856 3093 1082 3142"><span class='xocr_word' id='xword_1_155' title="x_wconf -1">anterior.</span></span> <span class='ocr_word' id='word_1_156' title="bbox 1100 3087 1425 3141"><span class='xocr_word' id='xword_1_156' title="x_wconf -1">Lembrando</span></span> <span class='ocr_word' id='word_1_157' title="bbox 1441 3108 1542 3158"><span class='xocr_word' id='xword_1_157' title="x_wconf -1">que</span></span> <span class='ocr_word' id='word_1_158' title="bbox 1557 3090 1683 3144"><span class='xocr_word' id='xword_1_158' title="x_wconf -2">cada</span></span> <span class='ocr_word' id='word_1_159' title="bbox 1701 3090 1955 3162"><span class='xocr_word' id='xword_1_159' title="x_wconf -2">fragment</span></span> <span class='ocr_word' id='word_1_160' title="bbox 1971 3109 2075 3147"><span class='xocr_word' id='xword_1_160' title="x_wconf -1">tem</span></span> <span class='ocr_word' id='word_1_161' title="bbox 2091 3114 2184 3148"><span class='xocr_word' id='xword_1_161' title="x_wconf -1">seu</span></span> <span class='ocr_word' id='word_1_162' title="bbox 2200 3099 2414 3165"><span class='xocr_word' id='xword_1_162' title="x_wconf -2">prprio</span></span> <span class='ocr_word' id='word_1_163' title="bbox 2430 3098 2646 3165"><span class='xocr_word' id='xword_1_163' title="x_wconf -2">arquivo</span></span> <span class='ocr_word' id='word_1_164' title="bbox 2661 3091 2726 3146"><span class='xocr_word' id='xword_1_164' title="x_wconf -1">de</span></span> <span class='ocr_word' id='word_1_165' title="bbox 2740 3089 2897 3156"><span class='xocr_word' id='xword_1_165' title="x_wconf -8">layout,</span></span></span>
<span class='ocr_line' id='line_1_33' title="bbox 610 3178 2881 3255"><span class='ocr_word' id='word_1_166' title="bbox 610 3201 705 3251"><span class='xocr_word' id='xword_1_166' title="x_wconf -5">P0f</span></span> <span class='ocr_word' id='word_1_167' title="bbox 723 3179 974 3248"><span class='xocr_word' id='xword_1_167' title="x_wconf -6">XmPl0</span></span> <span class='ocr_word' id='word_1_168' title="bbox 996 3181 1577 3246"><span class='xocr_word' id='xword_1_168' title="x_wconf -8">/TCS/<1)'0WfT1._Zm611_1</span></span> <span class='ocr_word' id='word_1_169' title="bbox 1592 3225 1603 3244"><span class='xocr_word' id='xword_1_169' title="x_wconf -1">,</span></span> <span class='ocr_word' id='word_1_170' title="bbox 1618 3186 2218 3254"><span class='xocr_word' id='xword_1_170' title="x_wconf -4">/res/layout_fragment_2</span></span> <span class='ocr_word' id='word_1_171' title="bbox 2241 3206 2268 3241"><span class='xocr_word' id='xword_1_171' title="x_wconf -1">e</span></span> <span class='ocr_word' id='word_1_172' title="bbox 2286 3178 2881 3255"><span class='xocr_word' id='xword_1_172' title="x_wconf -3">/res/layout_ragment_3-</span></span></span>
</p>
</div>
<div class='ocr_carea' id='block_1_15' title="bbox 608 3282 2903 3683">
<p class='ocr_par'>
<span class='ocr_line' id='line_1_34' title="bbox 611 3302 2898 3412"><span class='ocr_word' id='word_1_173' title="bbox 611 3309 661 3360"><span class='xocr_word' id='xword_1_173' title="x_wconf -4">O</span></span> <span class='ocr_word' id='word_1_174' title="bbox 682 3304 899 3412"><span class='xocr_word' id='xword_1_174' title="x_wconf -10">Segfedo</span></span> <span class='ocr_word' id='word_1_175' title="bbox 920 3323 1042 3373"><span class='xocr_word' id='xword_1_175' title="x_wconf -8">para</span></span> <span class='ocr_word' id='word_1_176' title="bbox 1064 3303 1266 3356"><span class='xocr_word' id='xword_1_176' title="x_wconf -7">Uuhzaf</span></span> <span class='ocr_word' id='word_1_177' title="bbox 1284 3323 1344 3356"><span class='xocr_word' id='xword_1_177' title="x_wconf -5">05</span></span> <span class='ocr_word' id='word_1_178' title="bbox 1365 3302 1649 3374"><span class='xocr_word' id='xword_1_178' title="x_wconf -6">ffagmfints</span></span> <span class='ocr_word' id='word_1_179' title="bbox 1669 3328 1790 3363"><span class='xocr_word' id='xword_1_179' title="x_wconf -2">com</span></span> <span class='ocr_word' id='word_1_180' title="bbox 1811 3330 1866 3365"><span class='xocr_word' id='xword_1_180' title="x_wconf -1">as</span></span> <span class='ocr_word' id='word_1_181' title="bbox 1887 3311 2006 3366"><span class='xocr_word' id='xword_1_181' title="x_wconf -2">tabs</span></span> <span class='ocr_word' id='word_1_182' title="bbox 2026 3317 2053 3367"><span class='xocr_word' id='xword_1_182' title="x_wconf -2"></span></span> <span class='ocr_word' id='word_1_183' title="bbox 2074 3333 2107 3367"><span class='xocr_word' id='xword_1_183' title="x_wconf 0">o</span></span> <span class='ocr_word' id='word_1_184' title="bbox 2126 3321 2436 3369"><span class='xocr_word' id='xword_1_184' title="x_wconf -4">TabLstener.</span></span> <span class='ocr_word' id='word_1_185' title="bbox 2451 3318 2571 3385"><span class='xocr_word' id='xword_1_185' title="x_wconf -1">Veja</span></span> <span class='ocr_word' id='word_1_186' title="bbox 2593 3332 2699 3385"><span class='xocr_word' id='xword_1_186' title="x_wconf -1">que</span></span> <span class='ocr_word' id='word_1_187' title="bbox 2719 3330 2745 3365"><span class='xocr_word' id='xword_1_187' title="x_wconf -2">a</span></span> <span class='ocr_word' id='word_1_188' title="bbox 2764 3305 2898 3362"><span class='xocr_word' id='xword_1_188' title="x_wconf -6">clas</span></span></span>
<span class='ocr_line' id='line_1_35' title="bbox 610 3393 2900 3475"><span class='ocr_word' id='word_1_189' title="bbox 610 3402 945 3460"><span class='xocr_word' id='xword_1_189' title="x_wconf -4">MyTabL1stener</span></span> <span class='ocr_word' id='word_1_190' title="bbox 970 3393 1148 3447"><span class='xocr_word' id='xword_1_190' title="x_wconf -1">recebe</span></span> <span class='ocr_word' id='word_1_191' title="bbox 1173 3413 1242 3446"><span class='xocr_word' id='xword_1_191' title="x_wconf -1">no</span></span> <span class='ocr_word' id='word_1_192' title="bbox 1265 3413 1359 3447"><span class='xocr_word' id='xword_1_192' title="x_wconf -1">seu</span></span> <span class='ocr_word' id='word_1_193' title="bbox 1381 3413 1683 3452"><span class='xocr_word' id='xword_1_193' title="x_wconf -2">construtor</span></span> <span class='ocr_word' id='word_1_194' title="bbox 1705 3420 1738 3454"><span class='xocr_word' id='xword_1_194' title="x_wconf 0">o</span></span> <span class='ocr_word' id='word_1_195' title="bbox 1763 3400 2026 3473"><span class='xocr_word' id='xword_1_195' title="x_wconf -2">fragment</span></span> <span class='ocr_word' id='word_1_196' title="bbox 2049 3425 2156 3475"><span class='xocr_word' id='xword_1_196' title="x_wconf -1">que</span></span> <span class='ocr_word' id='word_1_197' title="bbox 2179 3406 2261 3461"><span class='xocr_word' id='xword_1_197' title="x_wconf -2">ela</span></span> <span class='ocr_word' id='word_1_198' title="bbox 2284 3406 2415 3461"><span class='xocr_word' id='xword_1_198' title="x_wconf -1">deve</span></span> <span class='ocr_word' id='word_1_199' title="bbox 2439 3423 2670 3462"><span class='xocr_word' id='xword_1_199' title="x_wconf -2">mostrar</span></span> <span class='ocr_word' id='word_1_200' title="bbox 2691 3422 2754 3459"><span class='xocr_word' id='xword_1_200' title="x_wconf -1">ao</span></span> <span class='ocr_word' id='word_1_201' title="bbox 2777 3397 2900 3452"><span class='xocr_word' id='xword_1_201' title="x_wconf -3">clicar</span></span></span>
<span class='ocr_line' id='line_1_36' title="bbox 612 3479 2900 3568"><span class='ocr_word' id='word_1_202' title="bbox 612 3505 695 3539"><span class='xocr_word' id='xword_1_202' title="x_wconf -1">em</span></span> <span class='ocr_word' id='word_1_203' title="bbox 716 3484 845 3538"><span class='xocr_word' id='xword_1_203' title="x_wconf -1">cada</span></span> <span class='ocr_word' id='word_1_204' title="bbox 865 3483 963 3537"><span class='xocr_word' id='xword_1_204' title="x_wconf -2">tab.</span></span> <span class='ocr_word' id='word_1_205' title="bbox 978 3487 1094 3552"><span class='xocr_word' id='xword_1_205' title="x_wconf -2">Veja</span></span> <span class='ocr_word' id='word_1_206' title="bbox 1114 3502 1218 3552"><span class='xocr_word' id='xword_1_206' title="x_wconf -1">que</span></span> <span class='ocr_word' id='word_1_207' title="bbox 1237 3483 1384 3538"><span class='xocr_word' id='xword_1_207' title="x_wconf -2">basta</span></span> <span class='ocr_word' id='word_1_208' title="bbox 1407 3505 1530 3541"><span class='xocr_word' id='xword_1_208' title="x_wconf -1">uma</span></span> <span class='ocr_word' id='word_1_209' title="bbox 1551 3492 1706 3545"><span class='xocr_word' id='xword_1_209' title="x_wconf -1">nica</span></span> <span class='ocr_word' id='word_1_210' title="bbox 1727 3491 1875 3548"><span class='xocr_word' id='xword_1_210' title="x_wconf -2">linha</span></span> <span class='ocr_word' id='word_1_211' title="bbox 1895 3494 1962 3549"><span class='xocr_word' id='xword_1_211' title="x_wconf -1">de</span></span> <span class='ocr_word' id='word_1_212' title="bbox 1981 3496 2175 3567"><span class='xocr_word' id='xword_1_212' title="x_wconf -2">cdigo</span></span> <span class='ocr_word' id='word_1_213' title="bbox 2196 3518 2323 3568"><span class='xocr_word' id='xword_1_213' title="x_wconf -2">para</span></span> <span class='ocr_word' id='word_1_214' title="bbox 2343 3515 2593 3554"><span class='xocr_word' id='xword_1_214' title="x_wconf -5">executar</span></span> <span class='ocr_word' id='word_1_215' title="bbox 2609 3518 2642 3553"><span class='xocr_word' id='xword_1_215' title="x_wconf -4">0</span></span> <span class='ocr_word' id='word_1_216' title="bbox 2662 3479 2900 3552"><span class='xocr_word' id='xword_1_216' title="x_wconf -6">eomand</span></span></span>
<span class='ocr_line' id='line_1_37' title="bbox 615 3578 2857 3662"><span class='ocr_word' id='word_1_217' title="bbox 615 3579 1337 3638"><span class='xocr_word' id='xword_1_217' title="x_wconf -5">Fragnenransacton.rep1ace(</span></span> <span class='ocr_word' id='word_1_218' title="bbox 1352 3617 1360 3627"><span class='xocr_word' id='xword_1_218' title="x_wconf 0">.</span></span> <span class='ocr_word' id='word_1_219' title="bbox 1378 3618 1386 3628"><span class='xocr_word' id='xword_1_219' title="x_wconf 0">.</span></span> <span class='ocr_word' id='word_1_220' title="bbox 1404 3582 1442 3638"><span class='xocr_word' id='xword_1_220' title="x_wconf 0">.)</span></span> <span class='ocr_word' id='word_1_221' title="bbox 1467 3597 1493 3630"><span class='xocr_word' id='xword_1_221' title="x_wconf -1">e</span></span> <span class='ocr_word' id='word_1_222' title="bbox 1515 3579 1797 3637"><span class='xocr_word' id='xword_1_222' title="x_wconf -2">substituir</span></span> <span class='ocr_word' id='word_1_223' title="bbox 1816 3605 1851 3639"><span class='xocr_word' id='xword_1_223' title="x_wconf -2">o</span></span> <span class='ocr_word' id='word_1_224' title="bbox 1873 3585 2137 3657"><span class='xocr_word' id='xword_1_224' title="x_wconf -2">fragment</span></span> <span class='ocr_word' id='word_1_225' title="bbox 2160 3609 2226 3644"><span class='xocr_word' id='xword_1_225' title="x_wconf -2">ao</span></span> <span class='ocr_word' id='word_1_226' title="bbox 2248 3590 2407 3645"><span class='xocr_word' id='xword_1_226' title="x_wconf -2">clicar</span></span> <span class='ocr_word' id='word_1_227' title="bbox 2427 3610 2513 3646"><span class='xocr_word' id='xword_1_227' title="x_wconf -1">em</span></span> <span class='ocr_word' id='word_1_228' title="bbox 2537 3590 2748 3662"><span class='xocr_word' id='xword_1_228' title="x_wconf -2">alguma</span></span> <span class='ocr_word' id='word_1_229' title="bbox 2771 3578 2857 3638"><span class='xocr_word' id='xword_1_229' title="x_wconf -4">tab-</span></span></span>
</p>
</div>
</div>
</body>
</html>
Captulo 8 n Fragments
257

MyTabListener.java
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBar;

public class MyTabListener implements ActionBar.TabListener {


private Context context;
private Fragment frag;
public MyTabListener(Context context, Fragment frag) {
this.context = context;
this.frag = frag;
}

@0verride
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
// Troca o fragment dinamicamente ao clicar na tab
ft.replace(R.id.layoutFrag, this.frag, null);
}

// Mtodos onTabUnselected e onTabReselected aqui.


}

Ao executar esse projeto, o resultado deve ser como a gura 8.10, que mostra a
segunda tab selecionada e o Fragnent2 no layout.

Fg2

Figura 8.10 - Action bar com tabs + ffagme


258 Google Android - 4' edio
8.6 Utilizando fragments com action bar + tabs + ViewPa9f
. . ainda
' r s mais
itilizar oViewPager ara eo
t P n.
_._ _. ... .- -nav
Para melhorar arentredo
as .'_~
o exemplo
' ' recisa anterior, podemos
trolar os tragmentsepermmrfazero gesto de swipe Iateralpr C8 _ g tibs.
Esse e um padrao de design muito conhecido no Andro1d, VOC P mma lo
O prximo exemplo que vou mostrar o projeto Fra9t'1@t5'T3b5'V"P39" QIU sst
disponvel com os exemplos do livro. Neste projeto foi con8Uf3d0 21 3CFlOl`l bar
com trs tabs, porm o controle de navegao feito pelo VGHPBQGF- SSIO ff 0 mais
importante deste exemplo! O ViewPager faz todo o trabalho e a tab so mostra 3
pgina que est sendo exibida.
O adapter do ViewPager ser formado pelos trs fragments, Fragmentl, Fragnentz
e Fragnent3. Portanto, voc poder utilizar o gesto de swipe para navegar nos
fragments. A tab nessa histria uma mera coadjuvante, pois ela apenas mostra
a pgina selecionada. A seguir, podemos visualizar o cdigo-fonte da HainActivity
que demonstra como utilizar o ViewPager com fragments.

LI MainActvity.java

public class HainActivity extends AppCompatActivity {


private ViewPager viewPager;
@0verride
protected void onCreate(Bund1e savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nain);
// ViewPager
viewPager = (ViewPager) ndViewById(R.id.viewPager);
viewPager.setAdapter(neu TabsAdapter(getSupportFragnentHanager()));
// Congura as Tabs
nal ActionBar actionar = getSupportActionBar();
actionBar.setNavigationHode(android.app.ActionBar.NAVIGATION_HO0E_TABS);
actionBar.addTab(actionBar.newTab().setText("Frag 1").setTabListener(new
HyTabListener(viewPager,0)));
actionBar.addTab(actionBar.newTab().setText("Frag 2").setTabListener(new
HyTabListener(viewPager,1)));
actionBar.addTab(actionBar.newTab() setText("Frag 3").setTabListener(new
HyTabListener(viewPager,2)));
// Se o ViewPager troca de pgina, atualiza 3 rab_
viewPager . set0nPageChangeListener( new ViewPager .0nPageChangeListener() {
QO/er ride

public void onPageSe1ected(int idx) {


// 59 ler Swipe no ViewPager, atualiza a tab
actionlar . setSe1ectedNav'lgationIten(idx) ;
Captulo 8 n Fragments 259
-}
@0verride

public void onPageScrolled(int position, oat position0ffset,


int position0ffsetPixels) { }
@0verride

public void onPageScrollStateChanged(int state) { }


});
}

Neste cdigo, estamos monitorando o evento de troca de pgina do ViewPager, pois


precisamos atualizar o ndice da tab selecionada, para corresponder pgina que
o ViewPager est mostrando. O mais importante deste exemplo voc entender
que no precisamos atualizar os fragments dinamicamente na tela com a classe
FragmentTransaction, pois o ViewPager que controla tudo. No arquivo de layout da
activity; basta inserir o ViewPager.

/res/layout/activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent" >
<android.support.v4.view.ViewPager android:id="@+id/viewPager"
android:layout_width="match_parent" android:layout_height="wrap_content" />

Veja que no cdigo-fonte da activity estamos utilizando a classe TabsAdapter, que


o adapter do ViewPager. Observe que o ViewPager pode utilizar uma implementao
de PagerAdapter para views normais, ou FragmentPagerAdapter quando cada pgina
representada por um fragment.

TabsAdapter.java
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
QLC class TabsAdapter extends FragmentPagerAdapter {
public TabsAdapter(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}

@0verride
public int getCount() {
// 0 ViewPager vai ter 3 pginas
return 3;
}
260 Google Android - 4 edio
@0verride
public Fragment getItem(int idx) {
if(id == G) {
return new Fragment1();
} else if(id == 1) {
return new Fragment2();
}

return new Fragment3();


}

Esse adapter apenas fornece o contedo do ViewPager; teremos trs pginas, e cada
uma um fragment. Para concluir o exemplo, a classe MyTabListener que trata dos
eventos das tabs foi alterada, para que, quando selecionar uma tab, a pgina do
ViewPager seja atualizada com o ndice da tab selecionada. Lembre-se de que neste
exemplo o ViewPager quem controla tudo, e as Tabs so meras coadjuvantes.

MyTabListener.java
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
public class MyTabListener implements ActionBar.TabListener {
private ViewPager viewPager;
private int idx;
public MyTabListener(ViewPager viewPager, int idx) {
this.viewPager = viewPager;
this.id = idx;
}

@Override

public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {


// Navega para a pgina desejada do ViewPager
viewPager.setCurrentItem(id);
}

@0verride

public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) { }


@0verride

public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) { }


l

Nota: a action
vendo al ' fb-' -, .,. .
af COITI tabs f0l descontmuada (deprecated); assim, voce deve estar
guns alertas (wammgs) DO codio. Mas este exemplo e um classico que
Captulo 8 I Fragments 261
voc precisa conhecer, at porque ele tambm mostrou como utilizar o ViewPager +
Fragments. A tab aqui mera coadjuvante e pode ser substituda por qualquer outro
componente. Quando formos desenvolver o projeto dos carros vamos utilizar o
componente TabLayout da biblioteca Android Design Support Library.

8.7 Ciclo de vida de um fragment


Um fragment tem um ciclo de vida bem denido, o qual atrelado ao ciclo de vida da
activity Se voc j entendeu como funciona o ciclo de vida de uma activity; como os
mtodos onCreate(bund1.e), onStart(), onResume(), onPause(), onStop() e onDestroy(), ser bem
simples de entender o ciclo de vida de um fragment, pois ele segue o mesmo conceito.
A gura 8.11 relembra os mtodos do ciclo de vida de uma activity

.._;
'..,,3
. z..
`'l` WW "
5- V- f l `.g
-zap-z I.. * ."*`"`'*, ~._, ._ Em
.;,..`,__zj_r
3 _ tzz..->1. z vv
z ...

onreatei)

de volta para a

onStart() '41-1 OHRGSHHO l


onesume

*f A mw' 'ty
EXQCUBDO j a executar

R notopodapha _ 2 Oul' acvfy enim 1

. g;P31z53()
,. __ A a executar
`
KOJJIHS
A activity visitar?

A activity no est mais 1/SIG

L j ao usurio e ser encenada __*


' onStop(3

onDestroy{)

Figura 8.11 - Ciclo de vida de uma activity.


262 Google Android - 4' Qdiu
. , . . - z ' oficial. Caso voc re '
- . - ue o ca itulo 4
Note que o diagrama esta em ingles, pois e da documentaaf? I P 915
relembrar em detalhes como funciona o ciclo de vida, Vflq P 50bre
a classe Activity.
O ciclo de vida de uma activity contm os tradicionais metodos onCreate( ), que so
chamados uma nica vez quando ela in iciada, e os mtodos como onPause() Q
onStop(), indicando que a activity ser interrompida e movida Para Segundo Plano.
Outro mtodo clssico o onDestroy(), chamado uma mca vez ao destruir a activity.

Seguindo esse mesmo princpio, tambm o ciclo de vida dos fragments contm esses
mesmos mtodos, os quais so amarrados com a activity que declarou o fragment,
conhecida como host activity. Portanto, quando algum mtodo do ciclo de vida de
uma activity for chamado, como por exemplo, o onPause(), o sistema vai chamar Q
mtodo onPause() em todos os fragments dessa activity. Da mesma forma, quando
o mtodo onResume() da activity for chamado, o mtodo onResume() de cada fragnent
tambm ser.
A maioria dos mtodos do ciclo de vida dos fragments um espelho dos mtodos
da activity, mas tambm existem outros mtodos especcos que existem somente
nos fragments, conforme podemos visualizar na figura 8.12. No lado esquerdo da
gura, podemos ver a ordem em que cada mtodo do ciclo de vida chamado.
No lado direito da gura, feita uma comparao com os estados de uma activity
Podemos ver que os mtodos onStart(), onResume(), onPause() e onStop() so sim
ples, e quando os mtodos da activity forem chamados, eles tambm sero
chamados nos fragments. Os mtodos onAttach(activity), onCreate(), onCreateView()
e onActivityCreated() so executados durante a criao da activity durante o on
Create(). Por exemplo, quando uma activity informa o seu layout pelo mtodo
setContentView(view), os fragments so inados e criados, ento os mtodos onAttach().
onCreate() e onCreateView() so chamados no fragment. Mas somente quando 11
activity retornar do mtodo onCreate() dela que o mtodo onActivityCreated() do
fragment ser chamado. importante ter conhecimento disso, pois nesse mo
mento o fragment sabe que a inicializao da activity foi realizada gm Sucesso
0 que Significa que OCOS OS fragments do layout tambm foram inicializados 6
tiveram suas views criadas.

Complementando, quando uma activity destruda durante 0 Seu mtodti


OHDHSFO)/i), OS metodos D@Sf0yV0w(), onDestroy() e onDetach() so chamados em
sequencia para encerrar os recursos e desassociar o fragment da activity que est
sendo destruda.
1
Captulo 8 1 Fragmemg

Mtodos dos Fmgmgm,


263

. . 'E ' '"


~ " l l f _ nmwmzcveaw
r---smnmmoo V. i A Started

"`" Y
l

Usurio pressiona
' v"' I
*a 1

"P"' S'
Oagmeni i` " `' Y
. . . _ . novamenfepois VE
""" mstopo *I l executada . "' ' f^ ''~'~~~f~ e ea -~-~~z
Y

/ ' . . ~ ' " _ A~ -. :.. zf l ' 7. :


~ =:.<_?*. ij

OD6nd1() gm T
._....__
DWUBSYOYO

Figura 8.12 - Ciclo de vida de um ragment.

A lista a seguir mostra os principais mtodos de ciclo de vida especficos dos


fragments:

l\[|t0____g4___g g Descrio
onAttach(acti.vi.ty) Esse mtodo chamado logo depois de o fragment ser as
sociado com a activity o que acontece assim que a activity
infla o layout do fragment pela tag ou o tragment e
adicionado dinamicamente via Fragmenransacton. Note que
o importante deste mtodo que ele recebe como parmetro
a activity que contm o fragment. Somente depois que esse
mtodo chamado (mas no nele), o mtodo getActivity()
do fragment vai retornar a activity host.
onCreate(bund1e) Esse mtodo chamado apenas uma vez e quando o fragment
est sendo criado. Ele recebe o Bundle que foi salvo durante
o mtodo onSaveInstanceState(state).
264 Google Android - 4 edio

Mtodo --'3FS59.(9"-) -- ~- e
onCreateView(inater,viewgroup,bund1e)
Nesse mtodo, o fragment precisa criar a view que ser
inserida no layout da activity Somente depois de esse
mtodo retornar, possvel chamar o mtodo getView()
que retorna a view que o fragment tem.
onActivityCreated(bundle) Esse mtodo chamado logo aps o onCreate() da
activity ter sido finalizado. Esse pode ser um bom
momento para consultar os web services e buscar 0
contedo necessrio para criar 0 layout.
onDestroyView() Esse mtodo chamado quando a view do fragment
foi removida e no pertence mais ao fragment. Depois
desse evento, o mtodo getView() do fragment vai re.
tornar null..
onDestroy() Chamado para indicar que o fragment no est mais
sendo utilizado e ser destrudo.
onDetach() Oposto do mtodo onAttach(actvity), esse mtodo
chamado quando o fragment foi desassociado da
activity Depois desse evento, o mtodo getActivity()
do fragment vai retornar null.

Dica: no se preocupe se no entender tudo sobre o ciclo de vida dos fragments


ou da activity. Continue lendo, e revise esse assunto quando achar necessrio.

8.8 Migrando um projeto que utiliza activity para fragments


Um dos exemplos mais comuns de uso dos fragments e um dos primeiros que

_ i
voce precisa entender como reaproveitar o cdigo entre a verso smartphone e
tablet, conforme a figura 8.13.

y. . ou
Nrvllvh Acuvny a I _ _ A com dos
Figura 8.13 - F
mgment que divide a tela em pedaos.
Captulo 8 n Fragments 265
No prximo exemplo, vamos criar uma lista com os nomes dos planetas e ao
selecionar um item da lista vamos navegar para outra activity que vai mostrar os
detalhes do planeta. O layout ser extremamente simples, pois estamos interessa
dos apenas em estudar os fragments. A gura 8:14 mostra o exemplo funcionando.
Observe que na segunda tela o nome do planeta mostrado no ttulo da action bar.

, . Terra
Mercuro
\____/'

Ci>
VGIUS

MBR!

Jptiet

Saturno

Figura 8.14 - Navegao de telas com duas activities.

Para comearmos o exerccio, abra o projeto Planetas-Activity. O cdigo-fonte


simples. Existe uma activity com um Listview na primeira tela e uma activity com
apenas um Textview na segunda tela. O exemplo j est funcionando, mas no utiliza
fragments. A classe MainActivity a activity que mostra a lista de planetas, e a classe
PlanetaActivity a segunda tela que recebe o nome do planeta por parmetro. Por
favor, abra o projeto de exemplo no Android Studio e execute no emulador. D
uma rpida olhada no cdigo para continuarmos o exerccio, pois vamos migrar
o projeto para utilizar fragments.
A alterao que vamos fazer encapsular a view e lgica dessas duas activities
em fragments. Para comear, vamos criar o fragment PlanetasFragnent com o layout
do Listview. Basicamente, a lgica da classe MainActivity ser transferida para esse
fragment.

P|anetasFragment.java
public class PlanetasFragnent extends android.support.v4.app.Fragment{
@0verride
public View onCreateView(Layoutlnater inater, @Nullable Viewroup container,
@Nullable Bundle savedInstanceState) {
View view = inater.inate(R.layout.fragment_planetas, container, false);
266 Google Android - 4' edio
// LiStView
Listview listview = (ListView) view.ndViewBy 1d(R.id.listview);
listView.setAdapter(new PlanetaAdapter(getActivity(ll);
listview.set0nItemClickListener(onItemClickPlaneta());
return view;
}

private Adapterview.0nItemClickListener onItemClickPlaneta() {


return new Adapterview.0nItemClickListener() {
@0verride
public void onItemClick(AdapterView<?> paret, VEW View t DOSIIOH, long id){
PlanetaAdapter adapter = (PlanetaAdapter) parent.9@t^dDtF();
String planeta = (String) adapter.getIten(position);
Toast.nakeTet(getActivity(), "Planetaz " + Dl6t3 T35t-LENGTH_5H0RT)-Show(
// 0 Context a activity, ento pode utilizar o mtodo getActivity()
// A navegao de telas continua sendo feita pela activity
Intent intent = new Intent(getActivity(),PlanetaActivity.class);
intent.putEtra("planeta",planeta);
startActivity(intent);
}

};
}

A diferena ao copiar o cdigo da activity para fragment consiste na utilizao do


context. Na activity o context ela mesma, portanto usamos o this. No fragment.
o contexto a activity portanto utilizamos 0 mtodo getActivity(). Por exemplo.
a activity utilizava este cdigo:
listView.setAdapter(new PlanetaAdapter(this));

Mas agora, dentro do fragment, o this vira o getActivity():


listView.setAdapter(new PlanetaAdapter(getActivity()));

Para continuar a migrao do cdigo para fragments, 0 fragment vai encapsular


a lista de planetas; portanto, crie o layout do fragmenr com 0 Lgtvew,

/res/layout/fragment_pIanetas.m|
<?nl version="1.9" encoding="utf~8"?
<LinearLayout nlns:android="http://schenas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="math Parent"
android:orientation="vertical" android:padding="15dp" > _

` etg natch'parent />


<ListView android:id="@+id/listview"
android:layout_width="natch _parent" android:layout h ' htz" "
Captulo 8 u Fragments 257
Nota: para acessar a classe android.content.Contet dentro do fragment, utilize o
metodo getActivity(), pois a classe Activity lha de Context.
\

O cdigo-fonte do fragment e layout so os mesmos que antes estavam na


MainAct1vity. Esse e o papel de um fragment. Ele encapsula determinadas view
e logica da tela. A vantagem disso que podemos remover a lgica da classe da
activity e no layout basta incluir o fragment conforme demonstrado a seguir:
I

MainActivity.java
public class MainActivity extends AppCompatActivity {
@0verride
protected void onCreate(Bund1e savedInstanceState) {
super.onCreate(savedInstanceState);
// 0 cdigo-fonte da activity c vazio.
setContentView(R.Iayout.activity_main);
}

/res/layout/activity_main.xml
<?xm1 version="1.0" encoding="utf-8"?>
<Re1ativeLayout m1ns:android="http://schemas.android.com/apk/res/android"
mins:too1s="http://schemas.android.com/tools"
android:1ayout_width="match_parent" android:1ayout_height="match_parent">
<fragment
android:1ayout_width="match_parent" android:1ayout_height="match_parent"
c1ass="br.con.1ivroandroid.planetas.P1anetasFragment"
tools:1ayout="@1ayout/fragment_planetas" />

Feita essa alterao, o cdigo-fonte da activity ficou vazio, e apenas a tag


foi inserida no layout. Mais uma vez, vou alert-lo para tomar cuidado ao digitar
c .ame da classe do fragment, pois o nome completo e deve conter o pacote
no qual a classe foi criada.
Pronto, j terminamos a primeira activity agora vamos para a segunda. Basica
mente, vamos fazer a mesma coisa e criar a classe PianetaFragment. Note que usamos
planeta no singular, e no no plural, como o fragment que acabamos de criar
para a lista.
268 Google Android - 4' edlm

if PIanetaFragment.}ava
public class Pl88FfQRt extends Fragnent {
@0verride
public View onCreateView(Layoutlnater inater, VBNGFOUP C"t"r
Bundle savedInstanceState) {
View view = inater.inate(R.layout.fragnent_Pl6. fif false);
return view;
l
public void setPlaneta(String planeta) {
Textvieu text = (Textview) getView().ndViewBy1d(R-ld-)
text.setText("Planeta: + planeta);
l
1

fi) /res/layout/fragment_pIaneta.xmI
<?xnl version='1.6' encoding='utf-8?>
<FraneLayout xnlns:android='http://schenas.android.con/apk/res/android'
xnlns:tools='http://schenas.android.con/tools'
android:layout_width=natch_parent android:layout_height='natch_parent'
tools:context='br.livroandroid.livroandroidcap8_planetas.PlanetaFragnent'
<TextVieu android:id='@+id/text
android:layout_width='wrap_content' android:layout_height='wrap_content'
android:layout_gravity='center' />

Esse um fragment simples que apenas mostra o nome do planeta no Textvieu.


O nico trabalho da activity inserir esse fragment no seu layout, e passar o
parmetro, que o nome do planeta para o fragment.

) PIanetaActivity.java
public class Planetanctivity extends AppConpatActivity {
@0verride

protected void onCreate(Bundle savedInstanceState) {


super_onCreate(savedInstanceState);
setContentView(R.layout.activity_planeta);
/I Parnetro enviado pela intent da activity
String planeta = getIntent().getStringExtra('planeta');
/I Pega o fragnent do layout pelo id
PlanetaFragnent f = (PlanetaFragnent)
QGSUDDOTFf9tHana9er().ndFragnentById(R.id.PlanetaFragnent);
I/ Atualiza o contedo do fragnenz
f.setPlaneta(planeta);
Captulo 8 1 Fragments 259
// Congura o nome do planeta como titulo na action bar
getSupportActionBar().setTit1e(planeta);
}

/res/layout/activity_pIaneta.xmI
<?m1 version="1.0" encoding="utf-8"?>
<Re1ativeLayout m1ns:android="http://schenas.android.con/apk/res/android"
xnins:too1s="http://schenas.android.con/tools"
android:1ayout_width="match_parent" android:iayout_height="match_parent"
android:padding="16dp" >
fragnent android:id="@+id/P1anetaFragment"
android:1ayout_width="match_parent" android:iayout_height="match_parent"
c1ass="br.com.1ivroandroid.planetas.P1anetaFragment"
tools:iayout="@1ayout/fragnent_pianeta" />

Veja que o segredo muitas vezes ao utilizar uma activity com fragments como
passar parmetros da activity para o fragment. Como a navegao de telas feita
no nvel da activity e os parmetros so passados pela intent, a activity precisa
ler esses parmetros e atualizar o fragment.
Depois dessas alteraes, o projeto deve continuar funcionando normalmente.
Assim, somente prossiga com a leitura caso seu exemplo esteja funcionando. Se
precisar, confira o exerccio pronto no projeto de exemplo Planetas-Fragnents.
Agora vamos brincar um pouco com fragments e implementar esse exerccio de
outra maneira. No cdigo que zemos at o momento, tivemos de passar um
parmetro para o fragment, e, como esse fragment est inserido de forma esttica
no layout XML, necessrio recuperar o fragment pelo id e chamar um mtodo
setP1aneta(p1aneta) para atualizar o contedo.
Outra abordagem, que eu at prero, adicionar o fragment dinamicamente
pela API. Ento para comear, altere o layout da activity do planeta e remova a
tag . Vamos deixar apenas um FraneLayout com um identificador para
adicionar o fragment.

/res/layout/activity_pIaneta.xmI
<?xn1 version="1.0" encoding="utf-8"?>
<ReiativeLayout . . .
android:id="@+id/1ayoutFrag" >
270 Google Android - 4 edio
, ,. -- ~ ment dinamicame
ossvel assar
O prximo passo e alterar a activity para adicionar o frag nte
no layout e pelo metodo setArguments(bundle) do fragment p P og
assar o mesmo Bundle que a activiti
parmetros. Note que a mgica est em p
recebeu pela intent.

PIanetaActivity.java

public class PlanetaActivity extends AppCompatActivity {


@0verride
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_planeta);
// Mostra o nome do planeta como titulo na action bar
String planeta = getIntent().getStringExtra("planeta");
getSupportActionBar().setTitle(planeta);
if(savedInstanceState == null) {
PlanetaFragment f = new PlanetaFragment();
f.setArgunents(getIntent().getExtras()); // Parmetros: mesmo Bundle da intent
FragmentTransaction ft = getSupportFragmentanager().beginTransaction();
ft.add(R.id.layoutFrag, f, "PlanetaFragment");
ft.commit();
}

Nota: se for necessrio passar um parmetro para o fragment, a nica forma


de faz-lo adicionar o fragment dinamicamente pela API. O construtor do
fragment deve ser sempre vazio, e os parmetros devem ser passados pelo
mtodo setArguments(bundle). Um conceito importante sobre 0 ciclo de vida da
activity e fragments: caso a tela do aplicativo seja rotacionada, o Android vai
destruir a activity e seus respectivos fragments. Nesse momento, o mtodo
onSaveInstanceState(bundle) chamado para dar a chance ao aplicativo de salvar
as informaes no Bundle. Logo depois, o Android vai recriar as activities e
fragments passando nos mtodos onCreate(bundle) esse mesmo Bundle com OS
objetos salvos. importante ter conhecimento de que informaes passadas
pela intent das activities e argumentos dos fragments sobrevivem a esse ciclo de
vida. Portanto, caso um fragment tenha parmetros, eles sobrevivem durante a
destruio e recriao da activity e seus fragments. Faa o teste, gire a tela do
seu smartphone e monitore as chamadas dos m todos do ciclo de vida.
Captulo 8 1 Fragments 271
A activity est passando o Bundle com os parmetros pelo mtodo setArguments(bundle).
Isso significa que precisamos ler tais parmetros no fragment. Para ler esses
parmetros ou argumentos, basta chamar o mtodo getArgunents( ), que vai retornar
o Bundle. Note que uma boa prtica validar se o mtodo getArgunents() no vai
retornar nulo, pois isso pode acontecer caso os argumentos no sejam enviados
ao fragment.

PIanetaFragment.java
public class PlanetaFragnent extends Fragnent {
@0verride
public View onCreateView(Layoutlnater inater, ViewGroup container,Bundle
savedInstanceState) {
View view = inater.inate(R.layout.fragnent_planeta, container, false);
if(getArguments() != null) { \
String planeta = getArgunents().getString("planeta");
setPlaneta(planeta);
}
return view;
}
@0verride
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(getArgunents() != null) {
String planeta = getArgunents().getString("planeta");
setPlaneta(planeta);
}

}
public void setPlaneta(String planeta) { .
Textview text = (Textview) getView().ndViewById(R.id.text);
text.setTet("Planeta: " + planeta);
l
}

Nota: eu gosto de utilizar o mtodo onActivityCreated(bundle) para iniciar a logica


da tela, porque neste momento sabemos que, pelo ciclo de vida, o metodo
onCreate(bundle) da activity j terminou. Outra vantagem que como o metodo
onCreateView(...) do fragment foi chamado e criou a view, podemos chamar o
mtodo getView() para acessar a view principal do fragment. Se voc chamar o
mtodo getView() durante o mtodo onCreateView(...), o resultado ser null.
272 Google Android - 4 edio
. . _ . _ - . ' ndo mas dessa vez
Pronto! Feito isso, o aplicativo deve continuar funciona , 0
- , ' l nocdio
fragment do planeta foi inserido pela API. Eu particularmente gosto de inserir
todos os fragments pela API, pois ca mais facil vericar todos e es g Java

8.9 Criando um layout dividido em partes nos tablets


Neste tpico, vamos continuar o exemplo dos planetas. O prorcimo passo e dividir
a tela em duas partes no caso dos tablets.
Para criar um layout especfico para tablets, podemos utilizar as seguintes pastas;
Pasta Descrio g *__ ____#___g mw, _
/res/layout-large Para tablets de 7'
/res/layout-xlarge Para tablets de 1O`
Por exemplo, se voc adicionar o arquivo /res/layout-xlarge/activity_main.xml no
projeto, quando o aplicativo for instalado no tablet de 10' esse layout customi
zado ser utilizado pelo Android. Tudo isso de forma automtica, apenas pela
conveno de nomes. Lembrando tambm que, a partir do Android 3.2, foram
criadas estas outras pastas:
Pasta Descrio
/res/layout-sw600dp Para tablets de 7'
/res/layout-sw720dp Para tablets de 1O,

Basicamente as duas pastas indicam o tamanho da tela na horizontal; a notao


sw de smallest width (menor largura). Os tablets de 7 tm pelo menos 60t)dp de
largura e os de 10 tm pelo menos 720dp de largura. Eu particularmente prefiro
utilizar a notao antiga /res/layout-xlarge para tablets de 1O pois funciona desde
o Android 3.0 e no apenas no Android 3.2.
Outra pasta importante a /res/layout-land, na qual o qualicador land de landscap
(l"l0fZ0fal); para customizar o layout para horizontal, basta inserir arquivos nessa
pasta. Voc pode inclusive fazer uma combinao dos identicadores, por exempl0
a pasta /res/layout-xlargc-land utilizada para tablets de 10 apenas na horizontal.
Para brincarmos com esse conceito, crie o arquivo e pasta /res/layout-xlarge-lam
actii/ity_main.xml, conforme mostra a figura 8_15_

. '
' a
_ i a t. z ea
Captulo 8 n Fragmemg

_n layout;
p c . i _ _~
p * zz- E
ft. mem
f dargelat1diactvty_mM,,;

wizwm@wt
z;3(.,;,,,,

alizado a seguir:
3 I Tm l
. .; ' * " c _. ""f`

H F* ldravvable-mdp hbleow
1 V llayout l L_lGridLayout
_' activity__main.xmI i Relativeuyout
* activity _planeta.xrnI C3 WMQS
9 .v
1

l
1

l * ?~*@@M#
Y%iz;zi
jmgnu
6dapter_pIneta.xm
fragment_pIant.mI
fr! rnent hnetasxml

P Small Button i
A *~ Bu
13RadoButton
|33v.zu.,-,,,gz0d, [ChecI<Bc|
AndroidManfest.xml H Swllh i
f E1 -szs=
I .V _tI9ss!sHsfrf=

androd:orentaton="horzonta1"
* r
L h:^--
- ~1._.,f~~~~-~.t
,_
' : ]]::;m`dTest E; ~- z _! ta' l:1N=10' i..})' @0Dmtme m- ). zq.
. V' Chuva ElFrameLayout \ ll W l .
~ Eb;_|vmnd,,d_| m,d p8_pmet ' {:|Lin:arLayout (Horizontal
V res ` E]LinearLayout (Vertical)
P Edrawable-hdpi l:lTabI:Layout

r! mzin TetV|ew
-mal Large Text
l L Medium Text
Small Tzzz

Figura 8.15 - Pr-visualizao do layout para tablet.

C* cdigo-fonte do arquivo /res/layout-xlargaland/actit/ity_main.xml pode ser visu

/res/layout-xlarge-Iand/activity_main.xmI
<?xm1 version="1.0" encodng="utf-8"?>
<LnearLayout xmlns:androtd="http://schemas.androd.com/apk/res/androd"
xmlns:tools="http://schemas.androtd.com/tools"
androd:layout_wdth="match_parent" androd:1ayout_height="match_parent"

fragment androtd:td:"@+d/PlanetasFragnent"
androd:layout_wtdth="Gdp" androd:1ayout_weight="1"
androd:1ayout_hetght="match_parent"
c1ass="br.com.Ivroandroid.planetas.P1anetasFragment
tools:1ayout="@1ayout/fragment_p1anetas" />

<fragnent android:td="@+td/P1anetaFragment"
androtd:layout_wdth="0dp" androd:1ayout_weght="1"
androd:1ayout_heght="match_parent"
cIass="br.com.1vroandrotd.planetas.P1anetaFragment"
tools:layout:"@1ayout/fragment_p1aneta" />
</LnearLayout>

Depois dessa alterao, ao executar o ap licativo em um tablet de 1O na hori


zontal, o layout ser ddivi i o em
d duas artesp (direita e esquerda). E necessrio
alterar o cdigo para que,l ionar
ao seum
ec laneta
p na lista, ele seja atualizado no
l
i
274 Google Android - 4 edio
, . . z - ' ctivities vai conti
fragment que esta na direita; caso contrario, a navegaf) de 3 uaf
acontecendo no tablet.
Um jeito fcil de fazer isso buscar of ragmen
t elo identicador
p com o mtodg
ndFragnentById(id). Se ele existir, sabemos que o apliCativO 6518 XCUf3Cl0 no
tablet de 10 e na horizontal. Nesse caso, basta atualizar o conteudo do fragmem
chamando qualquer mtodo de sua classe. Se o fragment da dlrlt 1130 X1stir,
significa que o aplicativo est executando em um smartphone OU HO tablet na
vertical, e a navegao de telas feita normalmente.

PIanetasFragment.java
public class PlanetasFragnent extends android.support.v4.app.Fragnent {
@0verride
public View onCreateView(Layoutlnater inater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) [

private Adapterview.0nItenClickListener onItemClickPlaneta() {


return new Adapterview.0nItenClickListener() {
@Override
public void onItenClick(AdapterView<?> parent, View view, int position, long id){
PlanetaAdapter adapter = (PlanetaAdapter) parent.getAdapter();
String planeta = (String) adapter.getIten(position);
Toast.makeTet(getActivity(), "Planetaz " + planeta, Toast.LENGTH_SHORT).show(h
PlanetaFragnent f = (PlanetaFragnent)
getFragnentHanager().ndFragnentById(R.id.PlanetaFragnent);
boolean dualLayout = f != null;
if(dualLayout) {
// Apenas atualiza o fragnent na direita se existe
f.setPlaneta(planeta);
} else {
// Faz a navegao de telas no caso do smartphone
Intent intent = new Intent(getActivity(),PlanetaActivity.class);
intent.putEtra("planeta",planeta);
startActivity(intent);
}

};
}

}
Captulo 8 1 Fragments 275
Execute o projeto no emulador com um tablet de 1O e confira o resultado. Gos
to muito de utilizar o emulador do Genymotion (genymotioncom), pois leve e
rpido. No Genymotion, voc pode criar facilmente o emulador do Nexus 10 e
testar esse exemplo.

Dica: no material de download do livro, voc vai encontrar os dois projetos de


exemplo com a lista de planetas. O primeiro projeto foi construdo apenas com
as activities; o segundo, com a soluo com fragments.

8.10 Exemplos da API dos fragments


Neste tpico, vamos estudar -o projeto DemoFragments, que demonstra vrios recursos dos
fragments. Recomendo que voc abra esse projeto no Android Studio e siga minhas
explicaes para entender cada funcionalidade. Os exemplos demonstrados no projeto
vo lhe fornecer uma base slida de conceitos sobre como utilizar a API de fragments.

No vou explicar o cdigo-fonte inteiro do projeto, pois ele simples. Vamos


apenas s partes principais. A MainActivity apresenta vrias aes na action bar,
que so configuradas no arquivo /res/menu/mena_main.xml. A gura 8.16 mostra
as opes dos itens -da action bar que existem no projeto. Cada opo demonstra
uma funcionalidade bsica -da API de fragments.

Find Fragi By id

Find Fzrag2 By Tag


E

Find Frag3 By Tag

Add Frag2
' HE

Remover Frag2

Repiace Frag

Add Fragd Args

Start Activity

Figura 8.16 - Pr-visualizao das aes da action bai:


276 Google Android - 4 edio
O arquivo /res/layut/attivily __main.xml da activity foi dividtdo`cmduas partsx

f,. =
Na parte dc cima loi inserido o Fragmentl de lorma estattca, L,21 pldflh. C 'diko
licou vazia, pois esse sera espao em que os outros lrmcms fall 'H<Js.

l ,,s
substitudos ou removidos dinamicamente./\ figura 8.17 mstra 21 Pfc'V'5U3l'Z<5<
d arquivo /res/layout/ac'tivity_main.xmI.
i: gq
,_ Rllvlly
W .munrml 1
~* . .
l Io; Liv _~;M!lu4' ' ;' `|'99"'"
1
l tz llll-dll
lb
l. fi
l

.., _. t.
l

"`*L, .__._... ..__., M . . __. .. et

Figura 8.7 - Pr-visualizao do layout da activity.

Depois dessa breve introduo, recomendo que voc execute esse projeto no emu
lador e brinque com cada opo do menu, pois so todas simples. Na sequencia,
estude o cdigo-fonte da activity para entender o que faz cada opo, mas basi
camente elas demonstram como utilizar a classe Fragmenransacton.
Uma vez que voc se familiarizou com o exemplo, vou dar algumas dicas do qUC
acho importante voc saber. Peo que execute as aes exatamente nesta ordem
que vou lhe dizer e conra os resultads.

Dica: no emulador, o funciona com boto voltar.

Cenrio 1

Clique Cm Find Fr92 ByTag. (_) resultado e que o fragment no existe.


(Llique ein Add Frag2 para adicionar o lragment2 no layout.
cap|I.I|0 8 n Fragments 277
Ao clicar em Find Frag2 ByTag, o fragment enggmradg

Clique em Remover Frag2 para remover o fragment pela API.


Cenrio 2
Clique em Add Frag2.

Ao clicar em Find Frag2 ByTag, o fragment encontrado.


Clique no boto Voltar. Isso vai desfazer a transao do FragmentTransacton, e vai
remover o fragment do layout. Isso acontece porque no cdigo foi utilizado o
mtodo addToBackStack(tag), que insere a transao na back stack dos fragments.
Clique no boto Voltar novamente. Dessa vez, a activity ser encerrada e o
aplicativo ser fechado. '
Cenrio 3
Clique em Add Frag2.

Clique em Add Frag2 novamente. O frag2 foi adicionado novamente por


cima do primeiro.
Clique no boto Voltar. Isso removeu o segundo frag2 que estava no topo
da pilha.
Clique no boto Voltar novamente. Isso removeu o primeiro frag2 que foi
adicionado.
Esse exemplo demonstra que devemos ter cuidado ao adicionar os
fragments, pois eles cam por cima dos outros. Como um FrameLayout foi
utilizado, os fragments adicionados ficam por cima.
Cenrio 4
Clique em Replace Frag3. Caso no exista nenhum fragment no layout, o
replace funciona como o add.
Clique no boto Voltar para desfazer a back stack. O resultado ser o layout
vazio.

Cenrio 5
Clique em Add Frag2.

Clique em ReplaceFrag3. O frag2 substitudo pelo frag3.


Clique no boto Voltar. A operao desfeita e o frag2 volta a ocupar O
layout.
278 Google Android - 4 edio

Clique no boto Voltar. O fragment2 removido do laYUt


Esse exemplo demonstra como funciona a back stack dos fragments.
Lembre-se de que isso acontece porque o mtodo addToBackStack(tag) fm
chamado no cdigo.
Cenrio 6
Clique em Add Frag4 Args.

Esse exemplo demonstra de forma simples como passar argumentos para


o fragment pelo mtodo setArguments(bund1e).
Clique no boto Voltar para remover o fragment.
Cenrio 7
Clique em Start Activity.

Esse exemplo demonstra de forma simples como iniciar uma activity que tem
um fragment no seu layout. E ainda como passar parmetros para o fragment.
Clique no boto Voltar para voltar tela anterior.
Cenrio 8
Clique no boto ReplaceFrag3.
Note que apareceu uma ao na action bar, com a gura de uma carinha/smile
Isso signica que fragments podem adicionar aes na action bar.
Ao clicar na ao, o prprio fragment faz o tratamento do evento.
Nos prximos tpicos, vamos revisar alguns conceitos importantes que vimos
nos exemplos desse projeto, como a back stack e como os fragments adicionam
aes na action bar.

8.11 Back stack

O mtodo addToBackStack(tag) da classe Fragmenransaction adiciona um fragml


na baCl< Sf2Cl<, O que significa que, ao clicar no boto voltar, a operao desfeita.
O parmetro do mtodo addToBackStack(tag) a tag que identica esta transao.
mas (5350 f55 nao Sela 1mP0ffHt para a lgica do seu aplicativo possvel paS5f
Wu- Q metodo PPBC|<5Cl<() da Classe Fragmentanager utilizado para desfazer a l'
uma Operao ou 5eJa desempilhar a back stack dos fragments, e funciona COITW
o boto Voltar. O mtodo popBackStack(string tag, int ags) da classe Fragrientllanager
Captulo 8 1 Fragments 279
recebe a tag que identifica a operao e um flag, que pode ser O ou a constante
Fragnentanager.POP_BACK_STACK_INCLUSIVE. Isso faz com que a back stack volte at
a tag desejada, por isso voc pode marcar a back stack ao chamar o mtodo
addToBackStack(tag). Se passar o nmero O (zero) no parmetro flags, a operao des
feita at a tag informada, mas, se passar POP_BACK_STACK_INCLUSIVE, a prpria operao da
tag informada desfeita, ou seja, todas as opes so desempilhadas da back stack.
Para concluir a ideia, cada vez que utilizamos a FragnentTransaction e fazemos
commit(), podemos dar um nome para essa transao. exatamente isso o que
faz o mtodo addToBackStack(tag). Ao adicionar esta transao na back stack, tudo
pode ser desfeito para voltar ao estado anterior. O mtodo popBackStack(string tag,
int ags) fora o estado a voltar exatamente para o nome da tag que voc salvou.

Nota: da mesma forma que o boto voltar utilizado para desempilhar as


activities da pilha de atividades (activity stack), o comportamento o mesmo
caso os fragments sejam adicionados na back stack. Nem sempre voc vai utilizar
esse recurso, vai depender do que sua aplicao est fazendo, mas importante
conhecer seu funcionamento.

8.12 Adicionando botes na action bar pelo fragment


Um fragment pode adicionar botes na action bar normalmente, mas para isso
obrigatrio que ele informe ao sistema por meio da chamada do metodo
setHas0ptionsMenu(true).

Se o fragment informar ao sistema que ele deseja adicionar aes na action bar, o
mtodo onCreateOptionsMenu(menu,inater) ser chamado. Basta inflar o XML de menu.
A seguir podemos visualizar o cdigo-fonte da classe Fragnent3 do exemplo anterior.
3

Fragment3.java

@0verride _ _
public class Fragnent3 extends android.support.v4.app.Fragnent {

public View onCreateView(Layoutlnater inater, Viewroup container,


Bundle savedInstanceState) { .
View View = inater.inate(R.layout.fragnent_3, container, false);
setHas0ptionsMenu(true);
return view;
}

@0verride
P ublc void 0nCreate0ptionsHenu(Menu menu, Henulnater inflater) {
280 Google Android - 4a Edio
inater.inate(R.nenu.nenu_frag3, menu);
}

@0verride
public boolean onOptionsItemSe1ected(HenuItem item) {
int id = item.getItemId();
if (id == R.id.action_he11o_frag3) {
Toast.nakeText(getActivity(),"Hello ActionBar Frag 3",Toast.LENGTH_SHORT).Show(M
return true;
}

return super.on0ptionsItenSe1ected(item);
}

public void he11o() {


Toast.makeTet(getActivity(),"Hello Frag 3",Toast.LENGTH_SHORT).show();
}

) /res/menu/menu_fragment3.java
<menu xn1ns:android="http://schenas.android.con/apk/res/android"
m1ns:too1s="http://schenas.android.com/tools"
xm1ns:app="http://schenas.android.con/apk/res-auto" >
<item android:id:"@+d/action_he11o_frag3"
android:title:"@string/he1io_frag3" android:icon="@drawab1e/smilel"
app:showAsAction="a1ways" />

A gura 8.18 mostra o boto com o cone de smile, o qual foi adicionado pelo fragmem.

_.,1
l7f'~`u l .)i]i

OK

Heilo Activity

F Q e- rw

FEWG 8.18 - Fragment com ao na action ban


Captulo 8 1 Fragments 231
8.13 Salvando o estado de um fragment
A maioria dos aplicativos consulta dados na internet por meio de um web service
e essa tarefa pode demorar
g os alguns
epen endose
da und d d `da' co
velocidade
nexo. Caso o usurio gire a tela, por padro o Android vai destruir a activity e
f
seus ragments, para depois recri~los. Nesse momento podemos salvar o estado
da tela, para depois recuperar os dados do web service e evitar a necessidade de
buscar os dados novamente da internet.
No exemplo anterior, o fragment 1 que foi inserido de forma esttica no layout da
activity demonstra como salvar o estado. Se voc clicar no boto OK da tela, ver
que uma varivel int count incrementada e impressa na tela com um toast. A se

}.
guir, podemos visualizar o cdigo simplicado desse fragment, no qual podemos
Ver como salvar 0 estado da varivel count, a fim de preservar o estado durante a
troca de orientao da tela.

Fragmentl .java
public class Fragmentl extends android.support.v4.app.Fragment {
private int count;
@0verride
public View onCreateView(Layoutlnater inater, ViewGroup container,
Bundle savedInstanceState) {
View view = inater.inate(R.layout.fragment_1, container, false);
// Recupera o estado da varivel
if(savedInstanceState != null) {
count = savedInstanceState.getInt("count");

count++; _
view.ndViewById(R.id.bt0k).set0nClickListener(new 0nClickListener() {
@0verride
public void onClick(View v) {

Toast makeTet(getActivity(), "Countz " + Count, Toast LENGTH_L0NG)-Sh0W(),


}

}) ;
return view;
}

@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outSta'C2); d
outState.putInt("count",c0Unt)5 / Salva esta
}

}
, . ndle no '
282 Google Android - 4 edio
(,omo vimos, para salvar o estado, basta preencher o Buf metodo
onSaveInstanceState(bundle), que chamado antes de destruir O fgmem- Dpoig,
ao recriar a view do fragment, basta ler os dados desse Bundle: Dependendo dos
objetos e variveis do fragmer1t,pOdmOS decidir 55 C necessario mlclallzaf 8 tela
ou no. Por exemplo, podemos decidir se nece ssrio buscar os dados do web
service ou no.

Outra maneira de preservar o estado do fragment, que muito utilizada devido


sua facilidade, o mtodo setRetainInstance(true). Caso esse mtodo seja chamado, 3
instncia do fragment ser preservada durante a rotao. Assim, o objetivo inteiro
do fragment ser mantido em memria, e apenas o mtodo onCreateView(inater,
container,bundle) ser chamado para recriar e retornar a *view Todos os atribu
tos, objetos e variveis do fragment sero mantidos vivos, pois a instncia do
objeto do fragment preservada. Ento faa o teste! Basta chamar o mtodo
setRetainInstance(true) durante os mtodos onCreate() ou onCreateView() do fragment
e pronto. No necessrio implementar o mtodo onSaveInstanceState(bundle).

Fragment1.java
public class Fragnentl extends android.support.v4.app.Fragment {
private int count;
@0verride
public View onCreateView(Layoutlnater inater, ViewGroup container,
Bundle savedInstanceState) {
View view = inater.inate(R.layout.fragnent_1, container, false);
// Indica que este fragnent deve preservar seu estado
setRetainInstance(true);
view.ndViewById(R.id.bt0k).set0nClickListener(new 0nClickListener() {
@0verride
public void onClick(View v) {
count++;

Toast.makeTet(getActivity(), "Countz " + count, Toast.LENGTH_LONG).show();


}
});
return view;
}

|'+ . [estar 3 fmca de Orientao da tela no emulador, pressione as teclas


gvfafa
(apitulo 8 n Fragments 283
8.14 Vantagens de utilizar os fragments
Depois de ler este capitulo, vamos revisar alguns conceitos importantes e as van
tagens de utilizar fragments.
1. Deixa o cdigo da activity simples, pois a lgica ca nos fragments.
2. Um fragment tem seu prprio ciclo de vida, o qual associado ao ciclo de
vida da activity Por exemplo, se a activity chamar os mtodos onPause () ou
onResume(), eles tambm sero chamados em todos os fragments da tela para
permitir que cada classe gerencie o seu estado.
3. Permite criar componentes reutilizveis.
4. Permite reutilizar o cdigo entre as verses smartphone e tablet, ou at
mesmo reutilizar cdigo dentro do smartphone.
5. Fragments so como miniactivities, pois tm um ciclo de vida bem denido.
6. Fragments so como views, e basta inclu-los no layout.
7. Fragments so utilizados em aplicativos que utilizam action bar com Tabs
e ViewPager, para gerenciar o contedo de cada tab ou pgina.
8. Com o uso da API, os fragments podem ser adicionados, substitudos e
removidos facilmente de qualquer posio do layout.

8.15 Links teis


Neste captulo, estudamos uma das principais APIs de desenvolvimento de UI no
Android, utilizada principalmente para criar componentes reutilizveis de cdigo,
facilitando a manuteno do projeto.
No projeto dos carros que vamos desenvolver nos prximos captulos, usaremos
fragments em conjunto com a navegao por tabs da action bar. Fique tranquilo,
pois ainda vamos estudar muito esse assunto, e o melhor: voc vai aprender de
senvolvendo o aplicativo dos carros passo a passo.
cparei alguns dos principais links cuja leitura recomendo:
Android API Guides - Fragments

http://developer android.com/guide/componemts/fragmcnts.html
Android API Guides - Supporting Tablets and Handsets

http //developer android. com/guide/practices/tablcts-and-humiscts. html


. Android Training - Building a Dynamic UI with Fragments

http '//developer android. com/training/basics/fragmcr1ts/i ndex.lmn1


~` `e CAPTULO
/z' .J
1

Animaes
H
.

Animaes do um acabamento prossional ao aplicativo, e costumam enriquecer


a experincia do usurio.
Neste captulo, vamos estudar diversos recursos de animaes, como movimentar
a view pela tela, criar efeitos de transparncia e muitos mais.
Vamos estudar a API de Animations, utilizada desde as primeiras verses do
Android, assim como a nova API Animator, criada no Android 3.0 Honeycomb.
Alm disso, veremos diversas dicas sobre animaes em geral.

9.1 Drawable Animation

Para comear a brincadeira, vamos estudar a classe androd.graphcs.drawab1e.


AnmatonDrawab1e, utilizada para criar uma animao de guras como se fosse um
GIF animado.

Esse tipo de animao feito com um arquivo XML na pasta /res/drawable, basta
congurar a lista de guras.

/res/drawable/Iist_Ioading.xmI
<?m1 verson="1.0" encoding="utf-8"?
<anmation-list xmlns : android="http: / / schemas . and rod . com/ apk/ res / androtd
android:oneshot="fa1se" >

<iten androdzdrawable @drawab1e/1oadng_01 androidzduratgn 299


<i.tem androdzdrawable @drawab1e/1oading_02 androidzduration 200
<ten androidzdrawable @drawab1e/1oading_03 androdzduraton 266
<tem androd:drawab1e @drawable/loadng_G4" androdzduratign 299
</animation-1ist

O arqulve representa uma gufa que vai animar as imagens 1oadng_61,1oad9-92


1oadng_03, 1oadng_04 sequencialmente, com um intervalo de 200 milissegund05
284
Captulo 9 n Animaes 285
Para ter essa animao em um Imagevew basta utilizar a propriedade androtdzsrc
normalmente, informando a imagem que contm a lista
<ImageView android:id="@+id/img"
3"dfd1lY0U_Wdth="wrap_content" android:1ayout_height="wrap_content"
android:src="@drawable/1ist_1oading" />

No cdigo, podemos usar o mtodo getDrawab1e() para obter o objeto AnimationDrawab1e


da animaao e chamar o mtodo start().
I

Imagevew img = (lmageview) ndVewById(R.d.mg);


AnimationDrawab1e anim = (AnimationDrawab1e) img.getDrawable();
anm.start();

Tambm possvel utilizar a propriedade androdzbackground em vez de androidzsrc.


<ImageView androd:d="@+id/img"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:background="@drawab1e/1st_1oadng" />

Neste caso, usaremos o mtodo getBackground() para recuperar o Anmatonmawable.

Imageview img = (lmageview) ndViewById(R.id.mg);


Animatable anm = (AnimationDrawable) img.getBackground();
anim.start();

9.2 Classe Animation


At antes do Android 3.0, a classe android.view. anmation.Anmati.on junto com a classe
android.view.anmaton.AnmatonUtils formaram a dupla principal para trabalhar com
animaes no Android. A classe Animation tem cinco subclasses:
AlphaAnmaton - Animao de transparncia.
RotateAnmation - Animao de rotao.
Sca1eAnmaton - Animao de escala.

. . ` 'I , ' ~ L 'L _ 3 T1


Trans1ateAnmaton - Animao de mOVimI1f0
AnimationSet - Classe utilizada para criar um grupo de 11IT1210@5 Pq* 1 SCM
executadas ao mesmo tempo.
Essas classes de animaes podem ser encapsuladas inclusive em arquivos XML,
para evitar que o desenvolvedor escreva muito cdigo. Por exempl0, SC P1`CC51`m5
criar uma animao qu e vai deixar uma view transparente gradatvamllf, WSY11
este simples trecho de codigo:
286 Google Android - 41 Mm
View view = ?
Animation a = AnimationUti1s.IoadAnimation(this,and 'd.R.anim.fade_in);
FOI
a . setDuration(2000);
view.startAnimation(a);

O mtodo utiliza a classe AnimationUti1s para carregar uma animao de transparn_


cia que vai deixar a view invisvel. Note que o parmetro passado e um recurso dg
animao que pode ser acessado pela famosa classe R. Nesse caso, usamos a classe
android.R nativa do Android para acessarmos um recurso de animao j existente
na plataforma. Tambm possvel criar animaes personalizadas e inseri-las na
pasta /res/anim. Observe que a classe Animationtiis serve para inflar 0 arquivo de
animao em um objeto do tipo Animation. Nesse exemplo estamos carregando 3
animao android.R.anim.fade_in, e isso retorna um objeto do tipo A1phaAnimation.
Depois que uma animao criada, podemos customizar a forma como ela vai
ser executada. Nesse exemplo, foi chamado o mtodo setDuration(mi11is) para con
gurar o tempo em milissegundos que o efeito da animao deve durar. A seguir

Mtodo Descrio _g
temos alguns dos principais mtodos da classe Animation.

setDuration(mi11isj- Congura o tempo em milissegundos que o efeito da


animao deve durar.
setFi11After(boo1ean) Este ag indica que o efeito da animao, conhecido como
transformao, deve ser mantido ao terminar a execuo
O valor default false. Por exemplo, se criarmos uma
animao de fade_out em uma vievig a mesma ir desa
parecer aos poucos. Mas ao nal da animao a view vai
voltar ao normal, aparecendo novamente. Para que a view
permanea invisvel ao trmino da animao, esse mtodo
deve ser chamado.
S@Uf@fD0t0f() Informa qual a implementao da interface Interpoiator
que ser utilizada. O padro Linearlnterpolator.
setRepeatCount(int) Quantidade de repeties que a animao deve efetuar.
O padro O (zero).
5@tRP@tN0d(t DO) Conguraseaanimaodeverepetirouno.chamadop1I`1
deixar uma animao em loop: setRepeatMode(Animati0
INFINITE).

Por ultimo, depois que a animao foi criada, basta chamar o mtod0
view.startAnimation(animation) para iniciar a animao

N C fC0mIidVl Crlar as animaes utilizando arquivos de XML dentro


da pasta /res/amm. Podemos e
ncontrar vrias animaes j disponveis de
forma nativa no Android, dispensando a criao de arquivos de animao
Captulo 9 n Animaes 287
customizados. Por exemplo, as animaes fade in e fade out j esto presentes
no Android; basta selecionar a classe android.R para utilizar os recursos nativos.
Dentro da pasta /android-sdk/platorms/$(plataformaj/data/res/anim voc pode
encontrar as animaes padres da plataforma.

9.3 View Animation

View Animation 0 ,framework de animaes at o Android 2.x, e com ele podemos


criar efeitos de transparncia, movimento, escala e rotao de forma simples.
Nos prximos tpicos, vou explicar como criar cada um desses tipos de animao,
e recomendo que voc abra 0 projeto ViewAnmaton de exemplo deste capitulo para
acompanhar as explicaes. importante que voc execute o cdigo no emulador
para visualizar as animaes acontecendo. A gura 9.1 mostra o projeto de exemplo
executando no emulador, com um exemplo da animao de transparncia, que
a classe AlphaAnmaton, a qual vamos estudar no prximo tpico.

liiimf AnImarcomAPI
Rotate

Scale
i

"Translate
i.
AnimationSet l

i; _d
, -_ i ~ ,_ _ ,
__A__
Animationstener 1
i. .. _. -~~f~~~---f-*~-^
E

Figura 91 -Imagem quase desaptzmceizco durante a animao de transparncia.

9.4 AIphaAnimation
. . ' ' ~~ >scondei' ii view
A classe A1phaAnmation perm ite criar os famosos efeitos de fade_in e fade_out. 1721111
^ ' da viewcom
alterar a transparencld 0 obietivo de mostrar ou ea
288 Google Android - 4 edio
Na prtica, a classe AlphaAnination altera a propriedade alpha da view FSPOSvcI
pela transparncia. Sempre que o alpha for 0.0 (zero), Slgmca que '3 VICW est
invisvel, e sempre que o alpha for 1.0 ela est 100% visvel. A propriedade alpha
um oat que varia entre 0.0 e 1.0. A tabela a seguir resume os dois parametros
utilizados pela classe AlphaAnination.

Pp'dq,___.__.____ -_ .-.- - -_ azaa A A- -~


oat fronAlpha Valor inicial da propriedad lph
oat toAlpha Valor nal da propriedade alpha.
Para usar a classe AlphaAnination, podemos utilizar um trecho de cdigo como este;
View view = /* qualquer view */
boolean show = false; // Mostrar ou no a view?
AlphaAnination fade_out = new AlphaAnination(1.0f, 0.0f); // Apaga a view (alpha 1 parae)
AlphaAnination fade_in = new AlphaAnination(0.@f, 1.Gf); // Mostra a view (alpha G para1)
AlphaAnination a = show ? fade_in : fade_out;
a.setDuration(2000); // 2 segundos
a.setFillAfter(true); // Manter o efeito no nal da animao
view.startAnimation(a);

Outra forma de fazer a animao criar um arquivo XML com a denio


da animao e inseri-lo na pasta /res/anim. Nos exemplos a seguir, a animao
/res/anim/fade_in.xmI faz a propriedade alpha ir do 0.0 invisvel para 1.0 visvel. A ani
mao /res/anim/fade_out.xmI faz a propriedade alpha ir do 1.0 visvel para 0.0 invisvel.

/res/anim/fade_in.xmI
<?xml version="1.0" encoding="utf-8"?>
<alpha xnlns:android="http://schenas.android.con/apk/res/android"
android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="2000" /

/res/anim/fade_out.xmI
<?xnl version="1.0" encoding="utf-8"?>
<alpha xnlns:android="http://schenas.android.con/apk/res/android"
android:fromAlpha="1.0" android:toAlpha="0.9" andrQid;durati0n="z9en" /

Uma vez que os recursos de animao foram criados, podemos utilizar a classe
Aninationutils para carregar e iniciar a animao. Nesse momento podemos utilizar
3 Classe R do 110550 pI`OpI'lO pI'Oj[O para 3CSS8I` SSS I'CLlI'SOS.
View view = /* qualquer view */
boolean show = false; // Mostrar ou no a viewv
int anin = show ? R.anin.fade_in : R.anin.fade_out'
.O
Captulo 9 1 Animaes 289

Animation a = Animationutils.1oadAnimation(this, anim);


view.startAnimation(a);

Nota: estou mostrando apenas o trecho de cdigo necessrio para criar as


animaoes, por isso recomendo que execute no emulador o projeto de exemplo
deste capitulo.

9.5 RotateAnimation

A classe RotateAnimation serve para para rotacionar uma vievig na qual so utilizadas
as coordenadas x e y e um ngulo em graus para a rotao. Para essa animao;
c possivel configurar um ponto que ser o eixo da rotao. O padro da rotao
a partir do canto superior esquerdo da vievig que tem os pontos x = O e y = O.
A tabela a seguir resume os dois parmetros utilizados pela classe RotateAnimation:
Propriedade Descrio

oat fromDegrees Valor inicial do ngulo para rotacionar.


oat toDegrees Valor nal do ngulo para rotacionar.
int pivotXType Tipo da rotao aplicada baseada no eixo x, podendo assumir uma
das trs constantes: Animation . ABSOLUTE,Animation . RELATIVE_T0_SELF
011Animation.RELATIVE_T0_PARENT.

oat pivotXVa1ue Valor no eixo x para servir de eixo da rotao. Pode receber um
valor absoluto em pixels, em que O (zero) representa o canto
esquerdo superior ou valores relativos coordenada da view ou
de seu layout pai.
int pivotYType Idem a propriedade pivotXType mas para o eixo y
oat pivotYVa1ue Idem a propriedade pivotXVa1ue mas para o eixo ya

O cdigo a seguir demonstra como rotacionar uma view em 1800 graus com a
classe RotateAnimation. A primeira animao gira a vievig e a segunda gira novamente
para a posio de origem.
view view = /* qualquer view */
boolean primeiravez = true;
int angulo = 189; // Girar 180 QFHUS
Animation giralda = new RotateAnimation(0,angu1o,
Animation.RELATIVE_T0_SELF, 0.5F,
Animation.RELATIVE_T0_SELF, 0.5F)5
Animation giraRetorno = new RotateAnimation(an9Ul0,0,
Animation.RELATIVE_T0_SELF, 9.5F,
290 Google Android - 4= edio
Animation.RELATIVE_T0_SELF. 0.SF);
Animation a = prmeiravez ? giralda : gtraRetorno;
a.setDuration(2000); // 2 segundos .
a.setF11After(true); // Manter o efeito no nal da antma
view.startAnination(a);

Note que foram passados no construtor da classe RotatonAni.maton os graus inicial e


final da rotao (O e 180), e as coordenadas X e Y que sao o eixo da rotaao. Para 3
animao de retorno, foram denidos os graus inicial e nal da rotaao (l80 e 0)_
Foi informado Animation.RELATIVE_TO_SELF para indicar que a coordenada relativa
ao prprio objeto, sendo que o valor 0.5F correspondente a 50%. Nesse caso,
o valor 0.0F igual a 0%, O.5F igual a 50% e 1.0F igual a 100%. A constante
Animation.RELATIVE_T0_SELF utilizada para indicar que a rotao relativa ao objeto
que est sendo animado. Dessa forma, sabemos que o ponto X e Y que indicamos
com o valor 0.5F (50%) o centro da imagem. Se alterarmos esta constante para
Animation.RELATIVE_T0_PARENT este ponto de eixo passaria a ser o centro do layout.
A diferena na animao seria gritante. Ao rotacionar no eixo de si mesma, a
imagem nem sequer se move de lugar, ela apenas gira. Mas, se rotacionarmos a
view utilizando outro ponto como o centro do layout, ela iria se movimentar ao
redor desse ponto.
A seguir podemos ver os dois arquivos XML que fazem esta mesma rotao de
girar a view em 180. Observe que no arquivo o ngulo de rotao vai de 0 a
18O para dar um giro completo, e o eixo da rotao foi definido no centro da
imagem, conforme as propriedades androd:pi.votX e andro'td:pvotY, que no XML
podem receber o valor de 50%.

/res/anim/rotate_gira_ponta_cabeca.xmI
<?n1 verson="1.0" encoding="utf-8"?
!-- Rotao do ngulo 0 para 180 graus. -->
<rotate xmlns:androd="http://schenas.androd.com/apk/res/androd"
androd:fronDegrees="0" androd:toDegrees="189"
androd:pvotX="S0%" androd:pvotY="S0%
androd:duraton="500@ androd:11Aftef="true" /,

/res/anim/rotate_gira_ponta_tabeta_retorno.xmI
<?n1 version="1.0" encoding="utf-8"?>
<rotate xm1ns:androd="http://schenas,andr0 d.com/apk/res/android"
androtd:fronDegrees="180" android:toDegrees="0"
android:pivotX="5G%" android:pivotY=59%"
android:duraton="500B" androd:I1After="trUe" /,
(aptulo 9 z Animaes

Utilizando esses XMLs, podemos inflar o objeto da animao:


Animation giralda = Aninationutiis.ioadAnination(this, R.anin.rotate_gira ponta cabeca)
Animation giraRetorno = Aninationtils.loadAnination(this,

ifa1 ' ~ ii
R. anin. rotate_gira_ponta_cabeca_retor`no);

A gura 9.2 exibe o resultado desse exemplo, e mostra o bonequinho do Andmld


de ponta cabea depois da rotao.

1 al
' An " ' . t l . -- a , l
q Imar com XML q Animal com API T .ggfnzy mm zm, Amma, com Am
*^~ f'~--~~~ ~ f~-~~ ~-~~~ -- --_-~. __;~z z.. ..._ , ....,.. _ 1 '_.H_,,,M___;(_,_%~J_(__M_ _ 'A:_=`M___~._M

il

Figura 9.2 - Exemplo da imagem rotacionada em 180.

Nota: a notao de percentual (exemplo android:pivotX="100%") no XML de


animao vai por padro considerar a congurao relativa view, como se
tivesse utilizado Animation.RELATIVE_T0_SELF. Para fazer com que esse parmetro
seja considerado relativo ao layout pai, deve-se inserir um "p" depois do sinal
de percentual, por exemplo, android:pivotX="100%p". Dessa forma seria como se
Animation.RELATIVE_T0_PARENT fosse usado pela API. interessante que voc brinque
bastante alterando os parmetros do eixo da rotao, para que entenda bem o
funcionamento das animaes.

9 6 ScaIeAnimation
\ classe Sca1eAnimation permite aplicar animaes de escala, para diminuir ou
1ilI11CI1t8I` uma vievi: O exemplo de cdigo a seguir faz a view diminuir graditi
\ imente at ela desaparecer. Na prxima vez, vamos fazer com que ela aumente
dt novo, gradativamente, at o seu tamanho normal.
292 Google Android - 4 edio
View view = /* qualquer view */
boolean primeiravez = true; // 59 ff 3 Primeira vez, vai diminuir...
int angulo = 180;
ScaleAnimation encolher = new SClAt0(
1.0f, G.0f, // X inicial e nal
1.0f, 0.0f, // Y inicial e nal
Animation.RELATIVE_T0_SELF, 0.5f, // Eixo X
Animation.RELATIVE_TO_SELF, 0.5f // Eixo Y
);
ScaleAnimation aumentar = new ScaleAnimation(
0.0f, 1.0f, // X inicial e nal
0.0f, 1.0f, // Y inicial e nal
Animation.RELATIVE_T0_SELF, 0.Sf, // Eixo X
Animation.RELATIVE_T0_SELF, 0.5f I/ Eixo Y
);
Animation a = primeiravez ? encolher : aumentar;
a.setDuration(2000); // 2 segundos
a.setFillAfter(true); // Manter o efeito no nal da animao
view.startAnimation(a);

Assim como as outras animaes, podemos fazer o mesmo efeito com recurso
XML, o que em minha opinio bem mais simples.
O exemplo a seguir dene que as coordenadas iniciais da animao so 1.0 (100%
tanto de X quanto de Y, informando o tamanho total da imagem. E as coordena
das nais informadas so 0.0 (0%), informando que o tamanho nal da imagem
deve ser reduzido em nada. Como 0 eixo da animao foi denido como 5090.1
imagem vai diminuir aos poucos at desaparecer no seu centro.

i /res/anim/scaIe_dimnuir.xmI

<?xml version="1.0" encoding="utf-8"?


<scale xmlns:android="http://schemas_android.com/apk/res/android"
android:fromXScale="1.0" android:toXScale="0.0"
android:fromYScale="1.0" android:toYScale="0.0"
android:pivotX="50%" android:pivotY="50%"
android:llAfter="true" android:duration="2000"
/

A prxima animao o contrrio da outra. As coordenadas iniciais so 0.0, ndl


Cd qm a wam P150 5f, pois est com seu tamanho zerado. Dessa 'l
as coordenadas nais foram
_ _ _ denidas como 1.0 (1O0/Q), para que a imagem
ao seu tamanho inicial.
Captulo 9 I Animaes 293
%i /res/anim/sca|e_aumentar.xm|
<?mi verson="1.0" encodng="utf-8"?>
<sca1e m1ns:androd="http://schemas.androd.com/apk/res/androd"
android:fromXSca1e="0.@" androd:toXScale="1.0"
androd:fromYScale="0.G" androd:toYSca1e="1.0"
androd:pivotX="5@%" androd:pvotY="50%"

Ii
android:l1After="true" androd:duraton="20G0" />

/\ figura 9.3 mostra o resultado desse exemplo. Na primeira animao, a imagem


vai diminuir at desaparecer, e depois na prxima vez vai aumentar gradativa
mente at ficar com o tamanho original. Na parte direita da gura, podemos ver
a imagem diminuindo, quase antes de desaparecer.

, Animar com XML , 1 Animar com API i L Anlmar com XML /mimar esta wi
LNB* __ vi ,`_ _ ____W_W*__M_4 I l _,____,_ _, _,_ K __W

^aasaa
' ..
tgl l~ z *
l

L >~;.`5*;;,'; z.Ea.{
. . .
._ ;

i i
~
l

l
E

1E
il

Figura 9.3 - Exemplo da imagem diminuindo de tamanho.

9.7 TransIateAnimation
z\ classe TransiateAnmation serve para mover urna view pelo layOL1f ffspeclcanfio
35 goordenadas X e Y iniciais e nais da animao. Essas coordenadas podem ser
passadas como um valor absoluto ABSOLUTE em pixels de tela, ou relativo a propi ia
view RELAT1vE_To_sELF ou ao seu layoutpa1RELATIVE_T0_P^RENT
. . " . ~ z ~- ~> ateAnimation.
A mbkh il Scguif fgmn os parametros utilizados pela classe Transi
I GOOQIQHIIOU-QIQQM
Propriedade DdCfI
non fmnnym Tipo da coordenada x inicial.
float fromtvaloe Valor da coordenada x inicial.
'L-nt toXTwe Tipo da coordenada x nal.
float t~oVa1ue Valor da eoordenacln x nal.
int front/Type Idem explicado no eixo x.
float front/Value Idem eqIiendo no -eixo x.
int toi/Type Idem explieado no eixo x.
float toYValue Idem explicado no eixo X.
Biisicainente. n elnsse recebe as coordenadas X e Y iniciais c nais. 'lemos assim
quatro pontos. Para cndn ponto, e especificado qual o tipo do valor, que podf
ser Anlnatton.ABSOLUTE. Animation.RELATIVE_T0_SELF ou Animation.RELATIVE_T0_PARENT_
Sempre que o tipo de um valor 'for Antnatton.ABSOLUTE, aquele parmetro poder
recelwer valores alwso-luros. que so valores numricos que especieam a real
posio ou y em pixels. Se o tipo do parmetro for Antnatlon.RELATIVE_T0_SELF ou
Antnatton.RELATIvE_T0_PARENT, os valores informados sero em percentual. No XMI
so utilizados os valores 0% e 100%. e nojava so utilizados os valores ODF e IDF.
O trecho de codigo n seguir mostra como mover a .imagem para baixo e depois
para eimn. O valor 2 neste exemplo 6 para a imagem se mover em duas veres n
seu tamanho
View vtew - I* qualquer view */
boolean prtnetravez = true; /I Se for a prtnetra vez, nover para baixo.
Antnatton-noverParaBato = new TranslateAnnatton(
Animation.RELATIvE_T0_SELF, 8.0F. Antnatton.RELATIVE_T0_SELF, 0.0F,
Anlnatlon.RELATIVE_T0_SELF, 0.8F, Animation.RELATIVE_T0_SELF, 2.0F
):
Animation noverParaCtna = new Trans1ateAntnation(
Antnatton.RELATIV_T0_SELF, 0.0F, Antnatton.RELATIVE_T0_SELF, B.6F,
Antnatlon.RELATIVE_T0SELF, 2.0F, Antnation.RELATIVE_T0_SELF, 9.6F
):

nntnatton a = prtnetravez ? noverearahaixoz noverarattna;


a.setDuratton(200B); I I 2 Segundos
4-$\Flll~^f10f('U0) /I Manter o efeito no nal da antnaao
vtew.startAntnation(a);

-lbm Pdl`"*"5 1`*~" *HITUQCS de movimento utilizando XML. O CJIIW 'l


. ` ~ 3 1 0 '
seguir mostra uma animao-que move a imagem pu- baixo (mm. quc sis mile
nd " fim E l~ O WIN -00 ki 6 para a imagem se mover duas vezes o seu tam1lI^`
Captulo 9 n Animaes 295
ffi /res/anim/transIate_mover_para_baixo.xm|
<?m1 verson="1.0" encodng="utf-8"?>
<translate m1ns:androd="http://schemas.android.com/apk/res/android"
androd:fromDe1ta="0.0" android:toXDe1ta="0.0"
androd:fromYDe1ta="0.0" android:toYDe1ta="2@G%"
androd:1IAfter="true" android:duraton="2@00" />

E a animao a seguir o contrrio, faz com que a imagem volte para cima.

() /res/anim/transIate_mover_para_cima.xml
<?m1 verson="1.0" encodng="utf-8"?>
<trans1ate xmlns:androd="http://schemas.androd.com/apk/res/androd"
android:fromXDe1ta="@.0" androd:toXDe1ta="@.0"

l
android:fromYDe1ta="200%" androd:toYDe1ta="@.0"
android:11After="true" androd:duraton="2000" />

Nota: no arquivo de animao em XML os valores em percentuais so sempre


relativos view que est sendo animada. Se o desejado for informar um valor
relativo ao layout pai, utilize o valor com um "p" no final, como por exemplo
androd:toYDe1ta="50%p".

Ao executar esse exemplo, a imagem vai mover para baixo numa distncia de duas

i. I1g 11 _
vezes o seu tamanho, e depois na prxima vez a imagem vai se mover para cima
at voltar sua posio original. A gura 9.4 mostra o resultado dessa animao.

(___ _

*E . *llf com XML


_ | pV. s Animar com ,Wi
l

ML
i AnimarAlmf
com(Om
X _P
1 Wgmwg _``, __,\__,A_,___= W; ~_,_.\__,,.--_-._a._._...~... ; ~ ~ -fr f ^" 's

^ - e _9.4
ZIHZLI ~ -dti ozs
em '- t - ~ ' /mito
Figura Extmplo d 3 P dt st mova pam . .
296 Google Android ~ 46 adm
9.8 AnimationSet
'ma es para serem executad
A classe AnimationSet permite agrupar vrias am . b_ HS ao
mesmo tempo. A maneira de unliz-la simples: basta criar um o jeto Antmattonsez
e adicionar as animaes que devem ser executadas.
A classe AnimationSet contm ainda os mtodos para configurar as propriedades das
animaes, como o mtodo setDuration(1ong),o qual altera 0 tempo de execuo Se
alguma propriedade for alterada nessa classe, ela vai sobrescrever as propriedades
que foram antes conguradas em cada animao que foi adicionada na lista. Para
facilitar o entendimento, o cdigo-fonte a seguir mostra como mover uma imagem
ao mesmo tempo em que ela vai cando transparente, com a unio das classeg
Trans1ateAnimationt:A1phaAnimation.

AnimationSet lista = new AnimationSet(true);


Animation a1 = getAnimacaoMoverParaBaioCima();
Animation a2 = getAnimacaoAparecerDesaparecer();
1ista.addAnimation(a1);
1ista.addAnimation(a2);
// Pronto, basta utilizar a animao agora.

Se voc preferir, tambm possvel criar esta lista de animaes no arquivo


XML, no qual as tags de cada animao so agrupadas dentro de uma tag set>.
O exemplo a seguir mostra como criar a animao que move a view para baixo
ao mesmo tempo que faz ela desaparecer.

/res/anim/set_mover_para_baixo_desapareter.xmI
<?m1 version="1.0" encoding="utf-8"?>
<set xmins:android="http://schemas.android.com/apk/res/android">
<trans1ate
android:fromXDe1ta="0.0" android:toXDe1ta="0.0"
android:fromYDeita="0.0" android:toYDe1ta="200%"
android:l1After="true" android:duration="2000" />
<a1pha

3dFd=fF0f'1^1Dh6="1~0" dF0d2t0A1pha="0.0" android:duration="2000" />

No proximo arquivo e o contrrio, a view move para cima e volta a aparecer.


Captulo 9 n Animaes 297
fwl /res/an|m/set_mover_para_t|ma_apareter.mI
<?m1 version="1.0" encoding="utf-8"?>
<set xmins:android="http://schemas.android.com/apk/res/android">
<transiate
android:fromXDe1ta="G.0" android:toXDe1ta="0.0"
android:fromYDeita="200%" android:toYDeita="0.0"
android:iiAfter="true" android:duration="2000" />
<a1pha

android:fromAipha="0.0" android:toA1pha="1.0" android:duration="2000" />

Agora podemos carregar o AnimationSet utilizando estes recursos de animao:


AnimationSet setl = (AnimationSet) AnimationUtiis.1oadAnimation(this,R.anim.set_mover_
para_baixo_desaparecer);
AnimationSet set2 = (AnimationSet) Animationtiis.ioadAnimation(this, R.anim.set_mover_
para_cima_aparecer);
AnimationSet set = ag ? setl : set2;
// Pronto, basta utilizar a animao agora.

Lembre-se de que as animaes adicionadas no AnimationSet sero agrupadas em


uma nica animao. Os efeitos e transformaes de cada animao vo acontecer
tudo ao mesmo tempo, o que pode resultar em diferentes animaes. interes
sante que voc crie alguns exemplos para se acostumar com o comportamento
das animaes. A gura 9.5 exibe o resultado da animao. Na parte direita da
gura, podemos Ver a imagem se movendo para baixo e quase invisvel.

J za `*; . 1 "L;*r'
ia*
l . .>_zze_.=._x>._,,__ ..\_: _:.~..

Wi : 1. - ;~'* 1 i
, ,_
l

1 z A i_i. iriir.. .i .ir i ......~a---~ -s ~ ~~ W


Animar com XML l i Animar com API ; I p Animar com XML Ammar com API

rm
u. 5

Figura 9.5 - Exemplo de AnirmztionSct.


298 Google Android - 4= ed
9.9 Animationlistener
Se quiser monitorar o inciod enima o basta
trmino usaraa
e uma interf
, ace
android . view . animation _ Animation .AnimationListener.

Isso feito chamando o mtodo setAnimationListener(AnimationListener) da Classe


Animation, conforme demonstrado a seguir:
Animation anim = N;
anim.setAnimationListener(new AnimationListener() {
@0verride
public void onAnimationStart(Animation animation) {
// A animao foi iniciada
}

@0verride
public void onAnimationEnd(Animation animation) {
// A animao terminou
}

@0verride
public void onAnimationRepeat(Animation animation) {
// A animao est repetindo
}

});

9.10 Interpolator
Imagine que voc possui uma animao que vai mover o objeto da esquerda para
direita com o tempo de durao de dez segundos. De certa forma, podemos dizer
que, se dividirmos a distncia que ser percorrida pelo objeto por 10, o objeto vai
a cada segundo mover 10% da distncia. Se a distncia total a ser percorrida lior
100px, o objeto ser movido 1Opx por segundo. Esse o esperado e o compor
tamento padro, mas possvel alterar a acelerao dessa animao e customizar
seu comportamento.

d. . z . ` _ '
Quem dee esta taxa "rate" da animao a interface Interpolator. Como padr0~

Se nnhum interpolator for especificado, ser utilizada a classe LinearInterpolf~


qfle 22 fom q_ O efelw 5313 JUStamente o comentado anteriormente, e a anima'

em um carro l ' - . , .
ao sem COUSISWUYC C ter O mesmo efeito durante todo o tempo Agora vws
12f que 0 0bJet1v0 Seja acelerar o objeto que est se movendo Se pensarm05
E C Cma dfagaf ate ganhar aceleraao, e depois que embala \~
embora. Mas lembre-se: muita calma nessa hora Podemos criar o mesmo efew
CaptuIo9 n Animaes 299

com a animao de um objeto e aceler-la aos poucos. Usamos para isso a classe
Acceieratelnterpoiator. Para informar qual interpolator deve ser selecionado, chame
o mtodo setInterpol.ator(nterpolator) da classe Animation;
Anzimation anim = ;
ani.m.setInterpo1ator(new Acce1erateInterpolator());

E para denir o interpoiator utilizando o XML, utilize o atributo androidlrinterpoia-tor:


<?m1 verson="1.0" encoding:"utf-8"?>
<transIate , . and1rroti:inzte,rpo,1_ator="@android:anim/acceIerate_int_erpolator" />.

Existem diversas classes que implementam a interface Interpolator. Fica de exer


ccio para voc brincar com elas para testar a diferena que cada uma faz nos
efeitos de cada animao Na listaa seguir, podemos verificar a explicao das
principais classes..
Mt0d0 Descrio
AccelerateDe.cel;eratelnterpoliator A animao comea rpido. e termina devagar, mas
bem no meio d uma acelerada.
Accelerastelnterpolator A animao. comea devagar e vai acelerando.
An.tic~ipat;eIinter polator A animao- comea para trs e depois vai animando
para frente. Esse inzterpoiator d a impresso de que
oz objetovai para trs para pegar um embalo antes
de acelerar;
Antiicipateve rsh.ootl'nte rpolator Idem animao Anticipatelnterpolator, mas depois
de pegar oembalo ela se empolga e acaba passando
do alvo, de forma que tem de voltar um POUCO
BounceI'nterpoia.tor E1sse.interpo`i.a;to.r faz. com que o objeto d uns puli
nhos ao atingir o nal d_a animao, como se uma
bo-la estivesse quicando no cho antes de parar.
Cyclelnterpoiator Faz: com que a_ animao seja repetida no final por
um nmero "n" de vezes.
Deceleratelnterpolator A animao comea rpido e vai desacelerando.
Linearlnterpolator o nterpolator padro e faz com que O efeito da
animao seja constante.
Overshootlnterpolator A animao se empolga e acaba passando do alvo,
de forma que tem de voltar um p0uC0

9.11 0 problema com a API de animaes no Android 2.x


No Android 2.x a API de animao conhecida como View Animation, C Him QI"
P ossvel criar vrios efeitos especiais conforme acabamos de estudar.
300 Google Android - 41 emo
Mas esse framework de animao tem um problema classico QUC vou explicar
agora. O framework da lew Animation altera apenas a aparncia de uma vievt; mas
no o seu contedo interno, ou seja, o estado do objeto. Por exemplo, se ZrmO
uma animao para mover um boto para baixo, o esperado que o evento seja
disparado ao clicar na nova posio do boto. Mas no isso o que acontece, pgjs
o boto apenas foi desenhado em outro local, mas como se ele ainda estivegsc
l no local original. O usurio teria de continuar clicando no local de origem do
boto para disparar o evento.
No projeto de exemplo deste captulo, voc vai encontrar um exemplo que dg.
monstra essa situao, conforme a gura 9.6. A primeira parte da gura mostra 0
boto antes da animao e a segunda parte mostra o boto l em baixo, pois ele
se moveu. Conforme j expliquei, voc ter de clicar na rea denida pelo crculo,
mesmo depois de o boto estar em outra posio.
vn

6- Anim

lmf i
.` I
\
\
i/
j nlmf

aNota:nV'' ' '' ' ,- -,. ,


Figura 9.6 - Animao de movimento.

IGN Animation e o framework de animaao do Android 2.x, o qual altera


pe as a maneira como a view e desenhada, mas mantem as propriedades da
view inalteradas, o que pode causar alguns problemas

9.12 Property Animations

robusto framework de a ` ' - .


No Android 3.0 (Honeycomb) foi criada a API p
roperty Animation, que consiste em Um
mmae5~ que POCC animar e alterar qualquer propriedadf
Captulo 9 I Animaes 301
de um objeto, sobre uma linha de tempo. Essa nova API de animao vem comple
mentar a API de animao do Android 2.x, conhecida como iew Animation.
Um dos objetivos desse novo framework solucionar o problema que vimos an
terirrnente, em que a animao no alterava as propriedades internas do objeto,
apenas mudava a forma como o mesmo era desenhado. Com a Property Animation,
o conceito de animao baseado nas propriedades do objeto que podem ser
alteradas, como por exemplo a propriedade alpha e as posies x e y. Em vez de
criar classes de.objetos como A1phaAnimaton e TransIateAnmaton, podemos executar
um cdigo que vai alterar determinadas propriedades sobre uma linha do tempo.
Para criar o A1phaAnmaton, basta alterar a propriedade alpha que controla a trans
parncia, e para mover a view basta alterar as propriedades x e y.
O interessante desse framework que voc pode animar uma srie de proprie
dades, conforme vamos aprender agora.

9.13 Classe VaIueAnimator

A primeira classe que vamos estudar no novo framework a Va1ueAnmator, que


consiste em criar uma animao genrica e utilizar um istener para ouvir os
resultados durante a animao.
Nos prximos exemplos, usaremos o mesmo layout com a gura do Android dos
tpicos anteriores. Esse layout dene a imagem que ser animada, e dois botes
para criar a animao utilizando um arquivo em XML ou a API.
Para comear a brincadeira, veja o seguinte exemplo genrico de anmator:

/res/anim/animator_1_para_0.xmI
<aninator xmlns : androd="http : //schemas . android . com/apk/res/android"
android:duration="1000"
android:va1ueFrom="1" android:va1ueTo="0"
android:va1ueType="oatType" android:repeatCount="1" android:repeatMode="reverse" />

_ . . . ` ` ` ilar
Verificamos que essa animao dene que o valor inicial 1 e o nal O, mas no
dene qual a propriedade ou tipo da animaao que sera real1zado.|Isso acontece
porque o conceito de animaes nesse novo framework e generico. Podemos
informar o valor inicial e nal de forma abstrata, para posteriormente vinci
esses valores com alguma propriedd f211~
Uma caracterstica importante que podemos vericar nesse recurso de animao

esse 1interva
l lhido assar deo,
1 a Oo(note
vaqueor esco P'
que o tempo da animao foi denido como um segundo, e, portanto, durante
os nmeros so float)
302 AIIO - 43
~ ,- -. -. mos recu erar es - t
. _ . - ~ ~ 5 umte forma:
Uma vez que o recurso de animaao esteja CI'l1Cl0 Pode _ P Sa &m~
mao e instanciar um objeto do tipo ValueAmnator da seg

. _ _ _ - irias ri* .
V1u@AninatQr 3 z (va1ueAninator) Aninatorlnater.loadAninator(\h15
R.anim. aninator_1_paf3_9);

Essa configuraao de animaao informa o tempo e os valores, ao dent


quais as propriedades que precisam ser alteradas. Portant0 Para aPlCar a anima
o devemos criar um listener para car ouvindo o seu andament0,ue~ duramf
determinado tempo vai nos enviar numeros de 1 ate Tal listener po e receber os
valores e aplica-los em algum objeto durante aquele intervalo de tempot Conforme
demonstrado a seguir:
nal Inageview img = ...
V1ueAn1nr 3 z (ValueAninator) Aninatorlnater.loadAninator(th1s,
R.anin.aninator_1_para_9);
a.addUpdateListener(new ValueAninator.AnimatorUpdateListener() {
public void onAninationUtdate(ValueAninator animation) {
// Fica ouvindo os valores durante a animao
Float valor = (Float) anination.9etAniI'IatedV1U@();
// Altera o alpha
ing.setAlpha(valor);
}

});

Note que no cdigo o mtodo onAninationUpdate(anination) ser chamado vrias


vezes durante o tempo que a animao estiver executando. Chamando o mtodo
getAninatedValue(), recuperamos os valores que vo variar de 1.0 a O_O. Feito issu
podemos fazer qualquer ooisa, neste caso, estamos manualmente alterando
propriedade alpha da view o que vai criar uma animao do tipo fade_out, ou seja.
a view vai ficar transparente at desaparecer.
Como PUCCIUOS verificar, 0 novo framework de animao consiste em definir
um conjunto de valores que sero aplicados durante determinado intervalo dt
tempo, mas cabe ao desenvolvedor utilizar um listener para receber esses valore
e fazer a atualizao neceria em seu objeto
A ideia legal, mas na pratica acaba sendo trabalhosa demais Mas espere: 655
conceito que est por de baixo dos panos do framework, mas no dia a dia vamu
trabalhar com a classe 0bjectAninator, que vzii facilita; nossa vda_
Captulo 9 u Animaes 303
9.14 Classe 0bjectAnimator
Conforme vimos no exemplo anterior, tivemos um pouco de trabalho, pois foi
necessrio alterar a propriedade alpha da view manualmente.
Para facilitar a vida do desenvolvedor, foi criada a classe ObjectAnmator, que uma
subclasse de ValueAnmator, portanto faz tudo que ela faz, mas altera automatica
mente determinada propriedade. Com a classe 0bjectAnmator, criar uma animao
do tipo fade__out, variando o alpha de 1 para O, simples assim:
Imagevew img = m
ObjectAimator a = 0bjeCtAnimat0r.0fFl0at(img, "alpha", 1f, Gf);
anim.setDuraton(2G00); i
a.start();
O mtodo est criando uma congurao de animao que vai iniciar em 1 e
terminar em O, durante dois segundos. Desta vez, porm, no precisamos criar
nenhum listener, pois a classe 0bjectAnmator recebe como parmetro a propriedade
que deve ser alterada durante a animao, que nesse caso a alpha. Internamente
essa classe faz o mesmo processo manual que zemos no exemplo anterior.
Existem vrias propriedades que podemos alterar, outro exemplo seria mover a
view 100 pixels para a direita, conforme demonstrado a seguir:
Imageview img = N
0bjectAnmator a = 0bjectAnimat0r.0fFloat(img, "x", img.getX(), 100);
anm. setDuration(1l)G0);
a.start();
Note que anteriormente tnhamos as classes AlphaAnmati.on e TranslateAnmaton, para
implementar as mesmas coisas. Mas agora uma nica classe chamada 0bjectAnmator
capaz de alterar qualquer propriedade do objeto, e ainda manter o estado do
objeto, o que era um bug no framework antigo.
Para a classe ObjectAnimator conseguir alterar as propriedades do objeto, temos uma
restrio: o objeto que receber a animao precisa ter os mtodos get e set das
propriedades desejadas. Por exemplo, ao criar uma animao para a propriedade
alpha, podemos utilizar o seguinte cdigo:
0bjectAnimator a = ObjectAnimator.ofFloat(mg, "alpha", lf, GF);

Significa que os mtodos getAlpha() e setAlpha(oat) existem na classe View. Note que
o mtodo offFloat indica que o tipo do parmetro oat. Seguindo o mesmo prin
cpio, sabemos que podemos alterar a propriedade , porque existem os mtodo
304 Google Android - 4 @d
.~'"md'z
getX() e set(oat). dessa maneira que a classe 0bCt^"3tf funciona, podendo
alterar qualquer propriedade de um objeto durante a HDIITIHGO 6 Ctrminzdo
intervalo de tempo. um conceito bem flexvel.

Nota: para criar as anima _ _ d _


cs estamos usando o mtodo 0bjectAnmator.ofFloat,
porque os parmetros que estamos tentando manipular sao o tipo float, mas
tambm existem os mtodos 0bjectAnmator.ofInt e 0bjectAnu'iator.of0bJect, qug
permitem manipular outros tipos.

A lista a seguir exibe as propriedades mais comuns que podemos alterar com
essa classe, para obter as tradicionais animaes de alpha, rotate, scale, translate_

alpha

Transparncia da view que pode variar entre O e 1.

xey
Coordenadas com a posio da view

translatonX e translatonY

Essas propriedades representam um deslocamento segundo as coordena


das x e y Por exemplo, se uma view tiver a propriedade translation=-50, ela
ser deslocada 50 pixels para a esquerda. Isso til para colocar layouts
fora da tela, e depois anim-los para dentro.

rotaton, rotatlonX e rotatonY

Propriedades sobre a rotao da view em graus.


scaleX e scaleY

Propriedades para controlar a escala para redimensionar uma view

pvotX e plvotv

Propriedades que definem 0 eixo utilizado nas animaes de rota0 C


escala, em que o padro 0 centro da view
Agora que C0nhC<'3m05 3 Cl3SS 0bjectAnmator, vamos refazer a maioria dos exm'
Pl05 que @5U1dafl105 are 0 m0mf0 Para voc verificar a simplicidade dC**
framework de animao.
Captulo 9 I Animaes 305
Nota: o framework Property Animations funciona somente no Android 3.0 (I-Ioneycomb)
ou superior. Se voc deseja utilizar as facilidades desse framework em verses antigas
do Android, procure pela biblioteca Nine0ldAndroids (http://nineoldandroids.com/). Eu
particularmente utilizo essa biblioteca em meus aplicativos.

9.15 0bjectAnimator - animao fade_in/fade_out


Neste prximo exemplo, vamos implementar os famosos efeitos de fade_in e fade_out,
com o objetivo de alterar a transparncia da view

AIphaAnim.java
public class AlphaAnim extends Activity {
private boolean visivel = true;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.eemplo_animacao);
}

public void onClickAnimarXML(View view) {


Imageview img = (ImageView) ndViewById(R.id.img);
0bjectAnimator a = (0bjectAnimator) Animatorlnater.loadAnimator(this, R.anim.fade_out);
a.setTarget(img);
animar(a);
}

public void onClickAnimarAPI(View view) {


Imageview img = (ImageView) ndViewById(R.id.im9); .
0bjectAnimator a = 0bjectAnimator.ofFloat(img, "alpha", 1f, Gf);
animar(a);
}

private void animar(0bjectAnimator anim) {


anim.setDuration(2000);
if(visivel) {
anim.start();
} else {
// Apenas reverte a animao
anim.reverse();

// Inverte o ag para na prxima vez utilizar a animao inversa


visivel = lvisivel;
}

}
306 Google Android -vmjm
criar a animao
Esse exemplo utiliza a classe 0bjectAntnator parapela
' . API r
v 'Dor
XML. Para criar o mesmo cfeito em XML, l121SlH Cflf Um arquivo QIUC Cmec
com a tag c configurar as prpriCd8d5
i /res/anim/fade_out.mI
<objectAninator xmlns:androld="http://schenas.androd.com/apk/FGS/BHTO"
android:propertyName="alpha"
android:valueFrom="1" android:valueTo="G"
android:duration="1000" android:valueType="oatType" />

Ao executar esse exemplo, o resultado ser a animao de fade_ln e fade_out, como


o esperado. A classe 0bjectAninator facilita bastante a criao da animao. Uma
das funcionalidades mais interessantes 0 mtodo reverse() disponivel na classe
Animator, que faz com que uma animao execute no sentido inverso, desfazendo
-se. Esse mtodo um espetculo porque no precisamos criar duas animaes
distintas, uma para fazer o objeto aparecer e outra para desaparecer. Basta chamar
o mtodo reverse() e a animao executada no sentido contrrio. Compare essa
implementao com a anterior e veja a diferena.

Nota: o mtodo reverse() reverte a animao tornando o cdigo bem mais simples.
Nos casos em que voc precise programar vrias animaes em conjunto (ex:
alpha + translate + rotate) o mtodo reverse() realmente vale a pena, pois economiza
vrias linhas de cdigo.

9.16 Objectlinimator - animao de movimento


Para mostrar como o framework Property Animation simples, vamos refazer os
outros exemplos de animaes que j demonstramos neste captulo.
Q seguinte codigo mostra como mover a view para baixo, algo que no framework
View Animation seria feito com a classe TranslateAnnatton
Inageview img = (lnageview) ndVewById(R.d.lng);
// Pela API
0bjectAninator a = 0bjectAninator.ofFloat(tng, "y", 50 200) I/ De y 56 at 190
// Por XML

g::f"""atr 3 = (0bCt^""3tf) Anlnatorlnater.loadAnlnator(thls,R.an'tn.nover_

Neste exemplo, estamos movendo a view para baixo, alterando a propriedade jz


Captu|o9 :Animaes 307
/res/anim/mover_baxo.x'm|
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android
andr0id:propertyName=y"
android:va1ueFrom="50" android:va1ueTo="200"
android:duration="1000" android:vaiueType="oatType" />

NQR: execute o projeto. PropertyAnimat_ion disponvel nos exemplos deste captulo


para conferir o resultado das animaes.

9.17 0biectAnimartor - animao de rotao


O cdigo a seguir mostra como girar a view em um ngulo de 36O, algo que no
framework Wew Animation ser~ia feito com a classe RotateAnimation.

Imagevieu img = (lmageview), ndViewById(R.id.img);


// Pelil API
ObjectAni_mator a =- Objectmimator.QfF1oat(img, "rotation", 0, 360);
/'/' Por XML
Obje-tAninat_ot a = (0bj_ectA_nimat_or) Animatorlnflater._ioadAnimator(this, R.anim.rotate_360);

No caso do arquivo XML, ele pode s_er criado desta forma:

/res/anim/rotate_360.xmi
<objectAnimator xmlns :-android= "httpz / / schemas ,android . com/ pk/ res / android"
android:propertyNamQ="FOQOD"
android:-vaiueFrom="Q" andr0id:_\a1_ueTo="360"
android:dura_tion="1000" android:_va1ueType="oatType" />

Nota: no framework View Animation, vimos que o cdigo necessrio para animar
uma view muitas vezes era extenso e justamente por isso era recomendado
criar a animao em XML para facilitar a leitura do cdigo. Com o framework
Property Animation o cdigo se tornou extremamente amigvel, e podemos criar
animaes com apenas. uma linha de cdigo., Portanto, ca a seu critrio utilizar
API ou XML.
308 Google Android - 4 um
9.18 Objectllnimator - animao de estala
Ate o momento. tralialliamos corn a classe Objectlminator para alterar uma nica
propriedade de um olijcto para criar a a niniaczio No entanto, as vezes, dependencia
do caso. precisamos alterar mais de uma propricdlslt
Neste pixiino exemplo precisamos alterar duas propriedades do objeto. scalex Q
scaleY Pois P\`cisamos criar o efeito de diminuir o Olllfm "l CIC d*`5ll@f0Cer. e
depois aumenta-lo novamente ate o tamanho normal. Para alterar mais de uma
pnopriedade. e necessario criar um PropertyValuesHolder com as informaes de que
precisamos Essa classe apenas tem o objetivo de armazenar a informaao Salim
uma propriedade para ser animada.
PropertyValuesHolder aninl = Propertyvaluesiiolder.ofFloat("scalex", 1, G);
PropertyvaluesHolder anin2 = PropertyValuesHolder.ofFloat("scaleY, 1, B);

Depois de criar essas duas configuraes, podemos agrupa-las c criar um


0bjectAninator utilizando o metodo ofPropertyValuesHolder(objeto, valores. . .). no qual
podemos informar varias instncias de PropertyValuesHolder.
0bjectAninator a = 0bjectAninator.ofPropertyValuesHolder(ing, antnl, ani.n2);

Feito isso, o objeto 0bjectAninator vai executar as duas animaes simultneas para
criar o efeito de escala tanto no eixo x quanto y do objeto.

9.19 AnimatorSet - criando um conjunto de animaes


A classe AnnatorSet pode ser til para criar um conjunto de animaes que podem
ser executadas em sequncia ou ao mesmo tempo. A seguir, podemos visualizar
um trecho de cdigo que mostra como utilizar a classe AninatorSet:
Inagevlew img = (lnageview) ndViewById(R.id.ing);
I/ Cria as animaes
0bjectAnlnator alphalinin = 0bjeetAnlnator.ofFloat(ing, 1ph', lf, af).
0bjectAninator translateAnin = objetgnator`f1t(n9. y-, y' g_9etHeght()p
/I Insere na lista
AnlnatorSet lista = new AnlnatorSet();
lista.playTogether(translateAnin, alphaAnln);
I/ Dispara a animao
lista.setDuratlon(200G);
llsta.start();

A tnat rSet ll t A ' _


Caso voce prefira utilizar o XM L. basta inar a lista de aniinaes desta tornia:
Inageview lag = (lnageview) ndvt@w3yd(R_d_ng)
n 0 s a = ( ntnatorSet) Aninatorlnater.loadAninator(this,R.antn.antnator,Sfl~
Captulo 9 n Animaes 309
/res/anim/animator_set.xmI
<?ml version="1.G" encoding="utf-8"?>

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueTo="200" android:valueType="oatType"
android:propertyName="x" android:repeatCount="1" /
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueTo=400" android:valueType="oatType"
android:propertyName="y" android:repeatCount="1" />

Nota: recomendo executar o projeto de exemplo deste captulo para voc


visualizar as animaes. Os exemplos do projeto so coerentes com os ttulos
dostpkosdolhwo.

9.20 Animatorlistener
Com o framework Property Animation tambm podemos monitorar a execuo das
animaes, basta implementar a interface and roid . animation .Animator.AnimatorListener:
Animator anim = m;
anim.addListener(new Animator.AnimatorListener() {
@0verride
public void onAnimationStart(Animator animation) { }
@0verride
public void onAnimationEnd(Animator animation) { }
@0verride
public void onAnimationCancel(Animator animation) { }
@0verride
public void onAnimationRepeat(Animator animation) { }
});

Acredito que os mtodos dessa interface sejam autoexplicativos. Uma vantagem


dessa API que, se voc quiser, podemos usar a classe AnimatorListenerAdapter que
j implementa a interface AnimatorListener e deixa os mtodos vazios, de modo que
precisaremos apenas sobrescrever o mtodo desejado.
Animator anim = N;
anim.addListener(new AnimatorListenerAdapter() {
31 O Google Android-4*q1
@0verride
public void onAnimationEnd(Animator animation) {
// m da animao
}

}>;

Nota: a interface Animatoriistener do novo framework de animao do Android 3.x


e muita parecida com a interface AnimationListener que estudamos anteriormente
para o Android 2.x. Nessa nova interface, porm, os metodos recebem como
parmetro um objeto do tipo Animator e no um Animation.

9.21 ViewPropertyAnimator - animao do jeito fcil


Para o final do captulo deixei a cereja do bolo, pois a classe VieuPtooertyAninator
permite criar animaes com uma linguagem simples e alterando vrias proprie
dades ao mesmo tempo.
Se quisermos mover as propriedades x e y de uma view ao mesmo tempo, pode
ramos utilizar um cdigo assim:
0bjectAnimator animX = 0bjectAnimator.ofF1oat(myView, ", 56f);
0bjectAnimator animY = 0bjectAnimator.ofF1oat(myView, "y", 1G6f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.piayTogether(animX, animY);
animSetXY.start();

Com a nova sintaxe, basta uma linha de cdigo e a animao est feita:
myView.animate() .x(S9f) .y(166f) .a1pha(0);

O mtodo animate() da classe View retorna um objeto do tipo Viewropertyhninator


que contem vrios mtodos de convenincia para con figurar as propriedades dd
animao. Esse tipo de sintaxe de programao chamada de interface fluente
(fluent interface). pois em uma nica linha de cdigo e com uma linguagfm
natural possivel configurar varias propriedades do objeto de forma aninhada.

ma* 3 Cl55 V"P"P@f2y^imator somente est disponvel no Android 3.1 (AW


Level L), mas caso voc precise utilizar o framework Property Animation
em versoes anteriores do And 'd . procure pela biblioteca NineOldAndroid5
YUI
(hrtp://riinmldundroids.rm/).
Captulo 9 I Animaes 311
9.22 Classe ValueAnimator - outro exemplo
Como j expliquei anteriormente, a classe ValueAnimator a base do novo framework,
mas com ela temos o trabalho manual de obter os dados e atualizar as propriedades
na view A classe 0bjectAninator foi criada para facilitar esse trabalho. Se precisar,
releia as explicaes anteriores sobre essas classes.
s vezes, no entanto, o que voc quer justamente obter todos os valores num
ricos durantel um intervalo de tempo. Para exemplicar, o Google Fit utiliza o
pedmetro (sensor de passos) e mostra uma animao assim que a tela aberta.
Nessa animao a quantidade de passos atualizada de forma sequencial e ani
mada. Ento se voc deu 1.000 passos e fechou o aplicativo, e depois deu mais 500
passos e abriu o aplicativo, o Google Fit vai mostrar uma animao para atualizar
o texto do Textview de 1.000 at 1.500.

Como podemos fazer esse tipo de animao? A classe ValueAnimator pode ajudar,
basta denir o intervalo numrico que voc deseja e que o framework envie as
atualizaes e o tempo da animao. O seguinte trecho de cdigo mostra como atu
alizar o texto de um Textview do valor 0 para 100 de forma incremental e animada,
durante o intervalo de um segundo. Voc poder ver os nmeros incrementando
at chegar no valor nal.
nal TetView textview = ?
// Animaco genrica de 1 at 100
ValueAnimator a = ValueAnimator.ofFloat(1, 100);
a.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAninationUpdate(ValueAnimator animation) {
// Recebe o valor e atualiza o texto.
Float valor = (Float) animation.getAninatedValue();
tetView.setText(String.value0f(valor.intValue()));
}
});
a.setDuration(1000);
a.setTarget(tetView);
a.start();

9.23 Aplicando animaes no layout


Outro recurso interessante aplicar uma animao que foi definida na pasta
/res/anim no layout da tela. A animao precisa ser do tipo LayoutAnimationController
e pode ser definida em XML na pasta /f6S/d11im
312 Google Android - 4 edio
.. ~~ --~.~' ` lo
CSSIVQYH
a se uir
A classe LayoutAnmatonController serve para animar um gerenciador de layout V1ewGr0u
durante a sua criaao, de forma que a animaao seja aplicada suc 1 enr gm
todas as suas views filhas, durante a criaao do layout. O exemp 8 Tl0Stra
como animar o layout da tela. Note que 0 arquivo comea com a tag <1BY0U'C^ination>
e utiliza uma animao j existente para ser aplicada. Escolhemos a animao
/res/anim/fade_in.xml para que cada view aparea na tela aos poucos, Uma apos a outra,

/res/anim/animatao_Iayout_fade_n.xml
<?m1 verson="1.0" encoding="utf-8"?>
<layoutAnnaton xnlns:androd="http://schenas.androd.com/apk/res/androtd
android:annaton="@anm/fade_n"
android:duraton="50" />

Depois de criar a animao de layout, basta utiliz-la em qualquer layout criado


na pasta /res/layout, conforme demonstrado a seguir:
<LnearLayout . . . android:1ayoutAnmaton="@anm/annacao_1ayout_fade_in" >

Outro recurso interessante de animao suportado pelo Android so as animaes


que executam quando o layout de algum gerenciador de container alterado,
como, por exemplo, uma view ser adicionada ou removida dinamicamente.
Por padro, o Android no faz esse tipo de animao, mas para habilit-la basta confi
gurar o atributo androd : annateLayoutChanges para true, conforme demonstrado a seguir:
<LnearLayout androd:anmateLayoutChanges="true" />

Pronto, agora como um passe de mgica sempre que voc adicionar ou remover
uma view desse layout o Android vai animar essa transio.

Nota: para conferir os exemplos de animao de layout, execute 0 projeto


LayoutAnnatons disponvel nos exemplos deste captulo no Android Studio.

9.24 Aplicando animaes nos fragments


DeP0'5 de estudar 35 animaes, ea fcil aplic-las em qualquer lugar do sistem
Como fragments sao muito utilizados para adicionar, substituir e remover compo
nentes do laY0Ut POCCITIOS aplicar uma animao ao executar a FragmentTransact~
Codlgo-fonte a seguir mostra como substituir um fragment no layout de form
animada, utilizando as animaes de f ade_n e fade_out que controlam a tran5P*"
rncia das views.
Captulo 9 I Animaes 313
android.support.v4.app.FragnentManager fm = getSupportFragnentManager();
FragmentTransaction ft = fn.beginTransaction();
ft.setCustonAninations(android.R.anin.fade_in,android.R.anin.fade_out);
Fragmentl fragl = new Fragment1();
ft.repiace(R.id.1ayoutFrag, frag1,"Fragment1");
ft.commit();

O mtodo setCustomAnimations(int animEnter,int animEit) utilizado para especicar


a animao de entrada do novo fragment, e a animao de sada do fragment
atual, em caso de substituio. Neste exemplo utilizei a classe android.R nativa, mas
se voc quiser possvel criar suas prprias animaes.
Para testar esse cdigo, abra o projeto Fragments-ActionBarTabs no Android Studio.
Esse o mesmo exemplo que zemos com fragments + tabs no captulo 8, sobre
fragments. Porm, ao clicar em uma tab, estou substituindo o fragment utilizando
uma animao, conra!

9.25 Aplicando animaes ao navegar entre activities


A partir do Android 4.1 Gelly Bean), podemos customizar a animao de navegao
entre as activities. Para isso foi criada a classe Activityptions com trs mtodos:

makeCustomAnimation(Context context, int enterResId, int exitResId)

Congura uma animao customizada para a activity que est entrando


e saindo.

makeScaieUpAnimation(View source, int startX, int startY, int width, int height)
Congura uma animao customizada de escala para a activity que vai
ser chamada. As coordenadas startX e startY so as posies para iniciar a
animao, referentes view Os parmetros width e heigth denem o tama
nho inicial da nova activity

makeThumbnaiiSca1eUpAnimation(View source, Bitnap thumbnail, int startX, int startY)

Congura uma animao customizada de escala para a activity mas o ob


jeto que d origem animao uma imagem de Bitnap, e as coordenadas
startX e startY so as posies para iniciar a animao, referentes ao bitmap.
Para brincarmos com as animaes de transio entre telas, crie um novo projeto
chamado HeIIoActivityTransition. No layout da activity; vamos adicionar a imagem do
planeta Terra posicionada no centro. Deixei o tamanho da gura com 1@0dp.
314 Google Android - 4 edio
:Zn /res/layout/activity_main.xmI
<FrameLayout xmlns:android="http://schemas.android.com/apk/FGS/3"dfd"
android:layout_width="match_parent" android:layout_height="tCh_DF">
<InageView android:id="@+d/WQ" "dfd=1Y0U_9fVtY="C@tf"
android:src="@drawable/planeta_03_terra"
android:layout_width="100dp" android:layout_height="10Gdp"
android:onClick="onClickPlaneta" />

A ideia que, ao clicar na gura do planeta Terra, a activity PlanetaActivity seja


chamada com uma animao de transio. A segunda activity contm 0 mesmo
layout, porm a foto do planeta est maior. Para fazer a transio, em vez de cha
mar o mtodo startActivity(intent) como de costume, podemos utilizar a classe
ActivityOptionsConpat ea 1I(()NkCUSt0At0(COHX,D8C3OEtF8dId,BDNBCB
oSaidaId) conforme demonstrado a seguir.

) MainActivity.java
public class MainActivity extends AppConpatActivity {
@0verride
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

public void onClickPlaneta(View view) {


Intent intent = new Intent(getBaseContet(), PlanetaActivity.class);
Activity0ptionsConpat opts =
Activity0ptionsConpat.nakeCustonAnination(this, R.anin.fade_in, R.anin.fade_outM
ActivityConpat.startActivity(this, intent, opts.toBundle());
l
}

No cdigo foi denida a anima fade_in (aparecer) para a activity que vai abrir
e fade_out (desaparecer) para a activity que vai fechar, portanto crie os seguintes
arquivos de animao na pasta /res/anim.

i /res/anim/fade_in.xmI
<?m1 verSi0n="1.0" encoding="utf-8"?
<alpha xmlns:android="http://schenas.android.com/apk/res/androdn
android:fronAlpha="0.0" android:toAlpha="1_@" ndr0dduratn:190e />
Captulo 9 I Animaes 315
/res/anim/fade_out.xmI
<?xml version="1.0" encoding="utf-8"?>
<alpha mlns:android="http://schemas.android.con/apk/res/android"
android:fronAlpha="1.0" android:toAlpha="0.0" android:duration="1000" />

Na segunda activity vamos mostrar a mesma gura do planeta, sendo assim, voc
pode at copiar o layout anterior. A diferena que na primeira activity deixei a
guzra pequena com 100dp e na segunda deixei a figura grande ocupando o tamanho
que ela tem com a notao wrap_content. Na segunda activity o detalhe importante
que sobrescrevemos o mtodo finish(), pois preciso customizar a animao de
sada chamando o mtodo overridePendingTransition(animEntrada, animSaida).

PIanetaActivity.java
public class PlanetaActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_planeta);
getSupportActionBar().setDisplayHoneAsUpEnabled(true);
}

@0verride
public void nish() {
super.nish();
// Customiza a animao ao fechar a activity
overridePendingTransition(R.anim.fade_in, R.anin.fade_out);
}

A gura 9.7 mostra o resultado ao executar esse exemplo. Ao clicar na foto do


planeta Terra, a gura vai sumir e aparecer devido s animaes de transparncia:
fade_in e fade_out. Esse efeito muito interessante e amigvel aos olhos do usurio.
Se voc quiser, possvel criar outros tipos de animaes. E bem comum encontrar
aplicativos que utilizam o efeito que desliza a tela da esquerda para a direita. Isso
pode ser feito com os seguintes arquivos de animao.

/res/anim/sIide_in_Ie1't.xmI
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="50@" android:fromXDelta="1@0%p" android:toXDelta="0" />
316 9
0 't O . O oca: 9 4 ' 0 On'
` " ' aaa in t nouonfi* N A N N ,____
HIoAcuvityTnnaition
Google Android - 4 @d

Figura 9.7 - Animao de transio com transparncia.

/res/anim/slide_out_Ieft.mI
<trans1ate n1ns:android="http://schenas.android.com/apk/res/android"
android:duration="500" android:fromXDe1ta="0" android:toXDe1ta="-5G%p" />

No cdigo da MainActivity, basta utilizar esses arquivos de animao para fazer a


transio de telas com um efeito deslizante.
public void onCiickP1aneta(View view) {
Intent intent = new Intent(getBaseContet(), P1anetaActivity.c1ass);
ActivityOptionsCompat opts =
Activity0ptionsCompat.nakeCustomAnimation(this, R.anim.s1ide_in_1eft,
R.anim.s1ide_out_1eft);
ActivityCompat.startActivity(this, intent, opts.toBund1e());
i

S tenha ateno, pois se estamos fazendo a animao entrar com o efeito df


deslizar da direita para a esquerda, temos de fazer o contrrio ao pressionar O
boto voltar, ou seja, temos de sair da tela deslizando da esquerda para a direita.
portanto crie os seguintes arquivos de animaes:

ifo /res/anim/slide_in_right.xmI

<trans1ate xnins:android="http://schenas.android.com/apk/res/android"
android:duration="S90" android:fr
WD@lta="-50%p" android:toXDelta="0" /
Captulo 9 I Animaes 317

. I '
/res/anim/sIide_out_rght.xm|
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="S00" android:fromXDelta="0" android:toXDelta="100%p" />

Feito isso, utilize estas animaes na classe PlanetaActivity:


@0verride
public void nish() {
super.nish();
// Para voltar utiliza a animao da esquerda para a direita
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_right);
}

A gura 9.8 mostra o resultado da animao. Desta vez, ao clicar na imagem do


planeta Terra, a segunda activity entrou na tela da direita para a esquerda. Ao
clicar no boto voltar, a animao o inverso.

r'~.`,.J

Figura 9.8 -Animao de transio com deslize.

Caso queira conferir outras animaes, criadas com os mtodos


makeScaleUpAnimation(...) e makeThumbnailScaleUpAnir|ation(...) abra o projeto
ActivityAnimation-GoogIeDemo disponvel nos exemplos do livro.

Nota: a classe Activityptions foi criada no Android 4.1, mas para facilitar nossa vida
o Google disponibilizou as classes android.support.v4.app.ActivityCompat e android.support.
v4.app.Activity0ptionsCompat para termos a compatibilidade com verses antigas. Veja
que estamos utilizando as classes de compatibilidade no cdigo. Caso a animao
no possa ser feita nas verses antigas do Android, a activity vai abrir normalmente.
318 Google Android -4Q|||
f - > ` ' 'V ~ ` ` .` fr; I
9.26 Nine0IdAndroids - animaes com compotlbllldidf
l,a vai a dica hnal sobre anunaoes! Neste captulo. estudamos o "l11CW()I'l(
Pf0P0fYAnlmatlons que funciona somente no /\ndroid 3.0 (l'l0f`|CYUml7) U SUPCWUY
e facilita bastante a criao de animaes. li o melhor exemPl0 de md fm 0 que
mostramos no topico VIewPtopertyAnImator, pois com urna umca linha de codigo
possvel animar diversas propriedades de uma view.

- - * ` ~" 1 -' f
myView.anmate().(50f).y(100f).a1pha(0);

Mas como usamos essa sintaxe snnplihcada em vc rsocs amigas do Android.


A resposta e a bilvlioteca Nlne0IdAndrolds (hup://nineldandrids.com/`). Para utiliz-la,
adicione esta dependncia no arquivo app/huildgradlc.

ii /app/buiId.gradIe
dependencies {

Compile 'com.ntneo1dandrods:library:2.4.0'
}

Feito isso, podemos usar as classes de compatibilidade que tm os mesmos no


mes e mtodos das classes nativas, como por exemplo: com.ntneo1dandrotds.veu.
V'tewPropertyAnmator.

Mas o que eu realmente gosto de fazer usar a sintaxe simplificada da


VlewPropertyAnimator. Felizmente, isso muito simples; basta declarar um import
esttico no cdigo da classe da seguinte forma:
import static com.nneoldandroids.view.viewPropertyAnmator.antmate;

O segredo e que esse import esttico importou a funo antmate(vew), e com


ela podemos animar qualquer view utilizando a sintaxe resumida. O seguinte
exemplo mostra como mover uma imagem n eixo x e ) ao mesmo tempo em
que rotacionada ein I8O; no final, ficar com 50% de transparncia, tudo em
uma nica linha de cdigo.

anmate(mg) .By(200) . yBy(200) . rotat1.on(180) .a1pha(0.SF) .setDuration(2000);

A figura 9.9 mostra o resultad do projeto de exemplo NIne0ldAndr0lds disponvel nos


exemplos do livro, qual executa exatamente esse cdigo mostrado anteriormente.
Captulo 9 n Animaes 319

'A
ANIMAR X, Y E ALPHA ANIMR X, Y E ALPHA

QIIII. _ . ._.
i:ri_;____;}..
,- ai

Figura 9.9 - Animao.

9.27 Links teis


Neste captulo, estudamos como criar animaes para turbinar seu aplicativo e
melhorar a experincia do usurio,
Como o assunto de extrema importncia para criar aplicativos fantsticos que
encantem os olhos do Llsuri, separei vrios links da documentao ocial para
complementar seus estudos,
View Animation

http://developer android, com/guide/topics/graphic5/view-animation. html

Property Anlmatlon

http://dei/elopenmdroid,com/guide/topics/graphics/propanimation. html

Animating Layout Chnges

http://developer android.com/tmining/animation/layout. html


Drawable Animation

http;//dgvglopgzgndrgid,mm/gaide/topics/graphics/drawable-animation. html

Android Training - Animations

https://developer ndroid. com/tming/ar2imati0n/indx. html


Google Android - 4 edio

Android Developers Blog - lntroducing ViewPropertyAnimator

maior html
http://android-developers.blogspot.com.br/201 1/05/introducing-viewpropertyang

Nine0IdAndroids - Biblioteca de compatibilidade para animaes

http://nineoldandroids.com/
Vdeo no YouTube - Android DevBytes: Window Animations

https://www youtube. com/watch ?v=H 081/l' 61 l VI U

Vdeo no YouTube - Android DevBytes: Activity Animations

https://wwuzyoutube. com/watch P1/= CPxkoe2MraA


Vdeo no YouTube - Google Developers: Activity Transitions

https://www. youtube. com/watch?v=RhiP] By] M rM


r cAPTuLo 10
Threads, Handler e
*TW AsyncTask

Neste captulo, vamos estudar o conceito de threads e a classe Handler, a qual


utilizada para enviar ou agendar mensagens para serem executadas na thread
principal da aplicao, conhecida como Main Thread ou UI Thread.
A classe Handler tem um papel importante na arquitetura do Android, porque
somente por meio dela possvel atualizar a interface grfica a partir de uma
thread diferente da thread principal.

10.1 Introduo
Quando um aplicativo aberto no Android, um processo dedicado no sistema ope
racional criado para execut~lo. Cada processo tem uma nica thread, conhecida
como Main Thread ou UI Thread, responsvel por gerenciar todos os eventos da
tela, assim como atualizar a interface grca. O fato que muitas vezes a activity
pode realizar uma tarefa um pouco demorada, e para no travar a interface de
usurio recomendado que esse tipo de cdigo seja executado em outra thread.
Podemos dizer que, sempre que uma consulta realizada em um web service,
banco de dados, agenda de contatos ou leitura de um arquivo, obrigatrio criar
uma thread para desvincular esse processamento da thread principal. Antigamente
isso era apenas uma recomendao, mas nas verses mais novas do Android, se
o cdigo zer uma operao de I/O na thread principal, o sistema vai lanar a
exceo Network0nMainThreadEcepton.

Portanto, como regra, toda operao de I/O, seja consultar um web service, ler
um arquivo ou acessar do banco de dados, deve executar em uma thread separada.

321
322 Google I1d|`0(| - 4' QO
Outro motivo importante para utilizar threads porque a thread principal da
aplicao deve responder aos eventos do usurio, em no mximo em cinco segun
dos. Se esse tempo for ultrapassado, o erro AINR (Application Not Responding)
ser lanado. Esse erro a clssica mensagem com um Forteose que aparece em
muitas aplicaes, porque, nesse caso, o Android entende que a aplicao no est
respondendo e exibe esse alerta para o usurio fecha-la ou aguardar. Para evitar
esse tipo de erro, necessrio utilizar threads.
Uma vez que j justicamos a necessidade de utilizar threads, vamos ver um trecho
de cdigo em Java que executa um cdigo em uma nova thread.
new Thread() {
public void run() {
// Cdigo que deve executar en segundo plano aqui
};
}.start();
Uma thread deve ser lha da classe Thread e deve implementar 0 mtodo run(). Ao
chamar o mtodo start(), a thread iniciada, ou seja, 0 mtodo run() vai executar
em segundo plano. Para mais detalhes sobre threads no java, recomendo uma
leitura adicional em livros sobre essa linguagem.
No caso do Android, sempre que uma thread iniciada, temos um problema,
pois por questes de segurana e concorrncia o Android no permite que uma
thread diferente da principal atualize a interface grca da tela. Por isso, a classe
android.os.Handler foi criada com o objetivo de enviar uma mensagem para a thread
principal, para que, em algum momento apropriado, essa mensagem possa ser
processada de forma segura e consequentemente atualizar a interface grca da
tela (view). Um exemplo clssico de utilizao de threads e atualizao de interface
grca com um Handler pode ser visto a seguir:
nal Handler handler = new Handler;
new Thread() {
public void run() {
// Cdigo que deve executar en segundo plano aqui
handler.post(new Runnable() {
public void run() {
// Cdigo que atualiza a interface aqui
}

});
};
}.start();
Captulo 10 1 Threads, Handler e AsyncTask 323
Ou podemos utilizar o mtodo run0nUIThread(runnable), que um atalho para utilizar
um handler que est dentro da activity
new Thread() {
public void run() {
// Cdigo que deve executar em segundo plano aqui
run0nUiThread(new Runnab1e() {
public void run() {
// Cdigo que atualiza a interface/view aqui
}
});
};
}.start();

Essa a utilizao clssica de um handler, que tem como objetivo sincronizar o


cdigo de uma thread para atualizar a interface. No entanto, o handler tambm
muito utilizado para agendar tarefas e enviar mensagens dentro da activity:
Concluindo, podemos dizer que existem dois bons motivos para usar a classe
android.os.Hand1er:

1. Atualizar a interface (view) sempre que uma thread for utilizada para fazer
algum processamento em segundo plano.
2. Agendar uma mensagem android.os.Message ou um java.lang.Runnab1e para
executar em determinado momento. Essa mensagem pode ser enviada
instantaneamente ou com um intervalo de tempo (delay). Cada mensagem
enviada processada em uma la de mensagens nica para cada handler,
que est vinculada thread principal da aplicao.

Resumo: no Android, cada aplicao executada em um nico processo, e


cada processo por sua vez tem uma thread dedicada. Essa thread tambm
responsvel por desenhar e tratar todos os eventos da interface grca, e
conhecida como Main Thread ou UI Thread. Existe uma regra no Android que
diz que somente a Ul Thread pode atualizar a interface, ou seja, somente ela
pode chamar qualquer mtodo que vai atualizar uma view. A classe Handler
utilizada para enviar uma mensagem para ser processada pela Ul Thread, que
geralmente um cdigo que vai atualizar a view.
324 Google Android - 4' edio
10.2 Mtodo sendMessage(msg)
Para enviar uma mensagem com a classe Handler, pdCmS Utllllf 0 mtodo
sendHessage(msg) e suas variantes, conforme demonstrado a seguir:
Mtodo Descrio
sendMessage(msg) Envia a mensagem informada para a la de mensagens para
ser prcessada assim que possvel.
sendEmptyMessage(i.nt) Envia a mensagem contendo apenas o atributo what informa
d como parmetro. a mesma coisa que criar um objeto
androld.os.Hessage e congurar apenas o\atributo what.
sendMessageDelayed(msg, long)
lnvia a mensagem para a la de mensagens, mas ela pr
cessada somente depois de determinado tempo informado.
O segundo argumento do tip long, que representa o tempo
em milissegundos que a mensagem deve aguardar antes de
ser enviada.
sendMessageAtTlme(msg, long)
linvia a mensagem para a la de mensagens, mas ela pro
cessada somente na data informada. O segundo argumento
do tipo long, que representa uma data em milissegundos
para executar a mensagem.
Para brincar com a classe Handler, vamos criar um exemplo para enviar uma men
sagem com o mtodo sendMessageDelayed(msg, delay), o qual vai enviar a mensagem
com atraso (delay) de trs segundos. Para continuar, crie o projeto HelloHandler, ou
se preferir abra o projet de exemplo que acompanha o livro.
A seguir, podems visualizar o cdigo-fonte da activity e seu layout.

fi /res/layout/activity_demo_handIer_message.xmI
<?xml verslon="1.0 encodlng="utf-8"?
<LlnearLayout mlns:androd="http://schemas.androd.com/apk/res/androld"
androld:layout_wldth="match_parent" androld:layout_helght="match_parent"
androld:orlentaton="vertcal" androd:paddlng="20dp"
<TetVew

androd:layout_width=match_parent" androld:layout_helght="wrap_content"
androd:tet="Dlsparar uma mensagem com atraso de 3 segundos" /
<Button
androld:ld="@+ld/btEnvlar"
BHFO2lY0Ut_width="wrap_content" androld:layout_helght=wrap_content"
androld:text="Envlar mensagem" /
</LlnearLayout
Captulo 10 I Threads, Handler e AsyncTask 325
DemoHandlerMessageActivity.java

public class DemoHandlerMessageActivity extends AppCompatActivity {


protected static nal int MENSAGEM_TESTE = 1;
private Handler handler = new TesteHandler();
@0verride
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_demo_handler_message);
ndViewById(R.id.btEnviar).set0nClickListener(new Button.0nClickListener() {
@0verride
public void onClick(View v) {
// Cria a mensagem com delay de trs segundos
Message msg = new Message();
msg.what = MENSAGEM_TESTE;
// Envia a mensagem
handler.sendMessageDelayed(msg, 3006);
}

});
}

// Handler utilizado para receber a mensagem (classe interna)


private class TesteHandler extends Handler {
@Override
public void handleMessage(Message msg) {
// O atributo msg.what permite identicar a mensagem
switch (msg.what) {
case MENSAGEM_TESTE:

Toast.makeTet(getBaseContet(), "A mensagem chegou!",Toast.LENGTH_SHORT).show();


break;
}

Note que, para utilizar o mtodo sendMessage(msg) ou uma de suas variaes, pre
ciso criar uma subclasse da classe android.os.Handler; justamente por isso, criamos
a classe TesteHandler. Feito isso, para enviar uma mensagem ao handler, foi criado
um objeto do tipo android.os.Message e no atributo what foi informado um valor, que
contm uma constante para identicar a mensagem.
Message msg = new Message();
msg.what = MENSAGEM_TESTE;
handler.sendMessageDelayed(msg, 3000);
326 Google Android - 4 edio
O mtodo sendMessageDe1ayed(msg,de1ayHi11is) recebe a mensagem e o tempo em
milissegundos (delay) para atras-la. Nesse exemplo, depois de trs segundos, 0
mtodo hand1eMessage(message) da classe interna TesteHandler foi chamado. Nesse mo
mento, o valor informado no atributo what utilizado para identicar a mensagem
(isso til caso exista mais de uma), conforme demonstrado a seguir:
public void handleHessage(Message msg) {
// 0 atributo msg.what permite identicar a mensagem
switch (msg.what) {
case MENSAGEM_TESTE: \
Toast.makeTet(Exemp1oHandler.this, "A mensagem chegoul", Toast.LENGTH_SHORT).show();
break;
}

A gura 10.1 mostra o resultado desse cdigo executando no emulador. Ao clicar


no boto Enviar Mensagem, a mensagem disparada, e depois de trs segundos o
alerta exibido.
| 7:51

CJ. l-ltmtlier l~.T*L.s<1

|'"l`iLlf) '
DlSp3I' Uma mf`lSBgl' (Om atraso E 3 V

Em/lar mensagem l
1

Amensagem chegou!

Figura 10.1 - Exemplo inicial da classe Handlei:

Esse exemplo extremamente simples, e no momento voc pode no entender


quais os reais benefcios de utilizar esse tipo de mensagem. Observe que nesse
simples exemplo j podemos vericar que possvel agendar mensagens para
execuo posterior. Isso por si s j parece bastante til. O fato e que nosso exem
plo muito simples para demonstrar o que a classe android.os.Handier pode fazer.
Lembre-se de que as mensagens enviadas para um Handler so processadas pela
UI Fhread, e esse e o verdadeiro sentido de utilizar um handler. No momento,
Captulo 10 I Threads, Handler e AsyncTask 327
vamos continuar com esses exemplos simples para voc entender a sintaxe e como
utilizar um Handler e mais para frente vamos analisar casos em que utilizar um
Handler obrigatrio.

10.3 Mtodo post(runnabIe)


Outra forma de enviar uma mensagem com o mtodo postHessage(runnable), que
funciona de forma similar ao mtodo sendMessage(msg), mas recebe uma implemen
tao da interface java.lang.Runnable. A interface Runnable bem conhecida pelos
programadores Java e utilizada para auxiliar na programao multithreading.
No caso do Android e a classe Handler, a interface Runnable tambm pode ser utilizada
para enviar uma mensagem para a thread principal ou executar determinada tarefa
com um tempo de atraso. A vantagem de utilizar um java.lang.Runnable em vez de
enviar uma mensagem com a classe android.os .Message que no necessrio criar
uma subclasse de androtd.os.Handler e implementar o mtodo handleMessage(nsg).
Utilizando um java.lang.Runnable, naturalmente o mtodo run() implementado por
ela chamado na thread principal.
Para executar ou agendar um java.lang.Runnable, so usados os mesmos mtodos
que para enviar uma mensagem, com os mesmos argumentos, mas agora os no
mes dos mtodos comeam com a palavra post(. . .). A seguir, veja a lista com a
descrio de cada mtodo:
Mtodo Descrio
post(Runnable) Adiciona o Runnable na la de mensagens.
postDelayed(Runnable, long) Adiciona o Runnable na la de mensagens, mas somente
executa o processo depoisdo tempo especicado em
milissegundos.
postAtTine(Runnable, long) Adiciona 0 Runnable na fila de mensagens, mas somente
executa o processo na data especi cada em milissegundos.

Para praticar como utilizar o mtodo post( . . .) e suas variaes, vamos criar um
exemplo para enviar uma mensagem com atraso (delay).

DemoHandlerMessageActivty.java

public class DenoHandlerRunnableActvty extends AppConpatActvity {


private Handler handler = new Handler();
@0verrde
public void onCreate(Bundle icicle) {
super.onCreate(iccle);
328 Google Android - 4 edio
setContentView(R.layout.activity_demo_handler_message);
ndViewById(R.id.btEnviar).set0nClickListener(new Button.0nClickLtstener() {
@0verride
public void onClick(View v) {
// Cria a mensagem com delay de trs segundos
handler.postDelayed(new Runnable() {
@0verride
public void run() {
Toast.makeText(getBaseContet(), "A mensagem Ch90U CON RUHHBUE",
Toast.LENGTH_SHORT).show();
}

}, 3000);
}

});
}

Esse cdigo tem o mesmo objetivo do exemplo anterior, mas note que a sin
taxe utilizando um Runnable mais simples do que enviar uma mensagem pelo
sendMessage(msg). Ao executar 0 cdigo, 0 resultado ser o mesmo da gura 10.1.
Vale lembrar que a interface Runnable uma gurinha bem conhecida no mundo
java e podemos dizer que ela representa algum cdigo que deve ser executado.
Se necessrio, procure mais detalhes sobre essa interface.

10.4 Atualizando a view dentro de uma thread


Depois dessa introduo sobre como utilizar a classe Handler, vamos entender
quando ela realmente necessria, que quando as threads entram na brincadeira.
No captulo 7 sobre a classe View, no exemplo sobre Progressialog, mostramos como
fazer 0 download de uma imagem e mostrar uma mensagem de por favor, aguarde
para o usurio. Se voc voltar l e ver o cdigo desse exemplo, ver que ele utiliza
threads e o mtodo run0nUiThread(runnble) foi utilizado para enviar a mensagem
UI Thread. Antes de tudo, vale explicar que 0 mtodo run0nUiThread(runnble) um
atalho ao mtodo post(runnable) da classe Handler. Agora vamos estudar em mais
detalhes porque isso foi necessrio.

Vamos utilizar este cdigo que vai funcionar como exemplo porque apresenta
um bug.
Captulo 10 I Threads, Handler e AsyncTask 329
/res/layout/activity_downIoad_imagem.xm|
<?ml version="1.G" encoding="utf-8"?>
<FrameLayout xmlnszandroid="http://schenas.android.con/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent" >
<InageView android:id="@+id/img" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" android:scaleType="tCenter" /
<ProgressBar android:id="@+id/progress"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center"/

No layout XML existe um Imageview e por cima foi inserido um ProgressBar para
mostrar a animao durante o download da imagem. O cdigo da activity sim
plesmente faz o download de uma imagem e atualiza o contedo no Imageview.

DownloadlmagemActivty.java
public class DownloadImagemActivity extends AppCompatActivity {
private static nal String URL = "http://livroandroid.com.br/imagens/livro01.png";
private ProgressBar progress;
@0verride
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_download_imagem);
progress = (ProgressBar) ndViewById(R.id.progress);
progress.setVisibility(View.VISIBLE);
downloadImagem(URL);
}

// Faz o download da imagem em uma nova thread


private void downloadImagem(nal String urlImg) {
new Thread() {
@Override
public void run() {
try {
// Faz o download da imagem
nal Bitmap imagem = Download.downloadBitnap(urlImg);
// Atualiza a tela
atualizaImagen(inagem);
} catch (IOException e) {
// Uma aplicao real deveria tratar este erro
Log.e("Erro ao fazer o download: ", e.getMessage(), e);
}
33 Google Android - 4 edio
}
}.start();
}

// Vai dar Erro neste mtodo pois somente a UI Thread pode atualizar a view
private void atualizaImagem(nal Bitmap imagem) {
// Esconde o progress
progress.setVisibility(View.INVISIBLE);
// Atualiza a imagem
Imageview imgview = (ImageView) ndViewById(R.id.img);
imgview.setImageBitmap(imagem);
}

O download feito na classe Download, conforme demonstrado a seguir:

DownIoad.java
public class Download {
public static Bitmap downloadBitmap(String url) throws IOException {
// Faz o download da imagem
Bitmap bitmap = null;
InputStream in = new URL(url).openStream();
// Converte a InputStream do Java para Bitmap
bitmap = BitmapFactory.decodeStream(in);
in.close();
return bitmap;
}

Para o exemplo funcionar, declare a permisso INTERNET no arquivo AndroidManiest.xm!.

AndroidManifest.xmI
<manifest . . . />
uses-permission android:name="android.permission.INTERNET" /
<application ... /

Para fazer o download, estamos iniciando corretamente uma thread, pois isso
e obrigatorio. Contudo, no nal do download, ao tentar atualizar o Imageview, o
Android vai lanar uma exceo, conforme mostra a gura 10.2.
5mPf que Um UFO HCOIWCC, voc deve olhar os logs detalhados na janela LogCat,
Conforme 21 figura 103, que mostra a stack trace do erro. Podemos ver que o pr0
blema est na linha 46 da classe que criamos. Para mais detalhes do I.o9(at, reviS
Captulo 10 I Threads, Handler e AsyncTask 331
os captulos 2 e 3. Note que a mensagem de erro : Only the original thread
that created a view hierarchy can touch its views. Traduzindo a mensagem, isso
signica que somente a thread principal (UI Thread) pode atualizar as views!
Portanto, aqui que a classe Handler entra em ao.

Figura 10.2 - Erro ao executar o aplicativo.

ins uma
i ,_ '09-20 10:30:08.124 62-92/2 E/Iuputsparcher channel '40'7a4f8 br.livroand:oid.ca:ro:s/br.1iv2oan:iro1d.ca:zo:..
'09-20 18:30:08.124 G2-92/2 E/Inpucllispezcber channel 'l0'a4f8 br.livxoandzroidazros/br.livrc:and:oid.carros..
* O9-20 54.706 62-92/2 E/Inputzbispaccher channel '4080ledO br.livroandroid.livroandzuidcapi.l_hnndler/br.
z :09-20 54.706 62~92/? E/Input:Diapatcher channel 40801ed0 br.livroandtoid.1ivmandroid:apl1_handler/br.
":-1
._ OQ-20 07.115 62-92/?
09-20 07.115 62-92/? E/Inputbiapatcher
E/Inputbiapatcherchannel
channel. -061ebd0bnlivroandxoid.livrcandxeidcapl1__handle:/br.
406lu!.~d0 br.livmandzoid.livrcandroidcapllghandlerbr.
l' 509-20 48.405 62-92/7 E/Inputbispatcher channel 40762508 br.livraandroid.livtoendrcidcapl1__handler/br.
` 092O 48.405 62-92/? E/InputDispa\:che: channel '407{508 br.livrodndroid.l1vroand.roidcap1l_han:1lerfhr.
09-20 48.425 62-92/7 E/Inpucbispacchez: Received spurious receive callback ter unknown inpuc channel.

i.
l G 09-20 26.435
09-20 62-92/?
26.435 E/Inpucbispetcher
62-92/7 channel
E/Inpucbiapaccher '40769af0
channel bnlivxoandrnid.liv:oand.roldcap1l__hand1er-'br.
'|0'i69a0 bnlivroandroid.livroand.roidcap11_hundle:/br.
09-20 54.337 B82-890/? E/Androidkuntlnel FATAL EXCEYIION: Thread-10
android.v1ew.ViewRoat:$Celledfroimnqlhreedxcepxzianz Only the oriqinul thread that created A view hierucny can
ac andrid.view.VievRrot . chechread (viewkooc . j av: : 2932)
at nnd.roid.viev.Vie'uP.oox: . invalidecethild (Vie\P.cm: . java : 642)
ac andmid. v1e\:.V1evRom: . invalldatethildlnarent (viewkooz _ java : 665)
1 ac andreid.v:\ew.VievGroup. inva1ida\:eCh11d (yzgvrnw. i gva :
. at andreia . view . View . invalidez: (fg ei . >> avg ; 2 3)
^ ac and:oid.viea.Yie'r. aetflaga (View. vga- ; 556)
l na uiazmi-1.v1ew.v1ew. ze:v1z1b111:y3g;z,;,_az;5
* al: androidfidqec.P:oqressBar.aet:V1s1.bili\:yr.~,resg
3 lb b: . livmandroid. livroandro1dcap11_hundler . Downloadlmnqemhccivltyil . run (

__ _

Figura 10.3 - Detalhes do erro no LogCat.


Como uma thread foi utilizada para fazer o download, preciso utilizar um
Handler para enviar a mensagem para a thread principal (UI Thread), a m de
atualizar a view O cdigo-fonte a seguir est atualizado para utilizar o mto~
do run0nUThread(runnab1e), que nada mais do que um atalho para o mtodo
Hand1er.post(runnab1e) que estudamos anteriormente.
332 Google Android - 4 edio

r; DownloadlmagemActivity.java

public class DownloadImagemActivity extends AppCompatActivity {


private static nal String URL = "httpz//livroandroid.com.br/imgs/livro_android.png";
private ProgressBar progress;
@0verride
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_download_imagem);
progress = (ProgressBar) ndViewById(R.id.progress);
progress.setVisibility(View.VISIBLE);
downloadImagem(URL);
}

// Faz o download da imagem em uma nova thread


private void downloadImagem(nal String urlImg) {
new Thread() {
@Override
public void run() {
try {
// Faz o download da imagen
nal Bitmap bitmap = Download.downloadBitmap(URL);
// Atualiza a tela
atualizaInagem(inagen);
} catch (IOEception e) {
// Uma aplicao real deveria tratar este erro
Log.e("Erro ao fazer o download: ", e.getMessage(), e);
}

}.start();
}

private void atualizaImagem(nal Bitmap imagem) {


run0nUiThread(new Runnable() { // Atualiza a view na UI Thread
@0verride
public void run() {
// Esconde o progress
progress.setVisibility(View.INVISIBLE);
// Atualiza a imagem
Imageview ingview = (ImageView) ndViewById(R.id.img)
ingview.setImageBitmap(imagem);
}});
}

}
Captulo 10 I Threads, Handler e AsyncTask 333
Com essa alterao, o exemplo vai executar perfeitamente, pois o download
feito em uma thread separada, mas a view atualizada na thread principal com
a ajuda do nosso amigo Hand1er.A gura 10.4 mostra o resultado.
Q :I ' 3
Download llillflgfflll

I.

Google
.
1

HIIDROII) 1
Apnndaacarnpllcacsparadisposmvosmvels
oomoAndrodSDK `

novatec nrlw-on.|.cmu g 1

Figura 10.4 - Download da imagem realizado com sucesso.

Lembre-se de que estas duas tarefas so obrigatrias ( uma regra):


1. Toda operao de I/O, seja consultar um web service ou acessar o banco de
dados, deve executar em uma thread separada. Qualquer processamento demo
rado tambm deve executar em sua prpria thread para no travar a interface.
2. Somente a thread principal pode atualizar as views. Quando as threads
secundrias terminam o seu trabalho, necessrio utilizar um handler ou
o atalho runOnUThread(runnab1e) para atualizar asviews.

Importante: se a aplicao fechar por causa de um erro, olhe a exceo (stack


trace) nos logs do LogCat. Mostrei o erro de propsito aqui apenas para voc
se acostumar a olhar os logs de erro.

10.5 Agendando tarefas contnuas na activity


A classe Handler muito utilizada para executar tarefas de modo contnuo na
activity Por exemplo, se voc precisar executar um cdigo na activity a cada 30
segundos, isso pode ser feito com um handler. Isso muito comum para criar
telas que precisam car atualizando o seu contedo.
334 Google Android - 4' edio
Para demonstrar, vamos alterar o exemplo de download da imagem para atualizar
a imagem a cada dez segundos, ou seja, refazer o download continuamente. No
cdigo a seguir estou demonstrando apenas as partes importantes.

DownloadlmagemActivity.java
public class DownloadInagenActivity extends AppConpatActivity {

private Handler handler = new Handler();

// Faz o download da imagen em uma nova thread


private void downloadInagen(nal String urllmg) {
new Thread() {
@Override
public void run() {
try {
// Faz o download da imagen...
nal Bitnap bitmap = Download.downloadBitnap(URL);
// Atualiza a tela
atualizaInagen(inagen);
// Agenda o download novamente (daqui a dez segundos)
handler.postDelayed(new Runnable() {
public void run() {
downloadInagen();
}
},16606); // dez segundos
} catch (IOException e) {

}.start();
}

@0verride
protected void onDestroy() {
super.onDestroy();
// Cancela o runnable ao sair da activity
handler.renoveCallbacksAndHessages(null);
}

Ao executar esse cdigo, ser feito o download da imagem normalmente. Depois


de dez segundos, o download ser feito novamente. Observe que no mtodo
onDestroy() da activity todas as mensagens enviadas ao handler foram canceladas
Captulo 10 I Threads, Handler e Asynclask 335
com o mtodo renoveCallbaclsAndMessages(null). Isso necessrio para garantir que
nenhuma mensagem seja entregue com a activity fechada. Caso contrrio, o
handler continuaria executando continuamente sem a necessidade de fazer isso.

10.6 Implementao de um tela Splash Screen para sua aplicao


Provavelmente voc j viu algum aplicativo que exibe uma tela inicial com a
mensagem Por favor, aguarde, carregando a aplicao...' ou talvez exibindo uma
imagem antes de carregar o aplicativo.
Essas telas de inicializao so chamadas de splash screen e para implement-las
no Android podemos utilizar umhandler. Uma splash screen deve permanecer
aberta por determinado tempo para que a aplicao consiga realizar algum pro
cessamento inicial. Enquanto isso, o usurio pode car observando uma imagem
ou mensagem na tela.
Vamos criar. uma splash screen na qual o layout da activity vai mostrar uma
simples gura.

/res/layout/activity_spIash_screen.xml
<FraneLayout nlns:androd="http://schemas.android.con/apk/res/android"
android:layout_width="natch_parent" android:layout_height="natch_parent">
<InageView androd:src="@drawable/livro_android"
androd:layout_width="wrap_content" android:layout_heght="wrap_content"
android:layout_gravity="center"/>

O cdigo da activity vai mostrar a tela por um segundo e depois vai prosseguir para
a primeira activity do projeto. Para isso, uma mensagem enviada ao handler com
um atraso de um segundo. No momento em que o handler receber a mensagem,
a aplicao j foi carregada e a prxima activity j pode ser exibida.

SpIashScreenActivity.java
public class SplashScreenActvity extends Activity {
@Overrde
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Exibe o layout com a imagen...
setContentView(R.layout.activity_splash_screen);
// delay de 1 segundo
new Handler().postDelayed(new Runnable() {
336 GO0Ql|! hdlld - 4' edlh
@0verride
public void run() {
// Inicia a HainActivity ,
startActivity(new Intent(getBaseContet(), HainActivity.c1ass));
// Fecha a activity da splash
nish();
}

},1600); /I Un segundo de atraso


1

Urna splash screen geralmente a primeira activity do projeto que aquela ao


MAIN e categoria LAUNCHER configurada no AndroidHani.fest.m1. No projeto de exemplo
deste captulo. eu deixei a Sp1ashScreenActivity como a primeira activity e cadastrei
a MainActivity que mostra a lista com os exemplos como uma activity normal,
conforme demonstrado a seguir.

J AndroidManifest.m|
<nanifest . . .>
<uses-permission android:nane=android.permission.INTERNET" /
<app1ication . . . >
activity androtd:nane=".SpIashScreenActivity"
intent-Iter
<action android:nane="android.intent.action.HAIN" /
category android:nane=android.intent.category.LAUNCHER /
/intent-lter
/acttvity
<activity android:name=".MainActivity" android:1abeI="@string/app_nane" /

por isso que, ao executar o projeto de exemplo deste captulo, voc ver uma
splash screen antes de visualizar a lista com os exemplos. Lembre-se de que a tela
de splash screen deve chamar o mtodo nish() para encerrar (3553 activity para
destruir a splash ao entrar no aplicativo.

|mP|'| Saiba WC Segundo as boas praticas de interface para Android.


no e recomendado criar uma splash screen. Uma tela de splash screen deve
ser utilizada somente se voc obrigatoriamente precisa ganhar tempo antes de
abrir *1 1*Pl11 POP Cxcmplo, para carregar informaoes necessarias para o
seu aplicativo funcionar. O fato e que muitos aplicativos comearam a abusar da
5Pla5h SCYCCH c mostram mclusive banners e anuncios antes de abrir o aplicativo.
Captulo 10 I Threads, Handler e AsyncTask 337
Isso para os usurios ruim, pois eles querem utilizar o aplicativo o mais
rpido possvel, e no car olhando guras. Portanto, utilize uma splash screen
somente se for realmente necessrio. Esse assunto foi mostrado aqui apenas para
voc saber como implementar tal tipo de funcionalidade, mesmo porque est
relacionado com o disparo de mensagens com atraso (delay) e a classe Handler.

10.7 AsyncTask
Criar uma thread simples, mas vimos que necessrio utilizar um Handler ou o
mtodo de atalho run0nUIiThread(runnable) para atualizar a interface.
Porm ao desenvolver aplicativos para Android no utilizamos threads diretamen
te, pois se recomenda utilizar a classe AsyncTask, a qual representa uma pequena
biblioteca de threads. A seguir podemos visualizar as suas principais caractersticas.
1. A classe AsyncTask gerencia internamente as threads e handlers necessrios
para atualizar a interface.
2. Uma tarefa pode ser cancelada se chamar o mtodo cancell(boolean).
3. Contm mtodos para atualizar o andamento (progresso) de uma tarefa,
por exemplo, o progresso de um download.
4. Contm um pool de threads que pode executar as tarefas de modo serial
ou em paralelo.
Para explicar o que uma AsyncTask, vamos ver um exemplo de cdigo. Basicamente
para criar uma tarefa preciso criar uma subclasse de AsyncTask e informar os trs
argumentos <Parans,Progress,Result>, conforme demonstrado a seguir. A sintaxe
<Parans,Progress,Result> das classes genricas (Generics) do Java.
private class DownloadFilesTask extends AsyncTaskURL, Integer, Long> {
@0verride
protected void onPreExecute() {
// Executa na thread principal
// til para mostrar um ProgressDialog ou ProgressBar
}

protected Long doInBackground(URL... urls) {


// Executa em segundo plano (background)
// 0 retorno do tipo "Long" passado ao mtodo onPostExecute()
return 1L;
}

protected void onProgressUpdate(Integer... progress) {


// Pode atualizar o progresso da tarefa
338 Google IO - 4 Ed0
// 0 valor do progresso deve ser enviado via o mtodo publishProgress(int)
// durante o doInBackground()
}

protected void onPostExecute(Long result) {


// Recebe o resultado do mtodo doInBackground()
// Executa na UI Thread e pode atualizar a view
}

O cdigo anterior est comentado, ento leia-o com ateno. Depois de criar essa
classe, para execut-la basta chamar o mtodo execute() e informar os parmetros,
que nesse caso pela Genetics foi denido como um objeto do tipo URL.
new DownloadFilesTask().execute(url);

Ou voc pode at passar mais de um parmetro:


new DownloadFilesTask().eecute(url1, url2, url3);

Para vermos um exemplo mais detalhado, o cdigo a seguir mostra como


fazer o download de um arquivo, e ainda mostra como utilizar o mtodo
onProgressUpdate(progress).

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {


protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
// Reporta o progresso
publishProgress((int) ((i / (oat) count) * 196));
// Se o mtodo cancel() foi chamado, termina.
if (isCancelled())
break;
}

return totalSize;
}

protected void onProgressUpdate(Integer... progress) {


// Atualiza a interface com o progresso dd dgwnload,
setProgressPercent(progress[0]);
1

protected void onPostEecute(Long result) {


showDialog("Downloaded " + result + " byteS")
}

}
Captulo 10 I Threads, Handler e AsyncTask 339
Na prtica, eu nunca precisei utilizar os mtodos pub1shProgress(progress) e
onProgressUpdate(progress), pois geralmente em aplicativos a nica coisa de que
precisamos consultar um web service, e durante isso podemos mostrar uma
animao com um ProgressBar ou Progressalog. Portanto, costumo utilizar um
template apenas com os mtodos onPreExecute(), doInBackground() e onPostExecute().
A lista a seguir explica o signicado de cada mtodo da AsyncTask.
Mtodo Descrio
onPreExecute() Mtodo executado antes de a thread iniciar, sendo uma boa
oportunidade para exibir uma janela de progresso ao usurio
ou uma mensagem de por favor, aguarde? Esse mtodo executa
na UI Thread."
doInBackground() Mtodo executado em background por uma thread, que deve
conter todo _o processamento pesado. Ele pode retornar um
objeto qualquer, o qual ser passado como parmetro para o
mtodo onPostEecute(). aqui que a thread executa, mas isso
feito automaticamente para voc.
onProgressUpdate() Mtodo chamado na UI thread e recebe geralmente um inteiro
para informara quantidade do progresso. O progresso deve serin
formado em background dentro do mtodo doInBackg round( ). Para
reportar o progresso, utilizado o mtodo pub1shProgress(int).
onPostEecute() Mtodo executado na UI Thread, em que podemos atualizar
a view com o resultado. Ele chamado utilizando um Handler
internamente.

Note que esses mtodos no devem ser invocados manualmente, pois so chama
dos automaticamente pela classe AsyncTask. Portanto, para iniciar o processamento,
necessrio apenas chamar o mtodo AsyncTask.execute(params. . .), informando os
parmetros se necessrio, como por exemplo: `
new Down'LoadF1esTask().eecute(ur11, ur12, ur13);

Nota: resumindo, voc deve criar um AsyncTask e utilizar o mtodo doInBackground()


para fazer o processamento, o qual executado automaticamente em uma thread.
Quando terminar, utilize o mtodo onPostEecute() para atualizar as views. A
classe AsyncTask elimina a necessidade de criar uma thread e utilizar um handler,
pois ela j faz esse trabalho para voc.

Talvez a parte mais difcil de entender na classe AsyncTask sejam os seus trs tipos
genricos, que tm a seguinte denio: AsyncTask<Params, Progress, Resu1t>.
340 Google Android - 4 edio
Parmetro Descriao g d_ _ __ ____ _ _`_ W
Pa rams O primeiro tipo genrico chamado de Parans, que so os argumentos
que podemos passar ao mtodo eecute(params. . .) para executar 0
AsyncTask. No exemplo da classe DownloadFilesTask, o parmetro foi
denido como URL, e portanto a tarefa pode ser executada passando
URLs como parmetro ao mtodo eecute( ) , ex: new DownloadFilesTask(),
eecute(url1, url2, url3).
Progress O segundo tipo genrico chamado de Progress, e pode ser utilizado
para receber um valor inteiro, que representa o progresso da exe
cuo, e em conjunto com uma barra de progresso, para noticar
o usurio. No exemplo que criamos, esse parmetro foi denido
como Integer, e o mtodo onProgressUpdate(Integer. .. progress) cou
com essa assinatura.
Result O terceiro tipo genrico chamado de Result, e o mesmo objeto
que retorna do mtodo doInBackground() passado como parmetro
para o mtodo onPostEecute(). O mtodo onPostEecute() executa na
UI Thread e pode atualizar a interface. No exemplo que criamos,
o retorno do mtodo doInBackground() era do tipo Long, e o mtodo
onPostEecute(Long result) recebe um Long como argumento.

Eu sei, parece complicado, mas logo voc se acostuma com a ideia. Mas isso nada
mais do que o conceito de Genetics da linguagem Java. Qualquer dvida, con
tinue lendo e depois volte aqui para revisar os conceitos, no se preocupe se no
entender exatamente o que significa cada parmetro agora.
Outra informao importante que, ao criar a AsyncTask, voc pode denir os ti
pos genricos que quiser e deixar alguns como Void. O prximo exemplo mostra
como deixar todos os argumentos como Void e somente o argumento Result como
Boolean. Veja como ca a sintaxe:

private class DownloadBitnapTask extends AsyncTask<Void, Void, Boolean {


Bitnap bitmap;
@Override
protected Boolean doInBackground(Void... parans) {
bitmap = downloadBitnap();
return true;
}

protected void onPostEecute(Boolean ok) {


if(ok) {
// atualizar a view aqui :-)
}

}
Captulo 10 I Threads, Handler e AsyncTask 341
s vezes, um cdigo e um exemplo falam mais que mil palavras. Vamos criar nova
mente o exemplo do download da imagem, mas desta vez utilizando a classe AsyncTask

MainActivity.java
public class MainActivity extends AppCompatActivity {
private static nal String URL = "http://livroandroid.com.br/imgs/livro_android.png";
private ProgressBar progress;
private Imageview imgview;
private Bitmap bitmap;
@0verride
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity;download_imagem);
imgView = (ImageView) ndViewById(R.id.img);
progress = (ProgressBar) ndViewById(R.id.progress);
// Faz o download
downloadImagem();
}

// Faz o download da imagem em uma nova thread


private void downloadImagem() {
// Cria uma AsyncTask
DownloadTask task = new DownloadTask();
// Executa a task/thread
task.execute();
}

private class DownloadTask extends AsyncTaskVoid,Void,Bitmap {


@Override
protected void onPreExecute() {
super.onPreExecute();
// Executa antes do download. Mostra o ProgressBar para fazer a animao.
progress.setVisibility(View.VISIBLE);
}

@0verride
protected Bitmap doInBackground(Void... params) {
// Faz o download em uma thread e retorna o bitmap.
try {
bitmap = Download.downloadBitmap(URL);
} catch (Exception e) {
Log.e("livroandroid",e.getHessage(), e);
}

return bitmap;
}
342 Google Android - 4' edio
protected void onPostExecute(Bitnap bltnap) {
if(bitmap != null) {
// Atualiza a imagen na UI Thread
ingvew.setImageBtmap(btnap);
// Esconde o progress
progress.setVisiblity(View.INVISIBLE);
}

public Context getContet() { return this; }


}

O layout da activity o mesmo do exemplo anterior do doumload da imagem. E,


ao executar o cdigo, o resultado tambm ser o mesmo.
O importante voc perceber que a AsyncTask encapsulou a necessidade de mani
pular as threads e handlers, alm de trazer outros benefcios os quais no utilizei
neste exemplo, como cancelar as tarefas ou utilizar o pool de threads para executar
o processo de forma serial ou paralela.

Nota: uma das vantagens de utilizar a classe AsyncTask que possvel parar a
execuo da tarefa com o mtodo cancell(boolean). Quando uma tarefa cancelada,
o mtodo onCancelled() chamado. Para descobrir se uma tarefa j foi cancelada,
basta chamar o mtodo isCancelled(). comum nos mtodos onPause() da activity
e fragment chamar o mtodo cancell(boolean) da AsyncTask; assim, quando a activity
vai entrar em estado de pausa, essas tarefas so interrompidas para economizar
recursos, uma vez que a tela ser fechada. Tudo depende do caso e se voc deseja
ou no parar a execuo da tarefa.

10.8 Download de imagens tom a biblioteca Picasso


O principal objetivo deste captulo foi lhe explicar a importncia do uso de
threads no aplicativo e consequentemente explicamos as classes Handler e AsyncTask.
Como o exemplo de threads que criamos fez o download de uma imagem, vamos
aproveitar e mostrar uma biblioteca que facilita este download, chamada de Picasso
(http://squaregithub.io/picasso/).

Essa biblioteca utilizada por muitos desenvolvedores, pois extremamente


simples e inclusive faz cache das imagens. Para utiliza-la, basta declarar a seguinte
dependncia no arquivo app/bui1d.gradle.
Captulo 10 n Threads, Handler e AsyncTask 343
/app/buiId.grad|e
dependencies {

compile 'com.squareup.picasso:picasso:2.5.2'
}

Depois de declarar adependncia, o download pode ser feito com apenas uma
nica linha de cdigo.
Picasso.with(this).1oad(URL).into(imgView);

Tambm possvel especicar uma imagem que deve ser exibida antes de o
download terminar (placeholder) e uma imagem de erro.
Picasso.with(this).1oad(URL).placeholder(R.drawab1e.android).error(R.drawab1e.android)
.into(imgView);

Caso voc queira animar um ProgressBar como fizemos nos exemplos anteriores,
basta mostrar o progresso antes do download, e escond-lo quando o download
terminar. A biblioteca Picasso oferece a interface de Callback para avisar o aplicativo
sobre o resultado do download, seja sucesso ou falha.
progress.setVisibi1ity(View.VISIBLE);
Picasso.with(this).1oad(URL)
.p1aceho1der(R.drawable.android)
.error(R.drawab1e.android)
.into(imgView, new Ca11back() {
@Override
public void onSuccess() { // OK
progress.setVisibility(View.GONE);
}

@0verride
public void onError() { // ERRO
progress.setVisibi1ity(View.GONE);
}

});

isso: simples e prtico.

Dica: mostrei como animar um ProgressBar para seu aprendizado, e isso muito
utilizado em vrias situaes. Porm, no caso de download de imagens, parece
que est havendo uma tendncia de utilizar apenas uma imagem temporria
durante o download, chamada de placeholder. Um exemplo a navegao no
aplicativo do Google Play que mostra uma imagem vazia enquanto o download
344 Google Android - 4 edio
do cone do aplicativo no termina. Nesse contexto, a biblioteca Picasso
extremamente til, pois faz o download em uma nica linha de codigo.

10.9 Links teis


Neste captulo, estudamos a classe Handler, que tem como principal objetivo
enviar uma mensagem para ser processada na UI Thread. Tambm estudamos a
importncia de criar threads e por ltimo aprendemos a utilizar a classe AsyncTask.
No que se refere principalmente classe AsyncTask, ainda temos rnuito o que estudar.
Como eu expliquei anteriormente, a classe AsyncTask uma biblioteca de threads e
contm vrios recursos interessantes. Acredito que esta introduo sobre threads
e AsyncTask j suciente para avanarmos com nossos estudos.
Eu quero entrar logo nos captulos 11 e 12, sobre Material Design e Toolbar respec
tivamente, para logo depois comear o desenvolvimento do aplicativo dos carros
passo a passo. Nesse aplicativo tambm vamos usar threads, pois os carros sero
buscados de um web service, portanto vamos aprender na prtica tudo o que for
necessrio. No final do livro, deixei um captulo especial mais avanado sobre a
classe AsyncTask (Captulo 31), que acredito que agora no seja o momento certo
para ler. Vamos dar um passo de cada vez.
Para complementar seus estudos, separei alguns links da documentao ocial.
(ommunicating with the UI Thread

https://developer android. com/training/multiple-threads/communicate-ui. html


Processes and Threads

http://developer android.com/guide/components/processes-and-th read.s.html


Picasso

http://squaregithub.io/picasso
.\ !.
CAPTULO 11
Material Design
\-1
.xl p

Com a chegada do Android 5.0 (Lollipop), foi criado o Material Design, um guia
completo sobre como criar aplicaes com um timo design e que leva em consi
derao que atualmente o Android est difundido em diversos dispositivos como
smartphones, tablets, wearables, culos, TVs e carros.

Com esses avanos da plataforma, foi necessrio criar um guia de Design, e princi
palmente uma interface que funcione de forma consistente, independentemente da
plataforma e do tipo do dispositivo, seja um pequeno relgio ou uma grande TV

11.1 Introduo
O Material Design um guia completo sobre como implementar o visual, anima
es e interao entre os componentes de um layout, considerando que o Android
se tornou uma plataforma comum para vrios dispositivos, como smartphones e
tablets (Android), wearables (Android Wear), culos (Google Glass),TVs (Android
TV) e carros (Android Auto). `
Implementar o visual de um aplicativo de forma consistente, simples e intuitiva para
cada tipo de dispositivo um desao, e o Material Design o resultado do esforo
do Google de padronizar um guia completo de design para nos auxiliar nessa tarefa.
No Android 5.0 (Lollipop), foram criadas diversas APIs para auxiliar o desenvol
ver a criar interfaces ricas, uidas e com animaes iguais quelas encontradas
nos aplicativos nativos do Google. O melhor de tudo que podemos utilizar
uma biblioteca de compatibilidade para trazer os benefcios do Material Design,
inclusive para dispositivos com verses antigas do Android.
A gura 11.1 da documentao ocial do Android e mostra a ideia do Material Design:
um aplicativo que tem um design consistente em diversos tipos de dispositivos.

345
346 Google Android - 4' edio

...z .. .. _...--zz
.__,,.,,.`,,,,,
,.. ..-zm
..-..~. zz...
W.
. a.....
.z..........`$--
...uv I

Figura 11.1 - Material Design.

11.2 Tema Material

No captulo 5, sobre action bar, estudamos a importncia dos temas na plata


forma de desenvolvimento do Android. Vimos que o tema Holo revolucionou o
desenvolvimento de aplicativos, pois introduziu a action bar, e o tema Material
foi criado junto com o Android 5.0 (Lollipop).
Nesta altura do livro, voc j sabe congurar a biblioteca de compatibilidade
no projeto e tambm sabe utilizar o tema Material. Conforme estudamos, basta
configurar o tema do aplicativo para herdar de algum destes temas:
android:/Theme.Matera1

android:/Theme.Material.Light
androd:/Theme.Materia1.Lght.DarkActionBar

Caso o aplicativo utilize a action bar de compatibilidade, deve-se utilizar o tema


AppCompat, que consistente com todas as verses do Android.
Theme.AppCompat

Theme.AppCompat.Lght

Theme.AppCompat.Lght.DarkActonBar

Lembre-se de que, para utilizar o tema AppCompat, voc deve declarar no arquivo
app/build.gradle a dependncia para a biblioteca supportzappcompat-v7 e todas as
activities devem herdar de AppCompatActvty.
Captulo 11 I Material Design 347
app/buiId.gradIe
dependencias {

compila 'com.androd.support:appcompat-v7:22.1.9'
}

Nota: para um melhor entendimento dos prximos exemplos, recomendo abrir o


projeto de exemplo deste captulo no Android Studio e acompanhar a explicao.

11.3 Paleta de cores


O Material Design utiliza muito o conceito de ter uma cor padro (primary color)
para o aplicativo e uma cor de acentuao (accent color) para dar destaque a al
gumas views. No captulo 7, sobre a classe View, j expliquei um pouco sobre esse
assunto, e agora vamos estuda-lo um pouco mais a fundo.
O mais legal do tema Material que o Google tornou bem simples customizar
as cores do tema, algo que sempre foi uma dor de cabea nos temas antigos. Para
customizar as cores, basta sobrescrever algumas propriedades do tema, conforme
indicado pela figura 11.2.

_1, l
Figura 11.2 - Cores para customizar 0 tema Material.
343 Google Android - 4 edio
Para brincarmos, crie o projeto Helloaterial, ou abra o projeto de exemplo deste captu
lo. Ao criar o projeto com oAndroid Studio, deike ele compatvel com o Android 23 ou
superior e ative a biblioteca de compatibilidade appconpat-v7 no arquivo app/build.gradle_
Lembre-se tambm de que a MainActivity deve ser lha de AppCompatActivity.

Para comear, vamos customizar as cores do tema. O que eu costumo fazer


customizar a cor primria e a cor de acentuao, conforme demonstrado a seguir.
Note que, como estamos utilizando o tema AppConpat, s precisamos de uma verso
do arquivo /res/values/styles.xml. `
/res/values/styIes.mI

<style nane="AppThene" parent="Theme.AppConpat.Light.DarkActionBar">

<iten name:"colorPrinary"@color/prinary

<iten name:"colorPrinaryDark">@color/prinary_dark

<iten name="colorAccent">@color/accent

Estou customizando as cores no arquivo do tema, e por isso criei estas cores no
arquivo /res/values/colors.xml.

/res/values/coIors.xmI
<resources

<color name="primary">#03A9F4
<color name="primary_dark">#01579B
<color nane="accent">#F44336

Simples assim. Se voc executar o projeto com essas conguraes, a cor da action
bar ser azul, a cor da status bar ser um azul escuro, e a cor de acentuao uti
lizada para dar destaque vermelho.

Nota: a cor primria (primary) deve ser a cor principal do aplicativo. A cor primria
escura (primary escura) uma variao escura da cor primria e utilizada na
status bar. A cor de acentuao (accent color) de extrema importncia para
destacar views importantes do aplicativo e chamar a ateno do usurio.
Captulo 11 I Material Design 349
Para escolher essas cores, o Google recomenda seguir a paleta de cores, que pode
ser encontrada nesta pgina da documentao ocial:
http://www. google. com/design/spec/style/color html
Voc vai encontrar diversas cores nessa ina e todas elas tero vrios nveis
9

de intensidade. Segundo as boas prticas do Material Design, a cor primria


(primary) do aplicativo deve ser alguma cor com intensidade 500 e a cor primria
forte (primary dark) deve ter intensidade 700 ou superior.
Para entender do que estou falando, abra o link mencionado anteriormente e
veja a paleta de cores.

11.4 Elevao de views


No Material Design, as views podem ser elevadas da superfcie, aumentando ou
diminuindo a sombra sobre elas. Para alterar a elevao de uma view no XML,
utilize o atributo androdzelevaton ou utilize o mtodo setE1evaton(z) para alterar
pelo cdigo.
A gura 113 demonstra o conceito de elevao. Na esquerda podemos visualizar
a view normal. Na direita podemos visualizar o resultado se aplicada a elevao
no eixo Z da view

Figura 11.3 - Elevao e sombra da view.

Esse conceito um dos pilares do Material Design, pois os elementos visuais so


construdos e aplicados sobre camadas que se sobrepem. A figura 11.4 demonstra
a ideia. Na esquerda as views esto sobrepostas (correto) e na direita no temos
ideia de profundidade (incorreto).
350 Google Android - 4~ Qdljg

=:\ 1%zu'm| r;, '

Figura 11.4 - Elevao e sombra da view.

Para praticarmos o conceito de elevao, vamos criar um exemplo. O arquivo de


layout contm um boto cuja elevao vamos alterar via programao.

Ci /res/Iayout/activity_exempIo_eIevation.xml

<LnearLayout . . .>
<Button android:d="@+d/button" androd:tet="@strng/he1Io_wor1d"
androd:1ayout_wdth="wrap_content" android:1ayout_height="wrap_content"
androtd:eIevatton="2dp" />
<SeekBar androd:id="@+d/seekBar"
sty1e="?android:attr/progressBarSty1eHorzonta1"
androd:1ayout_wdth="match_parent" androd:1ayout_heght="wrap_content"
androd:nax="100" androtd:paddng="2Gdp" androd:progress="0" />
</LnearLayout>

A SeekBar uma view que se parece com um controle para aumentar ou diminuir
o volume do som; neste caso, vai permitir navegar entre O a 100, pois foi definida a
propriedade androd:ma="100". No codigo da activity sempre que o valor da Seekbar
for alterado, vamos congurar esse mesmo valor na elevao do botao.

(5131 ExemploE|evationActivity.java

public class Eemp1oE1evationActvity extends AppCompatActvity {


private SeekBar seekBar;
private Button button;
@0verrde
protected void onCreate(Bund1e savedInstanceState) [
super.onCreate(savedInstanceState);
Captulo 11 I Material Design 351
setContentView(R.layout.activity_eemplo_elevation);
button = (Button) ndViewById(R.id.button);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
seekBar = (SeekBar) ndViewById(R.id.seekBar);
seekBar.set0nSeekBarChangeListener(new SeekBar.0nSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fronUser) {
// Altera a elevao da view ao mexer na SeekBar
button.setElevation(progress);
}
@0verride
public void onStartTrackingTouch(SeekBar seekBar) { }
@0verride
public void onStopTrackingTouch(SeekBar seekBar) { }
});
1

Para entender esse exemplo, voc precisa executar no emulador. Ao mexer na


Seekbar, a elevao da view ser alterada e voc perceber o efeito que acontece na
sombra da view como se a view estivesse levantando e saindo da tela. A gura
115 mostra o valor 0 (zero) congurado como elevao e depois o valor 100. Veja
que no valor 100 a sombra da view grande.
Vale ressaltar que o mtodo setElevation(oat) da classe View est disponvel apenas
para o Android 5.0 ou superior. Em nosso caso, por questes de compatibilidade,
pode ser utilizada a classe Viewtompat, conforme demonstrado a seguir:
ViewConpat.setElevation(view, valor);

A classe ViewConpat aplica a elevao em dispositivos com Android 5.0 ou superior,


ou simula a elevao em verses antigas. O importante que o cdigo ca com
patvel com todas as verses.

. aowm; ueio
. __ u zz z z~ zz z z ,Q ` ,~. uw, .

Figura 11.5 - Exemplo de elevao e sombra da view.


3 52 Google Android - 4 edio
Importante: execute esses exemplos no emulador do Android 5.0 ou superior
para obter os efeitos desejados do tema Material. Por questes de compatibilidade
com verses antigas do Android, recomendo utilizar a classe Vewtompat.

11.5 Ripple - feedback ao toque


Ripple o nome do efeito de toque padro do Android 5.0, e todas as views como
botes, listas e aes da action bar o tm por padro. Esse? efeito de toque no
Android conhecido como Touch Feedback (feedback ao toque), e seu objetivo
informar ao usurio que o sistema recebeu 0 toque de uma forma leve e agradvel.

l
O efeito de ripple alcanado pela classe Rpplerawable, que pode ser criada por
programao, ou at mesmo via XML criando uma tag <rpple>. Neste prximo
exemplo, vamos testar em um boto vrios efeitos diferentes. Para isso abra o
arquivo /res/layout/activity_exemplo_ripple.xmI no editor visual (Figura 11.6).

* bel ii] l
.zirtriry_eempIo_r|ppIe xml \ 1
O ..
, Nexus S' v AprTheme mv -'

1 .,..
i

'W*V'- z'.-
2..=;-ir
rf cr
'-M, mg;

1

l
'NG
l

Figura 11.6 - likitos ao clicar em um boto.

Cada boto est congurado com um efeito diferente, mas para entender a expli
caao, por favor, execute o projeto no emulador para visualizar o efeito. No tem
como demonstrar as animaes no livro.

Agora que voce Ja executou o exemplo, vamos continuar com a explicao.


Captulo 11 I Material Design 353
O primeiro boto no faz `nada, mas caso o aplicativo seja executado em um
Android 5.0 ou superior o efeito de ripple criado automaticamente.
Para dar esse feedback ao toque e adicionar o efeito de ripple e qualquer vievsg
podemos utilizar o item ?attr/se1ectab1eItemBackground, que deve ser aplicado como
fundo (background) de uma view O segundo boto mostrou justamente isso.

<Button android:text="@strng/ok2" . . .
android:background="?attr/se1ectab1eItemBackground" />

A gura 11.7 demonstra a animao criada ao tocar no boto. A primeira parte


mostra o toque, e depois o efeito da onda foi crescendo e se propagando at ocupar
o boto inteiro. O item ?attr/se1ectab1eItemBackground muito utilizado ao construir
uma lista com Lstvew, com o objetivo de congurar o efeito de toque da lista.

()KI2

()K2

()K2

Figura 11.7 - Feedback ao toque.

Nota: a animao de ripple parecida com o efeito de quando voc toca alguma
superfcie com gua, formando aquelas ondas circulares.

O terceiro boto mostrou o efeito criado pelo item ?androd:attr/se1ectab1eItemBa


ckgroundBorder1ess, o qual faz o efeito da onda porm sem margens.

<Button androd:tet="@strng/ok3" . . .
androd:background="?attr/se1ectab1eItemBackgroundBorder1ess" />

como se o efeito continuasse executando, pois no bateu em nenhuma borda


para parar. A gura 11.8 demonstra que o efeito sem borda inclusive invadiu o
espao dos outros botes.
Os prximos botes, 4, 5, 6 e 7, mostram como criar um efeito de ripple customi
zado com um arquivo XML; assim podemos denir inclusive as cores do boto
e do efeito da onda.
354 Google Android - 4= edio
OK2

OK3

OK4

Figura 11.8 - Feedback ao toque com o efeito da onda sem a borda.

Um ripple criado com a tag <rpp1e> e o atributo androdzcolor dene a cor do


efeito das ondas. A tag dene o formato da borda, que pode ser retangular
(shape="rectang1e") ou oval (shape="ova1"). A seguir, temos um exemplo de arquivo
que cria um efeito de ripple retangular.

/res/drawable/rppIe_rect.xmI
<rpp1e xmlns:androd="http://schemas.androd.com/apk/res/androd"
androd:co1or="@co1or/accent">
<tem androd:d="@androd:id/mask">
<shape androd:shape="rectang1e">
<so1d androd:co1or="@co1or/primary" />

</rpp1e>

Esse arquivo customizado pode ser denido como o fundo de qualquer view
conforme demonstrado a seguir.

<Button androd:text="@strng/ok4" . . .
android:background="@drawable/rpple_rect" />

Para conferir os resultados, execute o projeto de exemplo deste captulo.

Nota: segundo as boas prticas do Material Design, importante fornecer


o feedback ao toque (Touch Feedback) para interagir com o usurio. Esses
conceitos podem ser aplicados em qualquer tipo de view.
Captulo 11 n Material Design 355
11.6 Floating Action Button (FAB)
Um dos novos padres mais utilizados do Material Design o Floating Action Button,
que consiste em um boto utuante que deve ser utilizado para conter a ao
mais importante da tela. Esse boto deve ter uma cor chamativa e por isso re
comendado utilizar a cor de acentuao denida no tema.
Vale ressaltar que o Floating Action Button frequentemente chamado apenas de FAB,
portanto acostume-se com essa sigla. Felizmente, criar um FAB bem simples e voc
pode utilizar um InageButton com um fundo especial, conforme o cdigo a seguir:

/res/Iayout/activity_exempIo_oating_button.xmI
<FrameLayout n1ns:androd="http://schens.androd.con/apk/res/androd"
android:1ayout_wdth="natch_parent" androd:1ayout_heght="natch_parent"
androd:paddng="16dp">
<TextVew android:tet="@strng/he11o_wor1d"
androd:1ayout_wdth="wrap_content" androd:1ayout_heght="wrap_content" />
<ImageButton`androd:d="@+d/bt0k"
androd:1ayout_wdth="56dp"androd:1ayout_heght="56dp"
androd:1ayout_gravity="center"
android:src="@androdzdrawable/c_nput_add"
android:tint="#fffB00"
android:background="@drawable/fab_ova1"
androd:e1evation="8dp" />
</FraneLayout

Esse boto foi congurado com uma imagem nativa do Android, sendo que a
notao @androd:drawab1e/ nonejnagem utilizada para acessar um recurso nativo do
Android. Em nosso exemplo, estamos utilizando a imagem c_nput_add. Se voc
abrir essa figura com a tecla CtrI+cIique no editor, ver que ela um sinal de mais
(+) transparente, conforme a figura 11.9.
1 -. : c \' _
' 'z^'. '. U-'zz '~ r, *.

.z;_,.. _.(4~.zh z \_._


W ''=='f'.

..-.
-,..;, ' .-uy...
ni 1 rf x'f':' .z \ viu \` w ~:
..".`=..'"," ' -`."-X
-1' '1'z``.'--'- _ v'` _
..,.zzz.z,.-,r;.

Figura 11.9 - Imagem transparente.

O segredo dessa imagem que a rea do sinal de mais (+) pode ser preenchida
com qualquer cor, e por isso definido o atributo androd:tnt="#fff000" que est
pintando a cruz de amarelo. j o fundo do boto feito com um efeito de ripple,
sendo assim basta criar um XML customizado conforme demonstrado a seguir:
356 Google IIO - 4 edio
/res/drawable/fab_ovaI.xmI
<?m1 verson="1.0" encoding="