Fragmento Fragment

[Language: Português]

01 – Entendendo o Fragment

Introdução ao curso

Este curso exige que você tenha conhecimentos básicos de Android.

Sem essa base, será difícil acompanhar.

Fragment é traduzido como “fragmento” ou “pedaço”.

Na verdade, “fragmento” é o mais correto.

É um fragmento de interface de usuário incorporado em uma Activity.

Permite que os aplicativos aproveitem melhor o espaço de telas grandes.

Por isso é muito adequado para tablets.

É muito parecido com uma Activity: tem seu próprio layout e seu próprio ciclo de vida.

Você pode pensar nele como uma Activity em miniatura.

Quando vamos desenvolver um aplicativo de notícias,

em uma tela de celular, poderíamos desenhar assim:

uma Activity de lista, e ao clicar abre uma Activity de detalhe da notícia.

Mas em um tablet, fazer isso deixaria grandes espaços em branco, o que não é bom.

Um design melhor é dividir a lista e o detalhe em dois fragmentos dentro da mesma Activity.

Criar um emulador de tablet

Para testar melhor nosso app no tablet, vamos criar um emulador de tablet.

02 – Primeiro exemplo com Fragment

Adicionar dois fragmentos em uma Activity e fazer com que dividam o espaço igualmente.

Adicione um novo projeto chamado FragmentFirst.

Adicione dois layouts: um para o fragmento da esquerda

newlist.xml

e outro para o fragmento da direita, newdetail.xml.

Fragmento esquerdo

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/buttondialog"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Guerra comercial China-EUA 2018" />
</LinearLayout>Code language: HTML, XML (xml)

Fragmento direito

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0ddb97"
    >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Conteúdo da notícia conteúdo da notícia" />
</LinearLayout>Code language: HTML, XML (xml)

Adicionar a classe do fragmento

Adicione um NewListFragment.

Herde de android.support.v4.app.Fragment.

Depois sobrescreva o método onCreateView para que este fragmento use o xml newlist.

public class NewListFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.newlist,container,false);
        return view;
    }
}Code language: PHP (php)

Adicione o fragmento de detalhe da notícia da mesma forma.

NewDetailFragment também herda de

android.support.v4.app.Fragment.

public class NewDetailFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.newdetail,container,false);
        return view;
    }
}Code language: PHP (php)

Chamar os fragmentos na visualização da atividade principal

Use o atributo android:name=”com.foxdevelop.” para definir qual fragmento usar.

Ao adicionar uma visualização de fragmento no layout principal, o id é obrigatório.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment
        android:id="@+id/newlist_fragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:name="com.foxdevelop.www.fragmentfirst.NewListFragment"
        />
    <fragment
        android:id="@+id/newdetail_fragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3"
        android:name="com.foxdevelop.www.fragmentfirst.NewDetailFragment"
        />
</LinearLayout>Code language: HTML, XML (xml)

03 – Adicionar fragmentos dinamicamente

O verdadeiro poder dos fragmentos é que eles podem ser adicionados dinamicamente a uma Activity enquanto o app está rodando.

Adicionando fragmentos dinamicamente conforme a situação, podemos criar interfaces muito mais diversificadas.

Por exemplo, em nosso app de notícias, alguns artigos são de imagem, outros de texto, outros de vídeo. Dependendo do tipo de notícia, podemos carregar diferentes layouts de fragmentos.

Vamos adicionar uma visualização new_picture.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/birdsee"
        />
</LinearLayout>Code language: HTML, XML (xml)

Para diferenciar, ele simplesmente exibe uma imagem.

Adicionar a classe de fragmento para imagens

public class NewImageFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.new_picture,container,false);
        return view;
    }
}Code language: PHP (php)

Usar FrameLayout na visualização principal

Aqui usamos um FrameLayout.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment
        android:id="@+id/newlist_fragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:name="com.foxdevelop.www.fragmentfirst.NewListFragment"
        />

    <FrameLayout
        android:id="@+id/framelayout"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3"
        ></FrameLayout>
</LinearLayout>Code language: HTML, XML (xml)

Adicionar dois botões à esquerda

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/buttondialog"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Guerra comercial China-EUA 2018" />
    <Button
        android:id="@+id/buttonpicture"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Notícia de imagem" />
</LinearLayout>Code language: HTML, XML (xml)

Adicionar eventos aos botões na atividade principal

Configurando eventos de clique nos botões, podemos carregar dinamicamente diferentes fragmentos conforme o botão pressionado.

