• Save
Curso de Android Aula 4
Upcoming SlideShare
Loading in...5
×
 

Curso de Android Aula 4

on

  • 7,986 views

Quarta sequência de slides do curso de Android da Especializa Treinamentos ...

Quarta sequência de slides do curso de Android da Especializa Treinamentos

http://www.especializa.com.br/curso/android

Assunto desta aula:
- Application (Mais detalhes do AndroidManifest.xml)
- Activity
- Fragment

Statistics

Views

Total Views
7,986
Views on SlideShare
7,196
Embed Views
790

Actions

Likes
24
Downloads
20
Comments
8

4 Embeds 790

http://especializa.com.br 786
http://www.udemy.com 2
https://twitter.com 1
http://www.especializa.com.br 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

15 of 8 Post a comment

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Curso de Android Aula 4 Curso de Android Aula 4 Presentation Transcript

  • GoogleAndroid Jose Berardo Especializa Treinamentos 1
  • Ementa1. Introdução ao Android2. Ambiente de desenvolvimento3. Conceitos básicos4. Application, Activities e Fragments5. Intents e Broadcast Receivers6. Views e Layout Managers7. Persistência de dados e Content Providers8. Shared Preferences 2
  • EmentaApplication, Activities e Fragments Android Application Mais sobre o Manifest.xml Activities Pilhas, estados e ciclo de vida Monitoramento de estados e LogCat Activity subclasses Fragments Estratégias de fragments em tablets x smartphones Ciclo de vida Fragment subclasses e suporte a APIs antigas 3
  • O que faz uma aplicação?Tipos de objetos que fazem uma aplicação Android: Activity Objetos de classes que herdem de android.app.Activity Controladora da interface de cada tela Activities carregam Views e Fragments para exibir conteúdo ao cliente Service Objetos do tipo android.app.Service Trabalhadores invisíveis que executam tarefas em background Atualizam Activities, disparam Notifications e difundem Intents Suas tarefas em geral são longas ou constantes sem nenhuma interação direta com o usuário 4
  • O que faz uma aplicação?Tipos de objetos que fazem uma aplicação Android: View Objetos de classes que herdem de android.view.View Representa cada componente na tela Gestores de layout herdam de sua subclasse abstrata android.view.ViewGroup Fragment Controladores de trechos de telas criados desde os primeiros tablets Android quando viram que uma Activity só para controlar essas telas maiores ficaria muito extensa São carregados por Activities, mas possuem seu próprio ciclo de vida 5
  • O que faz uma aplicação?Tipos de objetos que fazem uma aplicação Android: Intent Objetos do tipo android.content.Intent Mecanismo de troca de mensagens interactivities e até mesmo interaplicações São extensamente usadas para abrir ou encerrar Activities ou Services, enviar mensagens em broadcast e muito mais Broadcast Receiver Intent listeners Fazem a aplicação reagir a determinadas Intents publicadas Constroem uma aplicação orientada a eventos 6
  • O que faz uma aplicação?Tipos de objetos que fazem uma aplicação Android: Notification Possibilitam que sua aplicação alerte o usuário de determinada ação sem interromper o que ele estiver fazendo no momento Publicam na barra de notificações, em geral a partir de um Service ou Broadcast Receiver Content Provider Objetos do tipo android.content.ContentProvider Mecanismo compartilhável de armazenamento de dados que interage com bancos SQL Há diversos content providers nativos que nos dão acesso a bases como lista de contatos e mídias armazenadas 7
  • O que faz uma aplicação?Tipos de objetos que fazem uma aplicação Android: Widget Componentes visuais que rodam direto na home screen São uma variação especial de Broadcast Receiver, permitindo interação com o usuário e execução direta Live Wallpaper Serviços com interatividade na home screen Widgets de fundos de tela responsivos 8
  • Mais sobre o Manifest.xmlOutros atributos da tag raiz <manifest> package - determina o nome único do projeto. É recomendado que você utilize o padrão do DNS invertido finalizando com o nome do projeto android:* - prefixo XML que carrega nós definidos no namespace http://schemas.android.com/apk/res/android installLocation - Local default de instalação da aplicação. Disponível desde a API 8 (Froyo - 2.2) internalOnly - Só admite que a aplicação seja instalada na memória interna do dispositivo preferExternal - Sugere que a aplicação seja instalada no SD card. Se esta estiver cheia ou indisponível no momento da instalação, o sistema vai instalar na memória interna auto - Utiliza as definições padrão do cliente 9
  • Mais sobre o Manifest.xmlLocal de instalação da aplicação Instalar a app no SD card é bom por contar com mais espaço Mas quando o usuário utilizar o aparelho como USB mass storage, todas as apps instaladas no SD card serão encerradas Activities são fechadas Services são encerrados Alarmes são cancelados Widgets são removidos e Live Wallpapers são substituídos pelo default. Só voltam após o reinício da aplicação home. Em geral, quando ele reiniciar o aparelho A app não volta até a intervenção do usuário ou se estiver inscrita via BroadcastReceiver na Intent do sistema ACTION_EXTERNAL_APPLICATIONS_AVAILABLE 10
  • Mais sobre o Manifest.xmlApps que compartilham o mesmo usuário Cada app roda no Android em seu usuário único e seus recursos não são compartilhados para outros usuários O atributo sharedUserId pode ser usado para definir explicitamente uma string com o UID do usuário Duas apps podem definir o mesmo UID usando este atributo Têm acesso aos mesmos recursos como bases de dados Quando uma app chamar uma Activity de outra, esta segunda só rodará no mesmo processo (compartilhando até o que houver em memória) se tiver o mesmo sharedUserId As duas apps devem ter sido assinadas pelo mesmo certificado O atributo sharedUserString define um rótulo para o usuário 11
  • Mais sobre o Manifest.xmlTag <uses-configuration> Filtram sua aplicação para só funcionar se tais configurações estiverem presentes Notadamente úteis para games com jogabilidade única ou avançada reqTouchScreen - Restringe a determinado tipo de touchscreen undefined, notouch, stylus (requer touchscreen com suporte a caneta) e finger reqKeyboardType - Restringe a deteminado tipo de teclado undefined, nokeys, qwerty (exige um teclado padrão qwerty - com as letras q, w, e, r, t e y na primeira linha) e twelvekey (exige um teclado padrão de simples celulares - números, * e #) 12
  • Mais sobre o Manifest.xmlTag <uses-configuration> reqHardKeyboard - Booleano. Exige ou não presença de teclado físico. Caso preciso de um tipo específico, determine também reqKeyboardType reqNavigation - Restringe à presença de determinado mecanismo de navegação undefined, nonav, dpad (diretional pad), trackball, wheel reqFiveWayNav - Booleano. Exige ou não que o dispositivo tenha recursos de navegação direcional como trackball ou dpad 13
  • Mais sobre o Manifest.xmlTags <uses-feature> Indica que sua aplicação só estará disponível se o hardware tiver determinada característica. Úteis para quando for imprescindível o uso de algum ou alguns recursos não disponíveis em todos os aparelhos O ideal é você nunca precisar citar nada aqui, mas caso necessite é bom restringir para evitar clientes frustrados O Google Play filtra a sua aplicação para só aparecer para quem estiver com hardware compatível com esta tag As características podem ser exigidas ou apenas recomendadas, mas todas as que precisarem de permissão do usuário são, por padrão, consideradas exigidas Para desligar esse filtro de exigência utilize o atributo required=“false” 14
  • Mais sobre o Manifest.xmlTags <uses-feature> Atributos: name - especifica qual o recurso que você precisa. Ex.: android.hardware.bluetooth Podem ser de hardware: Audio, bluetooth, camera, location, microphone, nfc, sensor, screen, telephony, television, touchscreen, usb, wifi Ou sofware: live_wallpaper e sip (voip) Você pode conferir a lista completa aqui: developer.android.com/guide/topics/manifest/uses-feature- element.html#features-reference 15
  • Mais sobre o Manifest.xmlTags <uses-feature> Atributos: required - determina se a característica é apenas uma boa indicação ou se chega a ser uma exigência glEsVersion - informa se há uma recomendação de versão do OpenGL ES (para gráficos). O valor é numérico de 32 bits expresso na base hexa, sendo os 16 primeiros reservados ao maior número da versão e os outros 16 ao menor número. glEsVersion=“0x00020001” - para a versão 2.1 (0002 -> 2 e 0001 ->1) Exemplos: <uses-feature android:name="android.hardware.camera" android:required="false"/> <uses-feature android:glEsVersion="0x00020001" android:required="true" /> 16
  • Mais sobre o Manifest.xmlTags <uses-permission> Declara quais permissões a aplicação vai solicitar do usuário antes de ser instalada Basicamente, todas as operações que implicarem em custos ou questões de segurança precisam ser apresentadas ao clienteTraz apenas o atributo name e a listapossível nele é enorme 17
  • Activity Principal classe para aplicativos que precisam da interação com o usuário Declaração mais básica de uma Activity no manifest Só é <activity android:label="@string/app_name" necessário .Classe por android:name=".MainActivity"> causa do package de </activity> <manifest> Construção fundamental da classe public class MainActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... } } 18
  • Pilhas de Activities As activities são organizadas em pilhas (Last in first out) O estado delas é determinado pela sua posição na pilha Quando uma activity inicia, ela fica ativa no topo da pilha, quando o usuário aciona o botão back, a activity logo abaixo na pilha se torna ativa. 19
  • package br.com.especializa.minhaprimeiraapp;import android.os.Bundle; Código geradoimport android.app.Activity; pelo Hello Worldimport android.view.Menu;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } A tarefa mais básica e comum do método onCreate é carregar alguma View através do método setContentView(). Ele vai instanciar os objetos Java referentes a cada tag desse layout e definir o que será exibido assim que Activity chegar no modo Running @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; }} 20
  • Estados de uma Activity estadosmétodoscallback 21
  • Estados de uma Activity activity iniciada métodos estados chamadosmétodoscallback 21
  • Estados de uma Activity activity iniciada métodos estados chamados activity está ativamétodoscallback 21
  • Estados de uma Activity activity iniciada métodos estados chamados activity está ativa activitymétodos está visível mascallback sem foco 21
  • Estados de uma Activity activity iniciada métodos estados chamados activity está ativa activity está na memória mas não activitymétodos está visível mas está visívelcallback sem foco 21
  • Estados de uma Activity activity iniciada métodos estados chamados activity está ativa activity está na memória mas não activitymétodos está visível mas está visívelcallback sem foco activity está encerrada 21
  • Pilhas de Activities Para garantir que as activities vão reagir às mudanças de estado, o Android provê uma série de métodos de callback manipuladores de eventos Visão geral de todos os métodos do ciclo de vida activity activity onRestoreIntanceState onSaveIntanceState activity activity onResume onPause activity activity onStart onStop activity activityoncreate onDestroy activity onRestart Activity está ativa Activity está visível Tempo de vida completo da Activity 22
  • Métodos de ciclo de vidaonCreate(Bundle) Método principal onde normalmente as coisas são inicializadas Recebe um objeto bundle que empacota dados do estado anterior da ActivityonStart() Método chamado imediatamente antes da Activity ficar visível Seguido de onResume() ou onStop() 23
  • Métodos de ciclo de vidaonResume() Chamado imediatamente antes da activity estar pronta para interagir com o usuário É sempre seguido de onPause()onPause() Método chamado no momento em que o sistema vai resumir outra Activity 24
  • Métodos de ciclo de vidaonStop() Chamado quando a activity não vai ficar mais visível Seguido de onRestart() se outra activity entrou na frente e saiu Seguido de onDestroy() se a activity for ser encerradaonRestart() Chamado quando a activity for voltar a ficar visível, antes do onStart() 25
  • Métodos de ciclo de vidaonDestroy() Chamado quando a activity for encerrar O método isFinishing() retorna true aqui se a activity vai encerrar por que o usuário fechou ou a aplicação chamou o método finish() Retorna false se o sistema resolveu encerrar a activity para liberar espaço em memória 26
  • Logs do aplicativo A classe android.util.Log é útil para enviar informações no desenrolar do aplicativo Toda saída de sistema no Android (stdout e stderr) são direcionados para /dev/null, que significa que o bom e velho System.out.println() não vai funcionar O LogCat captura essas saídas de log e exibe as mensagens em cores diferentes: Código Nível Cor Log.v("categoria", "texto"); Verbose preto Log.d("categoria", "texto"); Debug azul Log.i("categoria", "texto"); Info verde Log.w("categoria", "texto"); Warning laranja Log.e("categoria", "texto"); Error vermelho 27
  • package br.com.especializa.minhaprimeiraapp;import android.os.Bundle;import android.app.Activity;import android.util.Log;public class EstadosActivity extends Activity {! @Override! protected void onCreate(Bundle savedInstanceState) {! ! super.onCreate(savedInstanceState);! ! setContentView(R.layout.activity_estados); Exemplo de Logs para! ! Log.i("LOG DO APLICATIVO", "Passou pelo onCreate"); monitoramento de! } estados! @Override! protected void onStart() {! ! super.onStart();! ! Log.i("LOG DO APLICATIVO", "Passou pelo onStart");! }! @Override! protected void onResume() {! ! super.onResume();! ! Log.i("LOG DO APLICATIVO", "Passou pelo onResume");! }! @Override! protected void onRestart() {! ! super.onRestart();! ! Log.i("LOG DO APLICATIVO", "Passou pelo onRestart");! }! // já deu pra entender né? Crie logs em todos os métodos citados anteriormente} 28
  • LogCat maximizado - DDMS Assim que iniciamos o aplicativo 29
  • LogCat maximizado - DDMS Assim que iniciamos o Encerramos a aplicação aplicativo 29
  • LogCat maximizado - DDMS Desligamos o visor Assim que iniciamos o (entrou a tela inicial), Encerramos a aplicação religamos e só então aplicativo encerramos a app 29
  • Salvando estado da Activity Mesmo quando uma activity é pausada ou parada, seu estado é mantido em memória No entanto, o sistema pode destruir a activity para liberar memória, mesmo sem avisar ao usuário O sistema deverá ser capaz de recriar a activity de modo que retome seu estado original se o usuário quiser retornar a ela Existem métodos callback para lidar com as operação de registro de estado onSaveInstanceState - Chamado quando o sistema vai destruir a activity, mas sabe que precisa restaurar depois Quando o usuário clica em back, ele não é chamado onRestoreInstanceState - Logo antes do usuário solicitar novamente a activity destruída 30
  • Salvando estado da activity 31
  • Salvando estado da activity Objeto Bundle Objeto que empacota um java.util.Map Delega todos os seus métodos (putInt(), putString(), getInt(), getString() ...) Passado aos métodos onSaveInstanceState(), onRestoreInstanceState() e mesmo o onCreate() Através dele podemos salvar dados em onSaveInstanceState() e recuperar esses dados em onRestoreInstanceState() 32
  • ! // Novos métodos em EstadosActivity /**! * Método chamado quando o sistema resolver destruir! * a activity atual em situações onde precisar recuperá-la de volta! */! @Override! protected void onSaveInstanceState(Bundle outState) {! ! outState.putLong("momento", System.currentTimeMillis());! ! super.onSaveInstanceState(outState);! ! Log.i("LOG DO APLICATIVO", "Passou pelo onSaveInstanceState");! }!! /**! * Método chamado quando o sistema recuperar uma activity! * destruída após chamada ao onSaveInstanceState! */! @Override! protected void onRestoreInstanceState(Bundle savedInstanceState) {! ! // TODO Auto-generated method stub! ! super.onRestoreInstanceState(savedInstanceState);! ! Log.i("LOG DO APLICATIVO", "Passou pelo onRestoreInstanceState " +! ! ! ! ! ! ! ! ! (System.currentTimeMillis() -! ! ! ! ! ! ! ! ! savedInstanceState.getLong("momento")) +! ! ! ! ! ! ! ! ! "ms depois do onSaveInstanceState");! } 33
  • Salvando estado da activity Iniciamos a aplicação, o onRestoreInstanceState não foi chamado 34
  • Salvando estado da activity O visor Iniciamos a esmaeceu após um aplicação, o tempo. onRestoreInstanceState onSaveInstanceState não foi chamado foi chamado 34
  • Salvando estado da activity Desbloqueamos a tela O visor Iniciamos a reexibindo aapós um esmaeceu aplicação. aplicação, o onRestoreInstanceState ainda tempo. onRestoreInstanceState a não foi chamado porque onSaveInstanceState activityfoi chamado não não havia sido foi chamado destruída 34
  • Salvando estado da activity Clicamos no back Desbloqueamos a tela O visor Iniciamosaaaplicacão. para encerra reexibindo aapós um esmaeceu aplicação. Como a activityo aplicação, não ainda onRestoreInstanceState é mais tempo. onRestoreInstanceState a necessária, não foi chamado porque onSaveInstanceState activityfoi chamado não não havia sido onSaveInstanceInstate foi chamado não foi chamado destruída 34
  • Salvando estado da activity Iniciamos a aplicação e rotacionamos visor noa tela Desbloqueamos back Clicamos O Iniciamosaaaplicacão. para encerra o aparelho. Esse éreexibindo aapós um um caso aplicação. esmaeceu em que o sistema Como a activityo aplicação, não ainda onRestoreInstanceState é mais sempre tempo. onRestoreInstanceState a não foi necessária, destrói e reconstrói achamado porque onSaveInstanceState activity activityfoi chamado não não havia sido onSaveInstanceInstate foi chamado não foi chamado destruída 34
  • Salvando estado da activity Curiosidade. Iniciamos a Quando a tela esmaece, e rotacionamos visor noa tela aplicação Desbloqueamos back Clicamos O Iniciamosaaaplicacão. para encerra a orientação da tela volta ao Esse éreexibindo aapós um o aparelho. um caso aplicação. esmaeceu estado inicial. Confiraque o sistema Como a activityo em os aplicação, não ainda onRestoreInstanceState é mais sempre tempo. onRestoreInstanceState a não foi necessária, métodos sendodestrói e reconstrói achamado porque onSaveInstanceState chamados activity activityfoi chamado não não havia sido onSaveInstanceInstate foi chamado não foi chamado destruída Voltaremos a este assunto na aula 6 ao falarmos mais sobre interfaces 34
  • Activity subclassesExemplos de subclasses: ListActivity - Activity que carrega ListViews para exibir coleções ExpandableListActivity - Activity que carrega ExpandableListViews TabActivity - Apresenta views em abas. Foi depreciada na API 13, em função dos fragments Aplicativos compilados com o extra Android Support Library poderão contar com FragmentActivity Trataremos deste assunto em Fragments Aplicativos compilados com a GoogleAPIs terão MapActivity Esse assunto será visto só em outro curso 35
  • ListActivity Classe que empacota um ListView sem precisarmos escrever nenhum arquivo de layout Exibe uma lista vertical de itens, quando não couberem na tela, carrega uma barra de rolagem É uma Activity com alguns métodos para gerenciamento de listas Para preencher a lista, passamos um objeto de uma classe que herde de ListAdapter Vamos trabalhar agora com ArrayAdapter e em assuntos posteriores com SimpleCursorAdapter 36
  • Activity subclasses Como não vamos criar uma view, vamos criar a Activity de outro jeito No Manifest, vá na aba Application e clique em add Mande criar uma Activity Em Attributes for Activity, clique em name para mandar gerar uma nova classe e preencha os demais atributos. É bem intuitivo. 37
  • package br.com.especializa.minhaprimeiraapp;import android.app.ListActivity;import android.os.Bundle;import android.widget.ArrayAdapter;/** * Devemos herdar de ListActivity */public class MinhaListaActivity extends ListActivity {! @Override! public void onCreate(Bundle savedInstanceState) {! super.onCreate(savedInstanceState);! // Valores que vão preencher a lista! String[] instrumentos = {"violão", "guitarra", "bateria", "gaita",! ! ! ! ! ! ! "microfone", "cajon", "bandolim", "congas",! ! ! ! ! ! ! "violino", "piano", "contra-baixo", "panela"};! // ArrayAdapter que vai saber fornecer cada item ao ListView! // context - this (toda Activity é um contexto)! // android.R.layout.simple_item_1 - componente visual de cada linha! // objetos - instrumentos - coleção de dados! ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,! ! ! ! ! ! ! ! android.R.layout.simple_list_item_1,! ! ! ! ! ! ! ! instrumentos);! // Método que define o adapter do ListView! setListAdapter(adapter);! }} 38
  • package br.com.especializa.minhaprimeiraapp;import android.app.ListActivity;import android.os.Bundle;import android.widget.ArrayAdapter;/** * Devemos herdar de ListActivity */public class MinhaListaActivity extends ListActivity {! @Override! public void onCreate(Bundle savedInstanceState) {! super.onCreate(savedInstanceState);! // Valores que vão preencher a lista! String[] instrumentos = {"violão", "guitarra", "bateria", "gaita",! ! ! ! Existe uma classe R padrão ! ! ! "microfone", "cajon", "bandolim", "congas",! ! ! !do Android.! referencia todos ! ! Ela "violino", "piano", "contra-baixo", "panela"}; os componentes que podemos! // ArrayAdapter que vai saber fornecer cada item ao ListView trabalhar! // context - this (toda Activity é um contexto)! // android.R.layout.simple_item_1 - componente visual de cada linha! // objetos - instrumentos - coleção de dados! ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,! ! ! ! ! ! ! ! android.R.layout.simple_list_item_1,! ! ! ! ! ! ! ! instrumentos);! // Método que define o adapter do ListView! setListAdapter(adapter);! }} 38
  • package br.com.especializa.minhaprimeiraapp;import android.app.ListActivity;import android.os.Bundle;import android.widget.ArrayAdapter;/** * Devemos herdar de ListActivity */public class MinhaListaActivity extends ListActivity {! @Override! public void onCreate(Bundle savedInstanceState) {! super.onCreate(savedInstanceState);! // Valores que vão preencher a lista! String[] instrumentos = {"violão", "guitarra", "bateria", "gaita",! ! ! ! Existe uma classe R padrão ! ! ! "microfone", "cajon", "bandolim", "congas",! ! ! !do Android.! referencia todos ! ! Ela "violino", "piano", "contra-baixo", "panela"}; os componentes que podemos! // ArrayAdapter que vai saber fornecer cada item ao ListView trabalhar! // context - this (toda Activity é um contexto)! // android.R.layout.simple_item_1 - componente visual de cada linha! // objetos - instrumentos - coleção de dados! ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,! ! ! ! ! ! ! ! android.R.layout.simple_list_item_1,! ! ! ! ! ! ! ! instrumentos);! // Método que define o adapter do ListView! setListAdapter(adapter);! }} 38
  • ListAdaptersComo vimos, servem para realizar o bind entre umaview e uma coleção de valoresArrayAdapter Carrega coleções arrays ou Lists em telas ListViewCursorAdapter Listas maiores ou mais complexas precisam de um adapter mais inteligente do que o ArrayAdapter CursorAdapters unem cursores (objetos que gerenciam eficientemente coleções em buffers) e listviews Voltaremos a esse assunto quando fizermos consultas a bancos de dados 39
  • FragmentsSão porções de tela por baixo de uma Activity É possível combinar mais de um Fragment numa telaDisponível desde a API 11 (Honeycomb) É possível decidir mostrar várias fragments em telas maiores (tablets) e continar usando navegação por activities (handsets)Disponível para APIs mais antigas (a partir da 4) atravésda Android Support Library No SDK Manager, vá aos extras e baixe esse pacote Seus próximos projetos já vão ser gerados com a inserção da dependência android-support-v4.jar 40
  • Navegação em handsets 41
  • Navegação em tablets 42
  • ?Que tal começar por um exemplo do zero? 43
  • Exemplo de Fragments1.Crie uma nova Activity 1.1.Defina o nome FragmentsActivity.java. Por enquanto não vamos mudar o conteúdo padrão dela 1.2.Renomeie a view gerada para fragment_dois_lados.xml2.Crie mais duas views 2.1.File > New > Other, depois Android > Android XML Layout File 2.2.Nomes: fragment_esquerda.xml e fragment_direita.xml3.Crie duas classes Java no pacote src 3.1.FragmentEsquerda.java e FragmentDireita.java 3.2.Elas devem herdar de android.support.v4.app.Fragment 44
  • View principal do fragment_dois_lados.xml exemplo. Carrega um layout em linha com dois elementos<?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="horizontal">! <fragment! ! android:name="br.com.especializa.minhaprimeiraapp.FragmentEsquerda"! ! android:id="@+id/fragmentEsquerda"! ! android:layout_weight="1"! ! android:layout_width="0px"! ! android:layout_height="match_parent" />! <fragment! ! android:name="br.com.especializa.minhaprimeiraapp.FragmentDireita"! ! android:id="@+id/fragmentDireita"! ! android:layout_weight="1"! ! android:layout_width="0px" Tags! ! android:layout_height="match_parent" /> fragment indicam</LinearLayout> no atributo name o nome da classe controladora 45
  • fragment_esquerda.xml Seu conteúdo é irrelevante no momento<?xml version="1.0" encoding="utf-8"?><LinearLayout! xmlns:android="http://schemas.android.com/apk/res/android"! android:orientation="vertical"! android:layout_width="fill_parent"! android:layout_height="fill_parent" Mudamos a cor! android:background="#00FF00"> do background só pra! <TextView ficar destacar mais o! ! android:layout_width="fill_parent" exemplo! ! android:layout_height="wrap_content"! ! android:text="Fragmento da esquerda"! ! android:textColor="#000000"! ! android:textSize="25sp" /></LinearLayout> fragment_direita.xml Pode ter um conteúdo semelhante. Só altere a cor do fundo 46
  • package br.com.especializa.minhaprimeiraapp;import android.os.Bundle; Vamos herdar deimport android.support.v4.app.Fragment; Fragment da supportimport android.view.LayoutInflater; APIimport android.view.View;import android.view.ViewGroup;public class FragmentEsquerda extends Fragment {! @Override! public View onCreateView(LayoutInflater inflater, ViewGroup container,! ! ! Bundle savedInstanceState) {! ! // LayoutInflater é um objeto com a capacidade de ler um arquivo XML,! ! // criar os objetos Java referentes a cada componente escrito lá! ! // e exibi-lo em algum lugar.! ! // Até então nós só havíamos conseguido isso com o setContentView()! ! // do onCreate da Activity.! ! // Que por sua vez carrega sempre na tela como um todo! ! return inflater.inflate(R.layout.fragment_esquerda, container, false);! }} No exemplo, Método callback do Chamada que FragmentDireita.java momento em que a view carrega a “sub” view deve ter a mesma principal for criada referenciada em R composição 47
  • Como tudo aconteceu? FragmentsActivity.java setContentView(R.layout.fragment_dois_lados) Carregou a view principal fragment_dois_lados.xml Tags <fragment> Cada tag carregou uma classe Fragment FragmentEsquerda.java FragmentDireita.java inflater.inflate() inflater.inflate()Carregou fragment_esquerda.xml Carregou fragment_direita.xml fragment_esquerda.xml fragment_direita.xml Simples arquivo de layout Simples arquivo de layout 48
  • O que ganhamos com isso? Telas maiores exibem mais informações Imagine A navegação não uma única Activity descarrega a tela para controlar todos os anterior seus eventos Cada Fragment controla a sua porção de tela 49
  • No tablet, o resultado foi bom 50
  • Mas no smartphone... 51
  • FragmentsPodemos detectar de alguma forma que a tela égrande e só então exibir dois fragmentsSe a tela for menor, exibiremos apenas um fragment Este fragment irá abrir outra Activity com o segundo fragment dentro1. Crie um novo arquivo XML de layout 1.1.Chame-o de fragment_um_lado.xml2. Altere a Activity principal para escolher entre ele ou o de dois lados 52
  • Um ou dois fragments FragmentsActivity.java OU setContentViewfragment_um_lado.xml fragment_dois_lados.xmlFragmentEsquerda.java FragmentDireita.javafragment_esquerda.xml fragment_direita.xml 53
  • fragment_um_lado.xml Apenas um fragment<?xml version="1.0" encoding="utf-8"?><fragment xmlns:android="http://schemas.android.com/apk/res/android"! android:name="br.com.especializa.minhaprimeiraapp.FragmentEsquerda"! android:id="@+id/fragmentEsquerda"! android:layout_width="match_parent"! android:layout_height="match_parent" /> 54
  • 1. @Override2. protected void onCreate(Bundle savedInstanceState) {3. super.onCreate(savedInstanceState);4. boolean doisPaineis = false;5.6. // Verificamos se a tela é padrão XLARGE7. if ((getResources().getConfiguration().screenLayout8. & Configuration.SCREENLAYOUT_SIZE_XLARGE)9. ! == Configuration.SCREENLAYOUT_SIZE_XLARGE) {10.11. ! Toast.makeText(this, "XLARGE", Toast.LENGTH_LONG).show();12. ! doisPaineis = true;13.14. // Verificamos se a tela é padrão LARGE15. } else if ((getResources().getConfiguration().screenLayout &16. Configuration.SCREENLAYOUT_SIZE_LARGE)17. ! == Configuration.SCREENLAYOUT_SIZE_LARGE) {18.19. ! Toast.makeText(this, "LARGE", Toast.LENGTH_LONG).show();20. ! doisPaineis = true;21.22. }23.24. if (doisPaineis) {25. setContentView(R.layout.fragment_dois_lados);26. } else {27. setContentView(R.layout.fragment_um_lado);28. }29. } 55
  • FragmentsNas linhas 7 e 15 getResources() retornou o objeto Resources a partir do qual se obtém dados dos recursos do dispositivo getConfiguration() retornou dados da configuração corrente screenLayout trouxe uma máscara de bits sobre o tamanho da tela Perguntamos se a máscara de bits casa com o padrão XLARGE ou LARGE Nesses casos, e só nesses casos, doisPaineis virou true E chamamos fragments_dois_lados 56
  • FragmentsComo vamos exibir o layout fragment_direita.xml?Ele deverá vir a partir de uma nova Activity Esta nova Activity não vai controlar a view do fragment Essa tarefa já ficou a cargo da classe DireitaFragment.java1. Vamos criar um botão em fragment_esquerda.xml2. Implementar o evento de clique no EsquerdaFragment.java 2.1. Será feito no novo método callback onActivityCreate()3. Criar a nova Activity chamada DireitaFragmentActivity.java 57
  • Exemplo completo Activity1 Activity2 FragmentsActivity.java FragmentDireitaActivity.java OU setContentViewfragment_um_lado.xml fragment_dois_lados.xml FragmentManager FragmentTransactionFragmentEsquerda.java FragmentDireita.javafragment_esquerda.xml fragment_direita.xml click no botão 58
  • <?xml version="1.0" encoding="utf-8"?><LinearLayout! xmlns:android="http://schemas.android.com/apk/res/android"! android:orientation="vertical"! android:layout_width="fill_parent"! android:layout_height="fill_parent"! android:background="#00FF00">! <TextView! ! android:layout_width="fill_parent"! ! android:layout_height="wrap_content"! ! android:text="Fragmento da esquerda"! ! android:textColor="#000000" Novo botão em! ! android:textSize="25sp" /> fragment_esquerda.xml! <Button! android:id="@+id/btnChamarDireita"! android:layout_width="wrap_content"! android:layout_height="wrap_content"! android:text="Chamar direita" /></LinearLayout> 59
  • Novo método em getActivity() recupera a FragmentEsquerda.java Activity associada ao Fragment@Overridepublic void onActivityCreated(Bundle savedInstanceState) {! super.onActivityCreated(savedInstanceState);!! Button b = (Button) getActivity().findViewById(R.id.btnChamarDireita);! b.setOnClickListener(new View.OnClickListener() {! !! ! @Override! ! public void onClick(View v) {! ! ! if (getActivity().findViewById(R.id.fragmentDireita) == null) {! ! ! ! Intent i = new Intent(getActivity(), FragmentDireitaActivity.class);! ! ! ! getActivity().startActivity(i);! ! ! }! ! }! });!} A chamada à próxima Activity precisa da criação de Intents. Assunto da próxima aula 60
  • package br.com.especializa.minhaprimeiraapp;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;public class FragmentDireitaActivity extends FragmentActivity {! @Override! protected void onCreate(Bundle savedInstanceState) {! ! super.onCreate(savedInstanceState); Novo objeto em! ! Fragment fragment = new FragmentDireita(); FragmentDireita que vai controlar a view. O papel desta! ! getSupportFragmentManager().beginTransaction() Activity é apenas criá-lo! ! .add(android.R.id.content, fragment).commit();! !! }} - getSupportFragmentManager() retorna o objeto FragmentManager. - Seu método beginTransation() é quem adiciona, remove ou substitui fragments ao layout da Activity atual - android.R.id.content referencia a raiz de elementos da View - commit() realiza a operação 61
  • O ciclo de vida do Fragmenté parecido e vinculado ao deuma Activity Se a Activity parar, seus fragments também param. Se for destruída, eles também serão onAttach(Activity) Chamado assim que o fragment for anexado a uma Activity. Ela é passada como parâmetro onCreate(Bundle) Semelhante ao da Activity. É chamado para fazer suas inicializações 62
  • onCreateView(LayoutInflater,ViewGroup, Bundle) O método mais usado em um Fragment representa o momento exato em que ele cria sua interface com o usuário Recebe o inflater que vai carregar a view, o ViewGroup que servirá de container e o mesmo bundle do onCreateonActivityCreated(Bundle) Chamado logo depois da Activity ser criada Como Fragments não herdam de Context, precisam sempre chamar a Activity para conseguir realizar algumas operações de conteúdo Lembra do Toast, por exemplo? A partir daqui getActivity() não retorna nulo 63
  • onStart() Chamado logo quando o Fragment estiver visívelonResume() Chamado logo quando ele assumir interatividade com o usuárioonPause() Chamado assim que ele perder a interatividadeonStop() Chamado assim que a Activity não estiver mais visível 64
  • onDestroyView(LayoutInflater,ViewGroup, Bundle) Método parecido com o onCreateView() Roda no momento em que a view carregada nele for destruídaonDestroy() Roda assim que o fragment não tiver mais serventiaonDetach() Roda quando não estiver mais anexado a uma Activity 65
  • Fragment subclassesHá duas versões de Fragments Elas possuem estruturas hierárquicas diferentes android.app.Fragment Classe adicionada na API 11 (honeycomb) justamente no momento da ascensão dos tablets Herdada por DialogFragment, ListFragment, PreferenceFragment e WebViewFragment android.support.v4.app.Fragment Classe da API Android Suppor V4, que é o extra que porta os fragments lá pra trás na API 4 (Donut - 1.6) Herdada apenas por DialogFragment e ListFragment sendo as respectivas classes criadas neste mesmo pacote Não são as mesmas do pacote principal 66
  • Suporte a APIs antigasApps com Fragments compatíveis com APIs antigas: Os fragments devem ser android.support.v4.app.Fragment As activities que anexam fragments devem herdar de android.support.v4.app.FragmentActivity Nelas, o objeto FragmentManager deve ser o do pacote android.support.v4.app, chamado exclusivamente por getSupportFragmentManager(), um método com função semelhante ao getFragmentManager() ListFragments e DialogFragments só podem ser do mesmo pacote da API de suporteAPIs v7 e v13 São supersets da v4 e trazem mais coisas, mas requerem minSdkVersion 7 e 13 respectivamente 67
  • ? Vamos analisar ocódigo gerado peloMasterDetailFlow 68
  • Esta foi a Activity principal<!-- Trecho no AndroidManifest.xml referente ao MasterDetailFlow que criamos --><activity android:name="br.com.especializa.minhaprimeiraapp.ProdutoListActivity" android:label="@string/title_produto_list" > <intent-filter> <action android:name="android.intent.action.MAIN" /> A segunda Activity <category android:name="android.intent.category.LAUNCHER" /> para quando a tela for </intent-filter> menor</activity><activity android:name="br.com.especializa.minhaprimeiraapp.ProdutoDetailActivity" android:label="@string/title_produto_detail" android:parentActivityName=".ProdutoListActivity" > <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".ProdutoListActivity" /> Atributo criado no Jelly</activity> Bean 4.1 (API 16) Versão anterior à da API 16 para a mesma idéia 69
  • Navegação UpA API 11 trouxe também as ActionBars e com elas, ochamado Up buttonAs declarações do AndroidManifest definiram a Activitya ser chamada quando este botão for acionado <meta name="android.support.PARENT_ACTIVITY"> Para APIs anteriores à 16 android:parentActivityName="" Para versões posteriores 70
  • Navegação Up e Back Up button disponível em telas internas Back button de sempre 71
  • package br.com.especializa.minhaprimeiraapp;import android.content.Intent;import android.os.Bundle;import android.support.v4.app.FragmentActivity;public class ProdutoListActivity extends FragmentActivity implements Interface! ! ProdutoListFragment.Callbacks { criada pelo próprio exemplo! private boolean mTwoPane;! @Override! protected void onCreate(Bundle savedInstanceState) {! ! super.onCreate(savedInstanceState);! ! // Layout que só carrega um único Fragment! ! // Vai ser trocado por outro usando um técnica bem legal! ! setContentView(R.layout.activity_produto_list);! ! // De cara, parace que nunca vai entrar nesse if! ! if (findViewById(R.id.produto_detail_container) != null) {! ! ! // Se entrar, essa variável vira true! ! ! mTwoPane = true; O estilo do ícone vai! ! ! ((ProdutoListFragment) getSupportFragmentManager() permanecer! ! ! ! ! .findFragmentById(R.id.produto_list)) clicado! ! ! ! ! .setActivateOnItemClick(true);! ! }! }! // continua ... 72
  • ! // Método que a interface criada exigiu que fosse implementado // O fragment controlador da lista vai invocá-lo de volta (Callback)! @Override! public void onItemSelected(String id) {! ! if (mTwoPane) {! ! ! // Em tela dupla (tablets), vamos criar um Bundle // para armazenar o id do produto clicado! ! ! Bundle arguments = new Bundle();! ! ! arguments.putString(ProdutoDetailFragment.ARG_ITEM_ID, id);! ! ! ProdutoDetailFragment fragment = new ProdutoDetailFragment();! ! ! fragment.setArguments(arguments); // Método que registra o bundle no Fragment // Substituindo o fragment de detalhes que estiver carregado por outro atualizado! ! ! getSupportFragmentManager().beginTransaction()! ! ! ! ! .replace(R.id.produto_detail_container, fragment).commit();! ! } else {! ! ! // Em telas simples, haverá uma chamada à nova Activity que vai! ! ! // receber no pacote o id do produto clicado // ... calma que ainda veremos Intents! ! ! Intent detailIntent = new Intent(this, ProdutoDetailActivity.class);! ! ! detailIntent.putExtra(ProdutoDetailFragment.ARG_ITEM_ID, id);! ! ! startActivity(detailIntent);! ! }! }} 73
  • activity_produto_list.xml Apenas um fragment gerado<fragment xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/produto_list" android:name="br.com.especializa.minhaprimeiraapp.ProdutoListFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" tools:context=".ProdutoListActivity" tools:layout="@android:layout/list_content" /> Tablets, que possuem telas grandes e APIs >= 11, vão sobrescrever a referência de<resources> R ao layout de um fragment <item name="activity_produto_list" type="layout"> pelo de dois @layout/activity_produto_twopane </item></resources> refs.xml em values-large Fez sentido o if (nomenclatura antiga) e (mTwoPane) da values-sw600dp (nova) Activity? 74
  • <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:divider="?android:attr/dividerHorizontal" android:orientation="horizontal" android:showDividers="middle" tools:context=".ProdutoListActivity" > <fragment android:id="@+id/produto_list" android:name="br.com.especializa.minhaprimeiraapp.ProdutoListFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" tools:layout="@android:layout/list_content" /> activity_produto_twopane.xml <FrameLayout android:id="@+id/produto_detail_container" carregando um fragment android:layout_width="0dp" produto_list e um outro componente android:layout_height="match_parent" produto_detail_container android:layout_weight="3" /></LinearLayout> 75
  • ListFragment da API de suportepublic class ProdutoListFragment extends ListFragment {! private static final String STATE_ACTIVATED_POSITION = "activated_position";! private Callbacks mCallbacks = sDummyCallbacks;! private int mActivatedPosition = ListView.INVALID_POSITION; Representa! /** posição inválida do! * Interface interna que a Activity principal implementou toque no item! */! public interface Callbacks {! ! /**! ! * Método implementado pela Activity principal! ! */! ! public void onItemSelected(String id);! }! @Override Lembra do! public void onCreate(Bundle savedInstanceState) {! ! super.onCreate(savedInstanceState); ArrayAdapter?! ! // TODO: replace with a real list adapter.! ! setListAdapter(new ArrayAdapter<DummyContent.DummyItem>(getActivity(),! ! ! ! android.R.layout.simple_list_item_activated_1,! ! ! ! android.R.id.text1, DummyContent.ITEMS));! } // continua ... 76
  • Assim que a view for criada. Ela é recriada em rotações! @Override! public void onViewCreated(View view, Bundle savedInstanceState) {! ! super.onViewCreated(view, savedInstanceState);! ! // Recuperando um possível valor de item selecionado! ! if (savedInstanceState != null! ! ! ! && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {! ! ! setActivatedPosition(savedInstanceState! ! ! ! ! .getInt(STATE_ACTIVATED_POSITION));! ! }! } Frescurinha! @Override particular do código! public void onAttach(Activity activity) { gerado! ! super.onAttach(activity);! ! // Activities containing this fragment must implement its callbacks.! ! if (!(activity instanceof Callbacks)) {! ! ! throw new IllegalStateException(! ! ! ! ! "Activity must implement fragments callbacks.");! ! }! ! mCallbacks = (Callbacks) activity;! } // Continua ... 77
  • ! @Override Quando o item for! public void onDetach() {! ! super.onDetach(); selecionado, chama o! ! mCallbacks = sDummyCallbacks; callback da activity! }! @Override! public void onListItemClick(ListView listView, View view, int position,! ! ! long id) {! ! super.onListItemClick(listView, view, position, id);! ! mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);! }! @Override! public void onSaveInstanceState(Bundle outState) {! ! super.onSaveInstanceState(outState);! ! if (mActivatedPosition != ListView.INVALID_POSITION) {! ! ! // Serialize and persist the activated item position.! ! ! outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);! ! }! } // Continua ... Salvando o item selecionado 78
  • ! public void setActivateOnItemClick(boolean activateOnItemClick) {! ! // When setting CHOICE_MODE_SINGLE, ListView will automatically! ! // give items the activated state when touched.! ! getListView().setChoiceMode( Redefinição! ! ! ! activateOnItemClick ? ListView.CHOICE_MODE_SINGLE! ! ! ! ! ! : ListView.CHOICE_MODE_NONE); inusitada de métodos! } sobre a marcação de itens selecionados! private void setActivatedPosition(int position) {! ! if (position == ListView.INVALID_POSITION) {! ! ! getListView().setItemChecked(mActivatedPosition, false);! ! } else {! ! ! getListView().setItemChecked(position, true);! ! }! ! mActivatedPosition = position;! }} 79
  • /** * Activity de detalhes para hansets */public class ProdutoDetailActivity extends FragmentActivity {! @Override Carregou a view! protected void onCreate(Bundle savedInstanceState) {! ! super.onCreate(savedInstanceState); porque não houve um! ! setContentView(R.layout.activity_produto_detail); fragment da direita no exemplo! ! // Exibindo o Up button! ! getActionBar().setDisplayHomeAsUpEnabled(true);! ! if (savedInstanceState == null) {! ! ! // Criando o fragment da direita! ! ! Bundle arguments = new Bundle();! ! ! arguments.putString(ProdutoDetailFragment.ARG_ITEM_ID, getIntent()! ! ! ! ! .getStringExtra(ProdutoDetailFragment.ARG_ITEM_ID));! ! ! ProdutoDetailFragment fragment = new ProdutoDetailFragment();! ! ! fragment.setArguments(arguments);! ! ! getSupportFragmentManager().beginTransaction()! ! ! ! ! .add(R.id.produto_detail_container, fragment).commit();! ! }! }! @Override! public boolean onOptionsItemSelected(MenuItem item) { Callback do evento! ! switch (item.getItemId()) { de clique no botão! ! case android.R.id.home: options do Android! ! ! NavUtils.navigateUpTo(this, new Intent(this,! ! ! ! ! ProdutoListActivity.class));! ! ! return true;! ! }! ! return super.onOptionsItemSelected(item);! }} 80
  • ?Que tal fazer um ListFragment do zero? 81