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.



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.


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");
  }

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();

}

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).


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;
                }
            }
        }
    }

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

}

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");

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


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 ()


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 .


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);
            }
        }
});

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
    }
}

1

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


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;
}

0

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

String fr_name = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();

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) 
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.