Compartilhar via


Criando um fragmento

Para criar um Fragmento, uma classe deve herdar de Android.App.Fragment e substituir o OnCreateView método . OnCreateView será chamado pela Atividade de hospedagem quando for hora de colocar o Fragmento na tela e retornará um View. Um típico OnCreateView criará isso View inflando um arquivo de layout e anexando-o a um contêiner pai. As características do contêiner são importantes, pois o Android aplicará os parâmetros de layout do pai à interface do usuário do Fragmento. O exemplo a seguir ilustra isso:

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    return inflater.Inflate(Resource.Layout.Example_Fragment, container, false);
}

O código acima inflará a exibição Resource.Layout.Example_Fragmente a adicionará como uma exibição filho ao ViewGroup contêiner.

Observação

As subclasses de fragmento devem ter um construtor sem argumento padrão público.

Adicionando um fragmento a uma atividade

Há duas maneiras pelas quais um fragmento pode ser hospedado dentro de uma atividade:

  • Declarativamente – fragmentos podem ser usados declarativamente dentro .axml de arquivos de layout usando a <Fragment> marca .

  • Programaticamente – os fragmentos também podem ser instanciados dinamicamente usando a FragmentManager API da classe.

O uso programático por meio da FragmentManager classe será discutido posteriormente neste guia.

Usando um fragmento declarativamente

Adicionar um Fragmento dentro do layout requer o uso da <fragment> marca e, em seguida, identificar o Fragmento fornecendo o class atributo ou o android:name atributo . O snippet a seguir mostra como usar o class atributo para declarar um fragment:

<?xml version="1.0" encoding="utf-8"?>
<fragment class="com.xamarin.sample.fragments.TitlesFragment"
            android:id="@+id/titles_fragment"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />

Este próximo snippet mostra como declarar um fragment usando o android:name atributo para identificar a classe Fragment :

<?xml version="1.0" encoding="utf-8"?>
<fragment android:name="com.xamarin.sample.fragments.TitlesFragment"
            android:id="@+id/titles_fragment"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />

Quando a Atividade estiver sendo criada, o Android criará uma instância de cada Fragmento especificado no arquivo de layout e inserirá o modo de OnCreateView exibição criado no lugar do Fragment elemento . Os fragmentos que são adicionados declarativamente a uma Atividade são estáticos e permanecerão na Atividade até que ela seja destruída; não é possível substituir ou remover dinamicamente esse fragmento durante o tempo de vida da Atividade à qual ele está anexado.

Cada fragmento deve receber um identificador exclusivo:

  • android:id – assim como acontece com outros elementos da interface do usuário em um arquivo de layout, essa é uma ID exclusiva.

  • android:tag – esse atributo é uma cadeia de caracteres exclusiva.

Se nenhum dos dois métodos anteriores for usado, o Fragmento assumirá a ID da exibição de contêiner. No exemplo a seguir, em que nem android:id nem android:tag é fornecido, o Android atribuirá a ID fragment_container ao Fragmento:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="+@id/fragment_container"
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

        <fragment class="com.example.android.apis.app.TitlesFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
</LinearLayout>

Caso do nome do pacote

O Android não permite caracteres maiúsculos em nomes de pacote; ele gerará uma exceção ao tentar inflar o modo de exibição se um nome de pacote contiver um caractere maiúsculo. No entanto, o Xamarin.Android é mais tolerante e tolerará caracteres maiúsculos no namespace.

Por exemplo, ambos os snippets a seguir funcionarão com o Xamarin.Android. No entanto, o segundo snippet fará com que um android.view.InflateException seja gerado por um aplicativo Android baseado em Java puro.

<fragment class="com.example.DetailsFragment" android:id="@+id/fragment_content" android:layout_width="match_parent" android:layout_height="match_parent" />

OU

<fragment class="Com.Example.DetailsFragment" android:id="@+id/fragment_content" android:layout_width="match_parent" android:layout_height="match_parent" />

Ciclo de vida do fragmento

Os fragmentos têm seu próprio ciclo de vida que é um pouco independente, mas ainda afetado pelo ciclo de vida da Atividade de hospedagem. Por exemplo, quando uma Atividade é pausada, todos os fragmentos associados são pausados. O diagrama a seguir descreve o ciclo de vida do Fragmento.

Diagrama de fluxo ilustrando o ciclo de vida do fragmento

Métodos de ciclo de vida de criação de fragmentos

