Caso prefira, você encontrará todo esse material, em inglês, no site do Developer Android. A tradução e comentários dos materiais eu faço livremente para ajudar a comunidade que fala português.

domingo, 3 de abril de 2011

Interfaces de Usuários - Fragmentos Parte 02

Gerenciando Fragmentos


Para gerenciar os fragmentos em sua atividade, você precisa usar o FragmentManager. Para tal, chame getFragmentManager() a partir de sua atividade.

Algumas coisas que você pode fazer com o FragmentManager incluem:

  • Conseguir ver os fragmentos que existem na atividade com o findFragmentById ou findFragmentByTag.
  • Retirar fragmentos do back stack usando o popBackStack() (que simula o comando BACK)
  • Registrar um listener para mudanças no back stack com o addOnBackStackChangedListener().
Executando transações de fragmento

Uma grande característica de usar fragmentos em sua atividade é a habilidade de adicionar, remover, substituir e realizar outras ações com eles em resposta à interação do usuário. Cada conjunto de mudanças que você faz commit para a atividade é chamada de transação e você pode realizá-las usando as APIs em FragmentTransaction. Você também pode salvar cadas transação para um back stack gerenciado pela atividade, permitindo ao usuário navegar pelas mudanças que foram sendo feitas no fragmento.

Você pode conseguir uma instância de FragmentTransaction a partir do FragmentManager como mostrado no código abaixo:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Cada transação é um conjunto de mudanças que você pode realizar ao mesmo tempo. Você pode realizar todas as mudanças que quer para uma dada transação usando métodos como add(), remove() e replace(). Então, persistir as modificações usando commit().

Antes de cada commit, contudo, você pode querer chamar addToBackStack() para adicionar a transação para o back stack de transações de fragmento. Esse back stack é gerenciado pela atividade e permite ao usuário voltar para estados de fragmento anteriores pressionando o botão BACK.

Por exemplo, aqui está como substituir um fragmento por outro e preservar o estado anterior no back stack:
// Cria novo fragmento e transação
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();


// Substitui quaisquer views do tipo fragment_containter com esse fragmento
// e adiciona uma transação ao back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);


// Faz o commit da transação
transaction.commit();
Nesse exemplo, newFragment substitui os fragmentos (caso haja algum) que está no container do layout ientificado pelo ID de R.id.fragment_container . Chamando addToBackStack(), a transação que vai ser substituída é salva no back stack para que possa ser chamada de volta quando o usuário pressiona BACK.

Se você adicionar múltiplas mudanças para a transação (como outro add() ou remove()) e chamar addToBackStack(), então todas as mudanças aplicadas antes de chamar o commit() serão adicionadas para o back stack como uma transação única e o BACK poderá voltar a ele.

A maneira com a qual você adicionará mudanças para o FragmentTransaction não importa, exceto que:
  • Você deve chama commit() no final da transação
  • Se você está adicionando multiplos fragmentos para um mesmo container, então a maneira com a qual são adicionadas determinam a ordem que aparecerão na hierarquia da View.
Se você não chama addToBackStack() quando você faz uma transação que remove um fragmento, então o fragmento é destruido quando a transação faz o commit() e o usuário não pode mais navegar de volta a ele. Mas, se você chama o addToBackStack() quando está removendo um fragmento, então o fragmento é parado e poderá ser reinicializado se o usuário navegar de volta para ele.

Dica: Para cada transação de fragmento, você pode aplicar animações de transição, chamando setTransition() antes de fazer o commit()

Chamar o commit() não realiza a transação imediatamente. Ao invés disso, ele agenda a realização dela na thread da interface da atividade assim que a thread estiver disponível para tal. Se necessário você poderá chamar executePendingTransactions() para executar imediatamente as transações submetidas para o commit(). Fazendo isso usualmente não será necessário a não ser que exista uma dependência entre os trabalhos em outras threads.

Cuidado: Você pode fazer o commit() apenas antes da atividade salvar o seu estado. Se você tentar fazer um commit após esse ponto, uma exceção ocorrerá. Isso acontece pois o estado após o commit pode ser perdido se a atividade necessita ser restaurada. Para situações nas quais você pode perder o commit, use commitAllowingStateLoss().

