Obter o objeto de fragmento atual

175

No meu main.xmleu tenho

  <FrameLayout
        android:id="@+id/frameTitle"
        android:padding="5dp"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:background="@drawable/title_bg">
            <fragment
              android:name="com.fragment.TitleFragment"
              android:id="@+id/fragmentTag"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content" />

  </FrameLayout>

E eu estou definindo um objeto de fragmento como este

FragmentManager fragmentManager = activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment newFragment = new FragmentType1();
fragmentTransaction.replace(R.id.frameTitle, casinodetailFragment, "fragmentTag");

// fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

Ele está definindo diferentes tipos de objetos Fragment ( FragmentType2,FragmentType3,...) em momentos diferentes. Agora, em algum momento, preciso identificar qual objeto está atualmente lá.

Em resumo , preciso fazer algo assim:

Fragment currentFragment = //what is the way to get current fragment object in FrameLayout R.id.frameTitle

Eu tentei o seguinte

TitleFragment titleFragmentById = (TitleFragment) fragmentManager.findFragmentById(R.id.frameTitle);

e

    TitleFragment titleFragmentByTag = (TitleFragment) fragmentManager.findFragmentByTag("fragmentTag");

Mas ambos os objetos (titleFragmentById e titleFragmentByTag) são Perdinull
alguma coisa?
Estou usando Compatibility Package, r3e desenvolvendo para API level 7.

findFragmentById()e findFragmentByTag()funcionará se tivermos definido o fragmento usando fragmentTransaction.replaceor fragmentTransaction.add, mas funcionará return nullse tivermos definido o objeto em xml (como o que fiz no meu main.xml). Acho que estou perdendo alguma coisa nos meus arquivos XML.

Labeeb Panampullan
fonte
A resposta do @CommonsWare ajuda você, porque eu ainda fico nulo?
IntoTheDeep

Respostas:

253

Agora, em algum momento, preciso identificar qual objeto está atualmente lá

Chamada findFragmentById()em FragmentManagere determinar quais fragmento está na sua R.id.frameTitleembalagem.

CommonsWare
fonte
1
Obrigado pela sua resposta. Funcionará se tivermos definido o fragmento usando fragmentTransaction.replace ou, fragmentTransaction.addmas não será possível se o tivermos definido como xml. Veja minha edição 2
Labeeb Panampullan
9
@Labeeb P: Você não pode modificar fragmentos declarados nos recursos de layout.
CommonsWare
Criar uma classe para conter a guia / fragmento atualmente visível também funcionará, apenas tentei isso. Espero que não haja falhas.
Skynet
@CommonsWare findFragmentByTagretornando nulo no caso de ActionBarGuias. No meu Activityque está se estendendo, ActionBarActivityestou adicionando abas ActionBare depois localizando-a!
Muhammad Babar 27/05
1
@MuhammadBabar: Você pode tentar executePendingTransactions()em FragmentManagerdepois de chamar commit()a transação, embora eu não tentei isso. Ou você pode usar setContentView()para usar um arquivo de layout com uma <fragment>tag. Um desses eventos ocorre de forma síncrona e, portanto, o fragmento existirá na onCreate()própria chamada em que você usou executePendingTransaction()ou setContentView(). Caso contrário, um comum FragmentTransactioné processado de forma assíncrona e nem começará no onCreate()final do tempo .
CommonsWare
110

Tente isso,

Fragment currentFragment = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);

isso lhe dará o fragmento atual, então você poderá compará-lo à classe de fragmentos e fazer seus materiais.

    if (currentFragment instanceof NameOfYourFragmentClass) {
     Log.v(TAG, "find the current fragment");
  }
Martelo
fonte
Onde colocar essa linha?
Anand Savjani
9
Às vezes você tem que usar getSupportFragmentManager()em vez disso, e vai ficar nula sem a supportparte
Muz
Remova as aspas de "NOME DA SUA CLASSE DE FRAGMENTOS".
1913 Alan Nelson
37

Eu acho que você pode usar o evento onAttachFragment pode ser útil para capturar qual fragmento está ativo.

@Override
public void onAttachFragment(Fragment fragment) {
    // TODO Auto-generated method stub
    super.onAttachFragment(fragment);

    Toast.makeText(getApplicationContext(), String.valueOf(fragment.getId()), Toast.LENGTH_SHORT).show();

}
Hede Hodo
fonte
3
Eu consigo obter qual fragmento estou anexado. Meu pensamento é quando eu mudar a orientação, então eu preciso exibir a mesma visão e não outra visão, então como fazer isso.
Androi Developer
7
Isso não funciona porque não atualiza o fragmento ativo quando você volta.
26714 Justin justin
1
@Justin por isso, só precisa usar onDetach também com uma lista WeakReference
letroll
12

Eu acho que você deveria fazer:

Fragment currentFragment = fragmentManager.findFragmentByTag("fragmentTag");

O motivo é porque você definiu a tag "fragmentTag" como o último fragmento que você adicionou (ao chamar substituir).

Niqo
fonte
Obrigado, eu o corrigi. É um erro de digitação ao escrever esta pergunta. Funcionará se tivermos definido o fragmento usando fragmentTransaction.replace ou, fragmentTransaction.addmas não será possível se o tivermos definido como xml. Veja minha edição 2
Labeeb Panampullan
Muito obrigado! Resolvido meu problema!
Jonas Gröger
2
Essa solução não significa que você precisa colocar a mesma tag para vários fragmentos? caso contrário, como você saberia que fragmentTagé a tag do fragmento atual?
Thupten
12