A lista a seguir mostra o fluxo dos vários retornos de chamada no ciclo de vida de um Fragmento conforme ele está sendo criado:

  • OnInflate() – Chamado quando o fragmento está sendo criado como parte de um layout de exibição. Isso pode ser chamado imediatamente depois que o fragmento é criado declarativamente de um arquivo de layout XML. O Fragmento ainda não está associado à atividade, mas a Atividade, o Pacote e o AttributeSet da hierarquia de exibição são passados como parâmetros. Esse método é melhor usado para analisar o AttributeSet e para salvar os atributos que podem ser usados posteriormente pelo Fragmento.

  • OnAttach() – Chamado depois que o Fragmento é associado à Atividade. Esse é o primeiro método a ser executado quando o Fragmento está pronto para ser usado. Em geral, fragmentos não devem implementar um construtor nem substituir o construtor padrão. Todos os componentes necessários para o Fragmento devem ser inicializados nesse método.

  • OnCreate() – Chamado pela atividade para criar o fragmento. Quando esse método é chamado, a hierarquia de exibição da Atividade de hospedagem pode não ser completamente instanciada, portanto, o Fragmento não deve depender de nenhuma parte da hierarquia de exibição da Atividade até mais tarde no ciclo de vida do Fragmento. Por exemplo, não use esse método para executar ajustes ou ajustes na interface do usuário do aplicativo. Este é o primeiro momento em que o Fragmento pode começar a coletar os dados necessários. O Fragmento está em execução no thread da interface do usuário neste ponto, portanto, evite qualquer processamento longo ou execute esse processamento em um thread em segundo plano. Esse método poderá ser ignorado se SetRetainInstance(true) for chamado. Essa alternativa será descrita mais detalhadamente abaixo.

  • OnCreateView() – Cria o modo de exibição para o Fragmento. Esse método é chamado quando o método OnCreate() da atividade é concluído. Neste ponto, é seguro interagir com a hierarquia de exibição da Atividade. Esse método deve retornar a exibição que será usada pelo Fragmento.

  • OnActivityCreated() – Chamado após Activity.OnCreate ter sido concluído pela Atividade de hospedagem. Os ajustes finais na interface do usuário devem ser executados no momento.

  • OnStart() – Chamado depois que a atividade que contém foi retomada. Isso torna o Fragmento visível para o usuário. Em muitos casos, o Fragmento conterá código que, de outra forma, estaria no método OnStart() de uma Atividade.

  • OnResume() – Esse é o último método chamado antes que o usuário possa interagir com o Fragmento. Um exemplo do tipo de código que deve ser executado nesse método seria habilitar recursos de um dispositivo com o qual o usuário pode interagir, como a câmera que o local atende. No entanto, serviços como esses podem causar consumo excessivo de bateria, e um aplicativo deve minimizar seu uso para preservar a duração da bateria.

Métodos de ciclo de vida de destruição de fragmentos

A próxima lista explica os métodos de ciclo de vida chamados como fragmentos que estão sendo destruídos:

  • OnPause() – O usuário não pode mais interagir com o Fragmento. Essa situação existe porque alguma outra operação fragmentada está modificando esse Fragmento ou a Atividade de hospedagem está em pausa. É possível que a Atividade que hospeda esse Fragmento ainda esteja visível, ou seja, a Atividade em foco seja parcialmente transparente ou não ocupe a tela inteira. Quando esse método se torna ativo, é a primeira indicação de que o usuário está deixando o Fragmento. O Fragmento deve salvar todas as alterações.

  • OnStop() – O fragmento não está mais visível. A Atividade do host pode ser interrompida ou uma operação Fragment está modificando-a na Atividade. Esse retorno de chamada tem a mesma finalidade que Activity.OnStop.

  • OnDestroyView()– Esse método é chamado para limpo recursos associados à exibição. Isso é chamado quando a exibição associada ao fragmento foi destruída.

  • OnDestroy() – Esse método é chamado quando o fragmento não está mais em uso. Ele ainda está associado à Atividade, mas o Fragmento não é mais funcional. Esse método deve liberar todos os recursos que estão em uso pelo Fragmento, como um SurfaceView que pode ser usado para uma câmera. Esse método poderá ser ignorado se SetRetainInstance(true) for chamado. Essa alternativa será descrita mais detalhadamente abaixo.

  • OnDetach() – Esse método é chamado logo antes que o Fragmento não esteja mais associado à Atividade. A hierarquia de exibição do Fragmento não existe mais e todos os recursos usados pelo Fragmento devem ser liberados neste ponto.

