Introdução
Link oficial sobre Fragments no site Android Developer: http://developer.android.com/guide/components/fragments.html
O Fragment é uma das grandes novidades da API do Android, que surgiu após a versão Android 3.0 HoneyComb, graças a chegada dos tablets no mercado.
Como o próprio nome sugere, Fragment pode ser definido como um fragmento de uma tela em um aplicativo Android.
Obs: Entenda tela como um Layout XML (View) vinculado a uma Activity (Controller). Se esta com dificuldades em entender esses termos leia este post
Por ser um “pedaço” de uma tela, podemos utilizar o Fragment em vários locais, esta reutilização de funcionalidades o torna uma estrutura muito poderosa.
É como se fosse uma mini Activity, com seu próprio ciclo de vida.
Outro problema bem comum que essa estrutura veio para resolver é o de manter uma boa experiência de Interface gráfica em todos os dispositivos Android, independente do tamanho da tela.
Vamos a um exemplo para entender este problema:
Imagine um aplicativo de notícias, que tem como requisito rodar bem em Smartphones e Tablets. Basicamente, o app conta com uma lista de nomes de notícias, que ao ser clicada mostrará uma tela com a notícia completa. Em um smartphone a melhor maneira de atender esta situação é ter uma Lista em uma tela, e depois dessa lista ser clicada o usuário seria direcionado para a tela de detalhes. Já em um tablet, a melhor maneira seria exibir em uma mesma tela, a lista e o detalhes de uma notícia selecionada juntos. Veja o esboço do layout dessas duas situações:
Formas de resolver este problema
Sem os Fragments, você teria que preparar um layout para cada esquema de tela (Tablet e Smartphone), até ai tudo bem.
Você também deveria ter uma Activity, que teria que realizar varias comparações para saber se o app esta sendo executado em um tablet ou em um smartphone, para assim saber como montar a tela ou saber como proceder quando um item for clicado.
No final das contas teria uma Activity de código grande e de difícil manutenção. Usando Fragment para resolver esse problema. Você teria um Fragment que conseguiria listar o titulo das notícias. E outro que conseguiria exibir os detalhes da notícia clicada.
Como resultado sua Activity ficaria muito mais leve, uma vez que as responsabilidades de exibir lista e mostrar detalhes foram delegadas para dois Fragments, e não ficará apenas em uma Activity.
Eventualmente, ainda pode existir validações pra saber se o app esta rodando em tablet ou smartphone para o aplicativo saber proceder da melhor maneira em alguma determinada situação. Porém essas validações seriam menos comuns do que no caso anterior onde não utilizamos Fragment.
Exemplo prático
O primeiro exemplo que utilizaremos para entender como utilizar Fragments, será um caso mais simples do que o esboçado logo acima. Mas também muito encontrado no universo do desenvolvimento para dispositivos móveis.
Imagine um cenário onde você tenha que desenvolver um aplicativo que tenha muitas telas, sendo que em cada tela exista um espaço de propaganda. Essa propaganda consiste em uma descrição de um site e um Button que ao ser clicado redirecionará o usuário para uma URL alvo da propaganda. Podemos resolver esse problema criando um Fragment que tem a responsabilidade de exibir a View da propaganda e tratar o comportamento dos componentes nela apresentados, no caso o Button.
Chamaremos esse Fragment de FragmentPropaganda. Podemos observar o código dele logo abaixo:
public class FragmentPropaganda extends Fragment { private static final String URL = "http://timespender.com/"; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.layout_fragment, container); Button buttonCliqueAqui = (Button) view.findViewById(R.id.button_clique_aqui); buttonCliqueAqui.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { irParaSite(); } }); return view; } private void irParaSite() { Uri uriVideo = Uri.parse(URL); Intent intent = new Intent(Intent.ACTION_VIEW, uriVideo); startActivity(intent); } }
Obs: O Fragment que utilizei é o android.support.v4.app.Fragment, ou seja pertence a library android-support-v4.jar. Essa biblioteca foi disponibilidade para que possamos utilizar diversos recursos como o Fragments em versões do Android Abaixo da 3.0. Conforme foi explicado no início do artigo, o Fragment é como se fosse uma mini Activity. Tal como a Activity, o Fragment possui um ciclo de vida, na imagem abaixo você poderá ver este ciclo do Fragment:
Assim como a Activity tem o método onCreate(), que é responsável pela criação da Activity, no Fragment temos o onCreateView(), que também representa o local onde será criado o Fragment. É la que vincularemos o Fragment a um layout XML, após isso podemos colocar comportamento nas Views, tal como foi feito no botão.
Neste exemplo, vinculei o meu Fragment ao layout layout_fragment, podemos vê-lo logo abaixo:
<!--?<span class="hiddenSpellError" pre="" data-mce-bogus="1"-->xml version="1.0" encoding="utf-8"?> <xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:gravity="center" > <TextView android:layout_weight="1" android:textSize="20sp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/propaganda" /> <Button android:layout_weight="0" android:id="@+id/button_clique_aqui" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/clique_aqui" /> </LinearLayout>
Podemos ver que é um layout bem simples, apenas um TextView que faz uma descrição do site que estamos anunciando, e um botão que abrirá o browser com o site alvo. Logo abaixo, segue o arquivo Strings.xml deste projeto:
<!--?<span class="hiddenSpellError" pre="" data-mce-bogus="1"-->xml version="1.0" encoding="utf-8"?> <resources> name="app_name">Fragments name="action_settings">Settings name="hello_world">Hello world! name="propaganda">Conheça o TimeSpender, programa-se ao ver videos! name="clique_aqui">Clique Aqui! name="layout_tela_um">Layout da tela UM name="layout_tela_dois">Layout da tela DOIS name="ir_para_tela_dois">Ir para a tela DOIS </resources>
Bom, nesse momento temos um Fragment funcional, pronto para ser utilizado em qualquer Activity do nosso projeto. É isso que devemos fazer. Crie em seu projeto uma Activity chamada ActivityPropagandaUm. Ela terá o seguinte código:
public class ActivityPropagandaUm extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_activity_um); } public void onClickTelaDois(View view) { Intent intent = new Intent(this, ActivityPropagandaDois.class); startActivity(intent); } }
Três coisas devem ser ressaltadas:
– Estamos herdando da classe FragmentActivity e não diretamente da classe Activity do Android.Se tiver trabalhando com Fragment dentro de uma Activity, lembre-se sempre de herdar FragmentActivity, esquecer isso é um erro comum.
– Criamos um método onClickTelaDois. Este método esta vinculado ao botão informado no layout XML, R.layout.layout_activity_um. Ele simplesmente chama a Activity ActivityPropagandaDois. Criaremos essa classe mais a frente nesse artigo.
– Estamos vinculando a nossa Activity ao layout layout_activity_um, o nosso Fragment foi declarado dentro deste XML, ou seja, fizemos um vinculo com a funcionalidade de propaganda sem usar código java.
Veja como o código ficou simples de ser analisado, este é um benefício de se usar Fragment.
Analise logo abaixo o layout layout_activity_um:
<xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/layout_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:gravity="center" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" > <TextView android:textSize="22dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/layout_tela_um" /> <Button android:text="@string/ir_para_tela_dois" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onClickTelaDois" /> </LinearLayout> <LinearLayout android:layout_gravity="bottom" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <fragment android:layout_margin="2dp" android:layout_width="match_parent" android:layout_height="wrap_content" class="com.example.tudofragment.FragmentPropaganda" /> </LinearLayout> </LinearLayout>
Se trata de um layout muito simples, com um TextView indicando qual Activity o usuário esta, e um botão para muda-lo de Activity. O ponto que queremos chamar a atenção esta mais embaixo, assim como declaramos qualquer View também declaramos um Fragment. A única particularidade é o atributo class=”com.example.tudofragment.FragmentPropaganda”, é nessa tag que informamos a classe do Fragment que queremos utilizar.
No final das contas teremos a seguinte tela a nossa disposição:
Para deixar o projeto ainda mais flexível, vamos criar um outro layout XML que encapsulará o nosso Fragment, o chamaremos de layout_propaganda, e ficará desse jeito:
<!--?<span class="hiddenSpellError" pre="" data-mce-bogus="1"-->xml version="1.0" encoding="utf-8"?> <xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <fragment android:layout_margin="2dp" android:layout_width="match_parent" android:layout_height="wrap_content" class="com.example.tudofragment.FragmentPropaganda" /> </LinearLayout> Após a criação deste layout, vamos vincula-lo ao layout da nossa <strong>Activity</strong>, ao invés de apontar para o <strong>Fragment</strong> direto, fazemos isso usando a tag <strong>include</strong>. Que nos possibilita incluir um layout XML dentro do outro. É um ótimo recurso para ajudar a reutilizar layouts ente <strong>Activitys</strong>. Nosso <em>layout_activity_um</em> ficará desse jeito: <xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/layout_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:gravity="center" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" > <TextView android:textSize="22dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/layout_tela_um" /> <Button android:text="@string/ir_para_tela_dois" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onClickTelaDois" /> </LinearLayout> <include android:layout_gravity="bottom" layout="@layout/layout_propaganda"/> </LinearLayout>
Para concluir nosso exemplo, crie uma outra Activity e a chame de ActivityPropagandaDois. Essa Activity terá o seguinte código:
public class ActivityPropagandaDois extends FragmentActivity { @Override protected void onCreate(Bundle arg0) { super.onCreate(arg0); setContentView(R.layout.layout_activity_dois); } }
Volte no código da ActivityPropagandaUm para ver que existe um método que vai abrir a ActivityPropagandaDois. Bem simples né!? Apenas faz vínculo ao layout XML que chamamos de layout_activity_dois. Podemos ver o código deste layout logo abaixo:
<xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/layout_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:gravity="center" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" > <TextView android:textSize="22dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/layout_tela_dois" /> </LinearLayout> <include android:layout_gravity="bottom" layout="@layout/layout_propaganda"/> </LinearLayout>
Observe que novamente, fazemos referência ao layout_propaganda. Ou seja, estamos reutilizando a funcionalidade de exibir uma propaganda em duas Activitys diferentes com um esforço muito pequeno.
Imagine se esse Fragment invés de mostrar uma propaganda, faça uma chamada no servidor para mostrar as condições climáticas, ou mostre o resultado do último jogo de seu time favorito.
As possibilidade são muitas, e uma vez feito você poderá utiliza-lo novamente em qualquer Activity do seu aplicativo.
FragmentTransaction e FragmentManager - Criando e trocando fragments dinamicamente
Em muitas situações você deverá ter uma activity que troque Fragments dinamicamente. Como por exemplo imagine que você tenha um menu no topo da tela do seu app, com base na opção que o usuário clicar você irá trocar o Fragment que esta posicionado no centro desta tela. Qual é a melhor maneira de fazermos isso? A API do Android nos fornece a classe FragmentTransaction, que te possibilita adicionar, remover, e substituir um determinado Fragment em uma tela.
Vejamos como funciona em um exemplo funcional. Crie uma Activity com o nome de ActivityFragmentDinamico. Esta Activity, estará vinculada a um layout que basicamente terá dois botões la embaixo da tela, com os dizeres UM e Dois. Pressionando o botão UM, o layout no centro da tela receberá o FragmentUm. Pressionando o botão Dois, o layout no centro da tela receberá o FragmentDois. Começaremos então com a criação dos Fragments: Código do Fragment UM:
public class FragmentUm extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.layout_fragment, container,false); return view; } }
Código do Fragment DOIS:
public class FragmentDois extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.layout_fragment_dois, container,false); return view; } }
Ambos estão vinculados a layouts bem parecidos, vejamos eles:
<!--?xml <span class="hiddenSpellError" pre="xml " data-mce-bogus="1"-->version="1.0" encoding="utf-8"?> <xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@android:color/black"> <TextView android:textColor="@android:color/white" android:layout_centerInParent="true" android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="FRAGMENT DOIS" android:textAppearance="?android:attr/textAppearanceLarge" /> </RelativeLayout>
Veja que se trata apenas de um layout simples que possui um TextView que indica qual Fragment o usuário esta vendo. Basicamente, teremos dois arquivos iguais a este acima, o primeiro com os dizeres FRAGMENT UM e o segundo com os dizeres FRAGMENT DOIS. Com os Fragments criados, voltamos então a Activity que irá troca-los e adiciona-los de forma dinâmica. Vejamos o código para posteriormente ver as explicações:
public class ActivityFragmentDinamico extends FragmentActivity { Fragment fragmentUm = new FragmentUm(); Fragment fragmentDois = new FragmentDois(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_activity_um); addFragment(fragmentDois); } public void onClickFragmentOne(View view) { replaceFragment(fragmentUm); } public void onClickFragmentTwo(View view) { replaceFragment(fragmentDois); } private void addFragment(Fragment fragment) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.add(R.id.layout_fragments, fragment); transaction.addToBackStack(null); transaction.commit(); } private void replaceFragment(Fragment fragment) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.layout_fragments, fragment); transaction.addToBackStack(null); transaction.commit(); } }
O código acima cria os objetos FragmentUm e FragmentDois. E no método onCreate adiciona o fragmentUm em seu layout dinamicamente. Utilizando o método addFragment, que recebe como paramêtro o Fragment que desejamos adicionar e passamos o R.id.layout_fragments, que representa o local do nosso layout no qual o fragment será inserido, observe o layout XML abaixo para identificar esse local, veja que esta no centro da tela.
<xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/layout_main" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white" android:orientation="vertical" > <LinearLayout android:background="#8A2BE2" android:id="@+id/layout_fragments" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical" > </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#7FFF00" android:gravity="center" android:orientation="horizontal" > <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="onClickFragmentOne" android:text="UM" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="onClickFragmentTwo" android:text="DOIS" /> </LinearLayout> </LinearLayout>
Basicamente a ação de adicionar é feita utilizando a classe FragmentTransaction que possui o método add, após adicionarmos o Fragment no local do layout que desejamos, acionamos o método commit também do FragmentTransaction para efetivara a ação. A mesma coisa é feita no método replace, que é acionado quando os botões forem clicados. Pretendo atualizar este post com novas informações sobre Fragments, vejo você novamente mais tarde =]
#1 by Isaiah Bering on Janeiro 6, 2021 - 9:27 am
You as a witness will be still, happy and utterly tranquil. To the correct audience, this issue is equipped with web website advertising. You might store for poker playing cards from the local store.
#2 by Booker Vierk on Julho 5, 2019 - 5:40 pm
This website was… how do you say it? Relevant!! Finally I have found something which helped me. Cheers!|
#3 by Igor Borges on Agosto 14, 2015 - 12:42 am
Mano vc explica mt bem.. vlw msm ajudou muito…
#4 by Wanderson on Agosto 5, 2015 - 12:29 am
Mano, como que faço um Fragment_dialog_about , com uma imagem , que , quando clicada, aparece as informações do app e meu Web site, email, Facebook, etc?
#5 by Lucas Medina on Maio 22, 2015 - 1:24 pm
Bom dia, estou utilizando fragment em meu projeto, pelo fato de ser em Material Design. Estou precisando clicar numa ImageButton e abrir outra fragment. Como faço isso?
Obrigado
Obs.: Segui este tutorial para fazer o Material Design.
http://www.androidhive.info/2015/04/android-getting-started-with-material-design/
#6 by Heitor on Maio 21, 2015 - 8:55 pm
Ótimo post! parabéns!
Ficou muito fácil de entender!
Abraço!
#7 by Leonardo Casasanta on Abril 16, 2015 - 2:24 pm
Rony,
Meu processo de desenvolver interface é bem arcaico.
Eu penso na funcionalidade e procuro exemplos de interface similares
Tipo quando eu vou desenvolver alguma função de mapa, ai eu analiso os exemplos abaixo:
Depois disso eu já tenho uma idéia de como a minha tela deve ficar, ai eu já começo a desenvolver.
Tem uma galera que usa o balsamiq pra fazer protótipo:
https://balsamiq.com
#8 by ronybiteduc on Abril 16, 2015 - 5:29 pm
Opa rapaz obrigado pela resposta! Estou montando um app para as pizzarias da minha cidade, gostaria de saber se vc tem algo mostrando como posso criar uma listview com dados que podem ser alterados na internet e colocados dentro do listview.
Muito Obrigado.
#9 by Leonardo Casasanta on Abril 16, 2015 - 5:40 pm
Vou te indicar duas leituras.
Pra pegar os dados da Web, você vai precisar saber fazer requisições HTTP.
A frequência dessa atualização de informações deve ficar a seu critério.
Esse artigo tem algumas dicas de como criar um ListView no Android.
Espero que lhe seja útil.
Abraço.
#10 by ronybiteduc on Abril 16, 2015 - 5:43 pm
Sera muito útil sim. Estou começando agora, seguirei o link enviado por vc e continuarei aprendendo contigo. Obrigado mais uma vez.
#11 by Clemente Martire on Novembro 10, 2014 - 6:41 pm
Vc tem como disponibilizar o codigo do projeto (Android Studio). Consertei algumas coisas que estavam erradas no código, mas não consegui fazer funcionar. Principalmente pelo fato dele chamar o Main e não existir ele no projeto.
#12 by Leonardo Casasanta on Novembro 11, 2014 - 4:28 am
Ola Clemente,
Coloquei o link para download do projeto no final do artigo.
Segue o mesmo logo abaixo também:
https://github.com/leonvian/TutorialFragment
#13 by ronybiteducRony on Abril 16, 2015 - 3:48 am
Olá, gostaria de saber qual software vc utiliza para desenvolver as telas do app antes de começar a criação do mesmo, onde vc fala ser o esboço do layout. Desde já agradeço.
#14 by Heitor on Outubro 29, 2014 - 6:14 pm
Ótimo post!
Ficou fácil de entender!
Valeu
#15 by Silvio on Abril 27, 2014 - 3:33 pm
Poderia por favor postar o codigo do projeto ?
Obrigado
#16 by Leonardo Casasanta on Novembro 11, 2014 - 4:28 am
Aqui esta Silvio:
https://github.com/leonvian/TutorialFragment
#17 by ovictorpinto on Janeiro 31, 2014 - 12:44 pm
“Fragment pode ser definido como um fragmento de uma tela em um aplicativo Android”
Vale lembrar que um fragmento pode não ser visível. Muito comum quando se usa o setRetainInstance().