Comunicando com a Atividade

Apesar do fragmento ser implementado como um objeto que é independente de uma atividade e que pode ser usada dentro de multiplas atividades, uma dada instância de um fragmento é diretamente relacionado à atividade que a contém.

Especificamente, o fragmento pode acessar a instância da Atividade com getActivity() e realizar tarefas facilmente como encontrar uma view no layout da atividade:
View listView = getActivity().findViewById(R.id.list);
Outrossim, sua atividade pode chamar métodos no fragmento adquirindo uma referência para o fragmento a partir do FragmentManager, usando findFragmentById() ou findFragmentByTag(). Por exemplo:
ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
Criando eventos de callback para a atividade


Em alguns casos, você pode precisar que um fragmento compartilhe eventos com a atividade. Uma boa forma de fazer isso é definir uma interface de callback dentro do fragmento e requerir que a atividade que a hospeda a implemente. Quando a atividade recebe um callback através da interface, ele pode compartilhar as informações com outros fragmentos no layout se necessário.


Por exemplo, se uma aplicação de notícias tem dois fragmentos em uma atividade - uma que mostra uma lista de artigos (fragmento A) e outra que mostra o artigo (fragmento B) - então o fragmento A deve dizer à atividade quando um item da lista é seleciona para que então possa dizer para o fragmento B para mostrá-lo na tela. Nesse caso, a interface OnArtigcleSelectedListener é declarada dentro do fragmento A.
public static class FragmentA extends ListFragment {
    ...
    // Container Activity must implement this interface
    public interface OnArticleSelectedListener {
        public void onArticleSelected(Uri articleUri);
    }
    ...
}
Então a atividade que hospeda o fragmento implementa a interface acima e faz um override em onArticleSelected() para notificar o fragmento B de um evento no fragmento A. Para assegurar que a atividade hospedeira implemente a interface, o método onAttach() do fragmento A instancia o OnArticleSelectedListener fazendo o casting da atividade que é passada dentro do onAttach().
public static class FragmentA extends ListFragment {
    OnArticleSelectedListener mListener;
    ...
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnArticleSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
        }
    }
    ...
}
Se a atividade não foi implementada na interface, então o fragmento dá um throw para ClassCastException. Se tiver sucesso, o membro mListener guarda uma referência para a implementação da atividade de OnArticleSelectedListener, para que o fragmento A possa compartilhar eventos com a atividade chamando métodos definidos pela interface OnArticleSelectedListener. Por exemplo, se o fragmento A é uma extensão de ListFragment, cada vez que o usuário clicar num item de lista, o sistema chama onListItemClick() no fragmento, que então chama onArticleSelected() para compartilhar o evento com a atividade.
public static class FragmentA extends ListFragment {
    OnArticleSelectedListener mListener;
    ...
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        // Append the clicked item's row ID with the content provider Uri
        Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id);
        // Send the event and Uri to the host activity
        mListener.onArticleSelected(noteUri);
    }
    ...
}
O parâmetro id qe é passado para onListItemClick é o ID da linha que é clicada e que é usada pela atividade para a captura do artigo no ContentProvider da aplicação.


Adicionando itens para a Action Bar


Seus fragmentos podem incluir itens de menu para a Options Menu da atividade (e, consequentemente, para a Action Bar) implementando o onCreateOptionsMenu(). Para fazer isso o método recebe a chamada mas deve chamar setHasOptionsMenu() durante o onCreate() para indicar que fragmento ele gostaria que fosse adicionado para o Options Menu.


Quaisquer itens que você queira adicionar para o Options Menu do fragmento são concatenados no menu de itens existente. O fragmento também recebe callbacks para onOptionsItemSelected() quando um item de menu é selecionado.

Você também pode registrar um view no seu layout de fragmento para prover um menu de contexto chamando registerForContextMenu(). Quando o usuário abre o menu de contexto, o fragmento recebe uma chamada para onCreateContextMenu(). Quando o usuário seleciona um item, o fragmento recebe uma chamada para onContextItemSelected().

1 comentários:

Frederico Brigatte disse...

Preciso fazer um Fragment com ListView

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.
Related Posts Plugin for WordPress, Blogger...