Usando SetRetainInstance

É possível que um Fragmento especifique que ele não deve ser completamente destruído se a Atividade estiver sendo recriada. A Fragment classe fornece o método SetRetainInstance para essa finalidade. Se true for passado para esse método, quando a Atividade for reiniciada, a mesma instância do Fragmento será usada. Se isso acontecer, todos os métodos de retorno de chamada serão invocados, exceto os retornos de chamada do OnCreate ciclo de vida e OnDestroy . Esse processo é ilustrado no diagrama de ciclo de vida mostrado acima (pelas linhas pontilhadas verdes).

Gerenciamento de Estado de Fragmento

Os fragmentos podem salvar e restaurar seu estado durante o ciclo de vida do fragmento usando uma instância de um Bundle. O Pacote permite que um Fragmento salve dados como pares chave/valor e é útil para dados simples que não exigem muita memória. Um fragmento pode salvar seu estado com uma chamada para OnSaveInstanceState:

public override void OnSaveInstanceState(Bundle outState)
{
    base.OnSaveInstanceState(outState);
    outState.PutInt("current_choice", _currentCheckPosition);
}

Quando uma nova instância de um Fragmento é criada, o estado salvo no Bundle ficará disponível para a nova instância por meio dos OnCreatemétodos , OnCreateViewe OnActivityCreated da nova instância. O exemplo a seguir demonstra como recuperar o valor current_choice do Bundle:

public override void OnActivityCreated(Bundle savedInstanceState)
{
    base.OnActivityCreated(savedInstanceState);
    if (savedInstanceState != null)
    {
        _currentCheckPosition = savedInstanceState.GetInt("current_choice", 0);
    }
}

OnSaveInstanceState Substituir é um mecanismo apropriado para salvar dados transitórios em um Fragmento entre alterações de orientação, como o current_choice valor no exemplo acima. No entanto, a implementação padrão de OnSaveInstanceState cuida do salvamento de dados transitórios na interface do usuário para cada exibição que tenha uma ID atribuída. Por exemplo, examine um aplicativo que tem um EditText elemento definido em XML da seguinte maneira:

<EditText android:id="@+id/myText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>

Como o EditText controle tem um id atribuído, o Fragmento salva automaticamente os dados no widget quando OnSaveInstanceState é chamado.

Limitações do pacote

Embora o uso OnSaveInstanceState do torne mais fácil salvar dados transitórios, o uso desse método tem algumas limitações:

  • Se o Fragmento não for adicionado à pilha traseira, seu estado não será restaurado quando o usuário pressionar o botão Voltar .

  • Quando o Pacote é usado para salvar dados, esses dados são serializados. Isso pode levar a atrasos de processamento.

Contribuindo para o menu

Os fragmentos podem contribuir com itens para o menu de sua Atividade de hospedagem. Uma Atividade manipula os itens de menu primeiro. Se a Atividade não tiver um manipulador, o evento será passado para o Fragmento, que o manipulará.

Para adicionar itens ao menu da Atividade, um Fragmento deve fazer duas coisas. Primeiro, o Fragmento deve implementar o método OnCreateOptionsMenu e colocar seus itens no menu, conforme mostrado no seguinte código:

public override void OnCreateOptionsMenu(IMenu menu, MenuInflater menuInflater)
{
    menuInflater.Inflate(Resource.Menu.menu_fragment_vehicle_list, menu);
    base.OnCreateOptionsMenu(menu, menuInflater);
}

O menu no snippet de código anterior é inflado do seguinte XML, localizado no arquivo menu_fragment_vehicle_list.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:id="@+id/add_vehicle"
        android:icon="@drawable/ic_menu_add_data"
        android:title="@string/add_vehicle" />
</menu>

Em seguida, o Fragmento deve chamar SetHasOptionsMenu(true). A chamada para esse método anuncia ao Android que o Fragmento tem itens de menu para contribuir com o menu de opções. A menos que a chamada para esse método seja feita, os itens de menu do Fragmento não serão adicionados ao menu de opções da Atividade. Isso normalmente é feito no método OnCreate()de ciclo de vida , conforme mostrado no próximo snippet de código:

public override void OnCreate(Bundle savedState)
{
    base.OnCreate(savedState);
    SetHasOptionsMenu(true);
}

A tela a seguir mostra a aparência desse menu:

Captura de tela de exemplo do aplicativo Minhas Viagens exibindo itens de menu