package com.foxdevelop.www.fragmentfirst;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Vincular eventos aos dois botões
        Button b1 = (Button)findViewById(R.id.buttonarticle);
        b1.setOnClickListener(this);
        Button b2 = (Button)findViewById(R.id.buttonpicture);
        b1.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        // Configurar diferentes fragmentos conforme o botão
        switch (view.getId())
        {
            case R.id.buttonarticle:
                setFragement(new NewDetailFragment());
                break;
            case R.id.buttonpicture:
                setFragement(new NewImageFragment());
                break;
            default:
                break;
        }
    }

    // Este método configura o fragmento para o FrameLayout
    public void setFragement(Fragment fragement) {
        FragmentManager fragementManager = getSupportFragmentManager();
        // Iniciar a transação
        android.support.v4.app.FragmentTransaction fragmentTransaction = fragementManager.beginTransaction();
        fragmentTransaction.replace(R.id.framelayout,fragement);// Configura o FrameLayout para usar o fragmento passado
        fragmentTransaction.commit();
    }
}Code language: JavaScript (javascript)

04 – Usar a pilha de retorno (back stack) com fragmentos

No curso básico já explicamos o que é a pilha de retorno.

No exemplo anterior, ao pressionar a tecla back, o app sai direto da atividade principal e encerra o programa. Mas esse não é o comportamento que queremos; queremos que ao pressionar back ele volte para o fragmento anterior.

Fazer com que os fragmentos suportem a pilha de retorno é na verdade muito simples.

Basta adicionar a transação à pilha de retorno.

// Este método configura o fragmento para o FrameLayout
public void setFragement(Fragment fragement) {
    FragmentManager fragementManager = getSupportFragmentManager();
    // Iniciar a transação
    android.support.v4.app.FragmentTransaction fragmentTransaction = fragementManager.beginTransaction();
    fragmentTransaction.replace(R.id.framelayout,fragement);// Configura o FrameLayout para usar o fragmento passado
    fragmentTransaction.addToBackStack(null);// Adiciona a transação à pilha de retorno
    fragmentTransaction.commit();
}Code language: JavaScript (javascript)

05 – Comunicação entre Fragment e Activity

Os fragmentos são incorporados nas atividades, mas na verdade o relacionamento não é tão próximo.

Nosso fragmento e nossa atividade existem como classes independentes.

Não há uma forma direta para eles se comunicarem.

Para facilitar a comunicação,

o FragmentManager fornece um método similar ao findViewById, usado para obter uma instância do fragmento a partir do layout.

getFragmentManager android.support.v4.app.Fragment

precisa de cast. Isso não foi mencionado no livro.

Se você importou o pacote android.support.v4.app.Fragment (ou seja, o pacote v4)

import android.support.v4.app.Fragment;

então, ao obter o FragmentManager, você deve usar

FragmentManager fm = getSupportFragmentManager();

O fragmento correspondente também deve importar o pacote correto!

// Obter a instância do fragmento no método onCreate da atividade
NewListFragment newListFragment = (NewListFragment)getSupportFragmentManager().findFragmentById(R.id.newlist_fragment);
Toast.makeText(this, newListFragment.getId()+"xxxx",Toast.LENGTH_LONG).show();Code language: JavaScript (javascript)

Obter a Activity a partir do fragmento

// Obter a Activity a partir do fragmento
MainActivity mainActivity = (MainActivity) getActivity();
Toast.makeText(getContext(), mainActivity.getTitle(),Toast.LENGTH_LONG).show();Code language: JavaScript (javascript)

Você pode chamar o método getActivity().

06 – Ciclo de vida do Fragment

O ciclo de vida do fragment é basicamente o mesmo da Activity.

Os fragmentos também têm quatro estados.

Em execução, Pausado, Parado, Destruído.

1. Estado em execução: o fragmento está visível e a atividade à qual pertence está em execução, então o fragmento também está ativo.

2. Estado pausado

Quando outra atividade que não ocupa a tela inteira é adicionada ao topo da pilha, o fragmento visível que ela gerencia entra no estado pausado.

3. Estado parado

Quando uma atividade entra no estado parado, seus fragmentos relacionados também entram no estado parado. Ou, se você usar os métodos remove ou replace do FragmentTransaction para remover um fragmento de uma atividade, e chamar addToBackStack antes de confirmar a transação, ele também entrará no estado parado.

Em resumo, um fragmento no estado parado não é visível para o usuário e pode ser reciclado pelo sistema a qualquer momento.

4. Estado destruído

Os fragmentos sempre dependem das atividades, então quando uma atividade é destruída, seus fragmentos relacionados também entram no estado destruído. Ou, se você usar remove ou replace para remover um fragmento sem chamar addToBackStack antes de confirmar, ele também entrará no estado destruído.

Assim como as atividades, o Fragment também fornece uma série de métodos de callback que cobrem cada etapa do ciclo de vida. Quase tudo o que uma Activity tem, um Fragment também tem.

Ao mesmo tempo, o Fragment também fornece alguns métodos de callback adicionais.

Fragmento Fragment

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *