Antes de tentar o componente de navegação, eu costumava fazer transações de fragmento manualmente e usar a tag de fragmento para buscar o fragmento atual.
val fragment:MyFragment = supportFragmentManager.findFragmentByTag(tag):MyFragment
Agora, no layout da minha atividade principal, tenho algo como:
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/nav_host"
app:navGraph= "@navigation/nav_item"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost= "true"
/>
Como posso recuperar o fragmento exibido atualmente pelo componente de navegação? Fazendo
supportFragmentManager.findFragmentById(R.id.nav_host)
retorna um NavHostFragment
e eu quero recuperar meu 'MyFragment` mostrado.
Obrigado.
onActivityResult
da minha atividade principal. Como não consegui obter o fragmento, simplesmente movi tudo isso para o próprio fragmento e parece funcionar.Respostas:
Consegui descobrir um caminho por agora e é o seguinte:
NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host); navHostFragment.getChildFragmentManager().getFragments().get(0);
Caso você saiba, é o primeiro fragmento. Ainda estou investigando uma maneira sem isso. Eu concordo que não é a melhor maneira, mas isso deve ser algo por agora.
fonte
navHostFragment!!.childFragmentManager.fragments.any { it.javaClass == fragmentClass && it.isVisible }
Funciona de forma bastante semelhante. Espero que ajude alguém!Não consigo encontrar nenhuma maneira de recuperar a instância do fragmento atual. No entanto, você pode obter a ID do fragmento adicionado por último usando o código abaixo.
navController.currentDestination?.getId()
Ele retorna o ID no arquivo de navegação. Espero que isto ajude.
fonte
Você deve examinar a propriedade childFragmentManager primaryNavigationFragment de seu fragmento de navegação, é aqui que o fragmento exibido atual é referenciado.
val navHost = supportFragmentManager.findFragmentById(R.id.main_nav_fragment) navHost?.let { navFragment -> navFragment.childFragmentManager.primaryNavigationFragment?.let {fragment-> //DO YOUR STUFF } } }
fonte
Esta parece ser a solução mais limpa. Atualização: Função de extensão alterada para propriedade. Obrigado Igor Wojda .
1. Crie a seguinte extensão
import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager val FragmentManager.currentNavigationFragment: Fragment? get() = primaryNavigationFragment?.childFragmentManager?.fragments?.first()
2.
Activity
comNavHostFragment
usá-lo como este:val currentFragment = supportFragmentManager.currentNavigationFragment
fonte
FragmentManager.currentNavigationFragment
(não como uma função)Use
addOnDestinationChangedListener
na atividade tendoNavHostFragment
Para Java
NavController navController= Navigation.findNavController(MainActivity.this,R.id.your_nav_host); navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() { @Override public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) { Log.e(TAG, "onDestinationChanged: "+destination.getLabel()); } });
Para Kotlin
var navController :NavController=Navigation.findNavController(this, R.id.nav_host_fragment) navController.addOnDestinationChangedListener { controller, destination, arguments -> Log.e(TAG, "onDestinationChanged: "+destination.label); }
fonte
isso pode ser tarde, mas para quem ainda está procurando
val currentFragment = NavHostFragment.findNavController(nav_host_fragment).currentDestination?.id
então você pode fazer algo como
if(currentFragment == R.id.myFragment){ //do something }
note que isso é para kotlin, o código java deve ser quase o mesmo
fonte
navController().currentDestination?.id
dar-lhe-á o seu
Fragment
id actual ondeprivate fun navController() = Navigation.findNavController(this, R.id.navHostFragment)
este id é o id que você forneceu em seu
Navigation Graph XML
arquivo nafragment
tag. Você também pode comparar,currentDestination.label
se quiser.fonte
Solução de trabalho encontrada.
private fun getCurrentFragment(): Fragment? { val currentNavHost = supportFragmentManager.findFragmentById(R.id.nav_host_id) val currentFragmentClassName = ((this as NavHost).navController.currentDestination as FragmentNavigator.Destination).className return currentNavHost?.childFragmentManager?.fragments?.filterNotNull()?.find { it.javaClass.name == currentFragmentClassName } }
fonte
Meu requisito é obter o fragmento visível atual da atividade pai, minha solução é
private LoginFragment getCurrentVisibleFragment() { NavHostFragment navHostFragment = (NavHostFragment)getSupportFragmentManager().getPrimaryNavigationFragment(); FragmentManager fragmentManager = navHostFragment.getChildFragmentManager(); Fragment loginFragment = fragmentManager.getPrimaryNavigationFragment(); if(loginFragment instanceof LoginFragment){ return (LoginFragment)loginFragment; } return null; }
Isso pode ajudar alguém com o mesmo problema.
fonte
De uma Activity que usa
NavHostFragment
, você pode usar o código abaixo para recuperar a instância doActive Fragment
.val fragmentInstance = myNavHostFragment?.childFragmentManager?.primaryNavigationFragment
fonte
De acordo com a resposta e comentário @slhddn, é assim que estou usando e recuperando o ID do fragmento do arquivo nav_graph.xml :
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setSupportActionBar(findViewById(R.id.toolbar)) val navController = findNavController(this, R.id.nav_host_fragment) ivSettingsCog.setOnClickListener { if (navController.currentDestination?.id == R.id.updatesFragment) // Id as per set up on nav_graph.xml file { navController.navigate(R.id.action_updatesFragment_to_settingsFragment) } } } }
fonte
você pode verificar com uma
getChildFragmentManager()
ligação comNavHostFragment fragment = supportFragmentManager.findFragmentById(R.id.nav_host); MyFragment frag = (MyFragment) fragment.getChildFragmentManager().findFragmentByTag(tag);
fonte
Faço :
• em algum botão em seu fragmento:
val navController = findNavController(this) navController.popBackStack()
• Em sua atividade no BackPressed ()
override fun onBackPressed() { val navController = findNavController(R.id.nav_host_fragment) val id = navController.currentDestination?.getId() if (id == R.id.detailMovieFragment){ navController.popBackStack() return } super.onBackPressed() }
fonte
Se você precisa da instância do seu fragmento, pode ir com:
(Atividade) =>
supportFragmentManager.fragments.first().childFragmentManager.fragments.first()
É muito feio, mas a partir daí você pode verificar se é uma instância do fragmento com o qual deseja brincar
fonte
No Androidx, tentei muitos métodos para descobrir o fragmento necessário
NavHostFragment
. Finalmente eu poderia quebrá-lo com o método abaixopublic Fragment getFunctionalFragment (String tag_name) { NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment); FragmentManager navHostManager = Objects.requireNonNull(navHostFragment).getChildFragmentManager(); Fragment fragment=null; List fragment_list = navHostManager.getFragments(); for (int i=0; i < fragment_list.size() ; i ++ ) { if ( fragment_list.get(i) instanceof HomeFragment && tag_name.equals("frg_home")) { fragment = (HomeFragment) fragment_list.get(i); break; } } return fragment; }
fonte
O primeiro fragmento no fragmento navhost é o fragmento atual
Fragment navHostFragment = getSupportFragmentManager().getPrimaryNavigationFragment(); if (navHostFragment != null) {Fragment fragment = navHostFragment.getChildFragmentManager().getFragments().get(0);}
fonte
Primeiro, você obtém o fragmento atual por id, depois pode encontrar o fragmento, dependendo desse id.
int id = navController.getCurrentDestination().getId(); Fragment fragment = getSupportFragmentManager().findFragmentById(id);
fonte
I combinado Andrei Toaders resposta e resposta Mukul Bhardwajs com um
OnBackStackChangedListener
.Como um atributo:
private FooFragment fragment;
No meu
onCreate
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host); FragmentManager navHostManager = Objects.requireNonNull(navHostFragment).getChildFragmentManager(); FragmentManager.OnBackStackChangedListener listener = () -> { List<Fragment> frags = navHostManager.getFragments(); if(!frags.isEmpty()) { fragment = (FooFragment) frags.get(0); } }; navController.addOnDestinationChangedListener((controller, destination, arguments) -> { if(destination.getId()==R.id.FooFragment){ navHostManager.addOnBackStackChangedListener(listener); } else { navHostManager.removeOnBackStackChangedListener(listener); fragment = null; } });
Assim, consigo um fragmento, que será mostrado mais tarde. Um até pode ser capaz de fazer um loop
frags
e verificar vários fragmentos cominstanceof
.fonte
Preciso fazer isso para configurar uma visualização de navegação inferior e fiz desta forma:
val navController = Navigation.findNavController(requireActivity(), R.id.nav_tabs_home) val bottomNavBar: BottomNavigationView = nav_content_view NavigationUI.setupWithNavController(bottomNavBar, navController)
fonte
A melhor maneira de fazer isso é registrar um retorno de chamada do ciclo de vida do fragmento .
De acordo com a pergunta original, se o seu
NavHostFragment
for definido como ...<fragment android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/nav_host" app:navGraph= "@navigation/nav_item" android:name="androidx.navigation.fragment.NavHostFragment" app:defaultNavHost= "true" />
Então, em sua atividade principal
onCreate(..)
...nav_host.childFragmentManager.registerFragmentLifecycleCallbacks( object:FragmentManager.FragmentLifecycleCallbacks() { override fun onFragmentViewCreated( fm: FragmentManager, f: Fragment, v: View, savedInstanceState: Bundle? ) { // callback method always called whenever a // fragment is added, or, a back-press returns // to the start-destination } } )
Outros métodos de retorno de chamada podem ser substituídos para atender aos seus requisitos.
fonte
Esta solução funcionará na maioria das situações Tente isto:
val mainFragment = fragmentManager?.primaryNavigationFragment?.parentFragment?.parentFragment as MainFragment
ou isto:
val mainFragment = fragmentManager?.primaryNavigationFragment?.parentFragment as MainFragment
fonte
Este código funciona comigo
NavDestination current = NavHostFragment.findNavController(getSupportFragmentManager().getPrimaryNavigationFragment().getFragmentManager().getFragments().get(0)).getCurrentDestination(); switch (current.getId()) { case R.id.navigation_saved: // WRITE CODE break; }
fonte
Isso funciona para mim
(navController.currentDestination as FragmentNavigator.Destination).className
Ele vai voltar
canonicalName
do seu fragmentofonte
isso pode ser tarde, mas pode ajudar alguém mais tarde.
se você estiver usando navegações aninhadas, você pode obter id como este em Kotlin
val nav = Navigation.findNavController(requireActivity(), R.id.fragment_nav_host).currentDestination
e este é um dos fragmentos em fragment_nav_host.xml
<fragment android:id="@+id/sampleFragment" android:name="com.app.sample.SampleFragment" android:label="SampleFragment" tools:layout="@layout/fragment_sample" />
e você pode verificar tudo que precisa assim
if (nav.id == R.id.sampleFragment || nav.label == "SampleFragment"){}
fonte
Finalmente a solução de trabalho para aqueles que ainda estão procurando. Na verdade, é muito simples e você pode conseguir isso usando o callback.
Siga esses passos:
Crie um ouvinte dentro do fragmento que você deseja obter a instância da atividade onCreate ()
public class HomeFragment extends Fragment { private OnCreateFragment createLIstener; public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { createLIstener.onFragmentCreated(this); View root = inflater.inflate(R.layout.fragment_home, container, false); //findViews(root); return root; } @Override public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.menu_main, menu); } @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { if (item.getItemId()==R.id.action_show_filter){ //do something } return super.onOptionsItemSelected(item); } @Override public void onAttach(Context context) { super.onAttach(context); try { createLIstener = (OnCreateFragment) context; } catch (ClassCastException e) { throw new ClassCastException(context.toString() + " must implement OnArticleSelectedListener"); } } public interface OnCreateFragment{ void onFragmentCreated(Fragment f); } }
Implemente seu ouvinte no fragmento / atividade do host
public class MainActivity extends AppCompatActivity implements HomeFragment.OnCreateFragment { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); BottomNavigationView navView = findViewById(R.id.nav_view); // Passing each menu ID as a set of Ids because each // menu should be considered as top level destinations. AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder( R.id.navigation_home, R. ----) .build(); NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment); NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration); NavigationUI.setupWithNavController(navView, navController); } @Override public void onFragmentCreated(Fragment f) { if (f!=null){ H.debug("fragment created listener: "+f.getId()); f.setHasOptionsMenu(true); }else { H.debug("fragment created listener: NULL"); } } }
E isso é tudo de que você precisa para fazer o trabalho. Espero que isso ajude alguém
fonte
A melhor maneira que eu poderia descobrir com 1 fragmento, Kotlin, uso de navegação:
No arquivo de layout, adicione a tag: "android: tag =" main_fragment_tag ""
<fragment android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/nav_host" app:navGraph= "@navigation/nav_item" android:tag="main_fragment_tag" android:name="androidx.navigation.fragment.NavHostFragment" app:defaultNavHost= "true" />
Em sua atividade:
val navHostFragment = supportFragmentManager.findFragmentByTag("main_fragment_tag") as NavHostFragment val mainFragment = navHostFragment.childFragmentManager.fragments[0] as MainFragment mainFragment.mainFragmentMethod()
fonte
val fragment: YourFragment? = yourNavHost.findFragment()
Nota: a
findFragment
função de extensão está localizada noandroidx.fragment.app
pacote e é uma função genéricafonte
Em sua atividade, defina um objeto de fragmento. E a partir de cada fragmento, chame esse método passando o objeto de fragmento, como Então, o objeto de fragmento estático será substituído pelo fragmento de exibição atual todas as vezes.
//method in MainActivity private static Fragment fragment; public void setFragment(Fragment fragment){ this.fragment = fragment; } //And from your fragment class, you can call ((<yourActivity in which fragment present>)getActivity()).setFragment(<your fragment object>); //if you want to set it directly; ((<yourActivity in which fragment present>)getActivity()).fragment=<your fragment object>;
Você também pode definir o retorno de chamada do fragmento para a atividade, para uma melhor abordagem e passar seu objeto de fragmento atual.
fonte