Você pode obter a lista dos fragmentos e procurar o último.

    FragmentManager fm = getSupportFragmentManager();
    List<Fragment> fragments = fm.getFragments();
    Fragment lastFragment = fragments.get(fragments.size() - 1);

Mas, às vezes (quando você navega para trás), o tamanho da lista permanece o mesmo, mas alguns dos últimos elementos são nulos. Portanto, na lista, iteramos o último fragmento não nulo e o usei.

    FragmentManager fm = getSupportFragmentManager();
    if (fm != null) {
        List<Fragment> fragments = fm.getFragments();
        if (fragments != null) {
            for(int i = fragments.size() - 1; i >= 0; i--){
                Fragment fragment = fragments.get(i);
                if(fragment != null) {
                    // found the current fragment

                    // if you want to check for specific fragment class
                    if(fragment instanceof YourFragmentClass) {
                        // do something
                    }
                    break;
                }
            }
        }
    }
eluleci
fonte
3
Não use o getFragments()método Ele está marcado com @hidee não deveria ser incluído no jar da biblioteca de suporte. Não deve ser considerado como parte da API exportada.
James Wald
Heh, eles deveriam ter criado um método que permite fazer exatamente o que getFragments()faz, porque você precisa com bastante frequência. Eu acho que também está disponível publicamente agora.
EpicPandaForce 27/06/19
10

Esta é a solução mais simples e funciona para mim.

1.) você adiciona seu fragmento

ft.replace(R.id.container_layout, fragment_name, "fragment_tag").commit();

2.)

FragmentManager fragmentManager = getSupportFragmentManager();

Fragment currentFragment = fragmentManager.findFragmentById(R.id.container_layout);

if(currentFragment.getTag().equals("fragment_tag"))

{

 //Do something

}

else

{

//Do something

}
Gau
fonte
9

Pode ser tarde, mas espero que ajude outra pessoa, também o @CommonsWare postou a resposta correta.

FragmentManager fm = getSupportFragmentManager();
Fragment fragment_byID = fm.findFragmentById(R.id.fragment_id);
//OR
Fragment fragment_byTag = fm.findFragmentByTag("fragment_tag");
Ahmad Ali Nasir
fonte
9
Isso não permite que você obtenha o fragmento ativo, pois você não conhece necessariamente o ID ou a tag.
26714 Justin justin
7

Talvez a maneira mais simples seja:

public MyFragment getVisibleFragment(){
    FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
    List<Fragment> fragments = fragmentManager.getFragments();
    for(Fragment fragment : fragments){
        if(fragment != null && fragment.getUserVisibleHint())
            return (MyFragment)fragment;
    }
    return null;
}

Funcionou para mim

madx
fonte
6

Você pode criar um campo na sua Classe de atividade pai:

public class MainActivity extends AppCompatActivity {

    public Fragment fr;

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

}

E então dentro de cada classe de fragmento:

public class SomeFragment extends Fragment {

@Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {

        ((MainActivity) getActivity()).fr = this;
}

Seu campo 'fr' é o fragmento atual Object

Também está trabalhando com popBackStack ()

buxik
fonte
4

Eu sei que já faz um tempo, mas eu vou fazer isso aqui, caso isso ajude alguém.

A resposta certa de longe é (e a selecionada) a resposta do CommonsWare. Eu estava tendo o mesmo problema que o postado, o seguinte

MyFragmentClass fragmentList = 
            (MyFragmentClass) getSupportFragmentManager().findFragmentById(R.id.fragementID);

continuou retornando nulo. Meu erro foi muito bobo, no meu arquivo xml:

<fragment
    android:tag="@+id/fragementID"
    android:name="com.sf.lidgit_android.content.MyFragmentClass"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
/>

O erro foi que eu tinha android: tag INSTEAD OF android: id .

Chayemor
fonte
2

A resposta do @Hammer funcionou para mim, estou usando para controlar um botão de ação flutuante

final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(final View view) {
            android.app.Fragment currentFragment = getFragmentManager().findFragmentById(R.id.content_frame);
            Log.d("VIE",String.valueOf(currentFragment));
            if (currentFragment instanceof PerfilFragment) {
                PerfilEdit(view, fab);
            }
        }
});
Thiago Melo
fonte
2

Se você estiver estendendo a partir de AbstractActivity, poderá usar o método getFragments ():

for (Fragment f : getFragments()) {
    if (f instanceof YourClass) {
        // do stuff here
    }
}
Marco Aurélio Alves Puton
fonte
1

Se você estiver definindo o fragmento na camada XML da atividade, Activitycertifique-se de ligar setContentView()antes de ligar findFragmentById().

IvancityM
fonte
1

Se você estiver usando o BackStack ... e SOMENTE se você estiver usando a pilha traseira, tente o seguinte:

rivate Fragment returnToPreviousFragment() {

    FragmentManager fm = getSupportFragmentManager();

    Fragment topFrag = null;

    int idx = fm.getBackStackEntryCount();
    if (idx > 1) {
        BackStackEntry entry = fm.getBackStackEntryAt(idx - 2);
        topFrag = fm.findFragmentByTag(entry.getName());
    }

    fm.popBackStack();

    return topFrag;
}
James Barwick
fonte
0

Isso fornecerá o nome atual da classe de fragmento ->

String fr_name = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();
Biplob Das
fonte
0
  1. Faça uma verificação (que fragmento no contêiner de atividade) no método onStart;

    @Override
    protected void onStart() {
    super.onStart();
    Fragment fragmentCurrent = getSupportFragmentManager.findFragmentById(R.id.constraintLayout___activity_main___container);
    }
  2. Alguns conferem:

    if (fragmentCurrent instanceof MenuFragment) 
Владислав Шестернин
fonte