Przed wypróbowaniem komponentu Nawigacja ręcznie wykonywałem transakcje fragmentaryczne i użyłem znacznika fragmentu, aby pobrać bieżący fragment.
val fragment:MyFragment = supportFragmentManager.findFragmentByTag(tag):MyFragment
Teraz w moim głównym układzie aktywności mam coś takiego:
<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"
/>
Jak mogę odzyskać aktualnie wyświetlany fragment przez komponent nawigacji? Robić
supportFragmentManager.findFragmentById(R.id.nav_host)
zwraca a NavHostFragment
i chcę pobrać pokazany przeze mnie „MyFragment”.
Dziękuję Ci.
onActivityResult
mojej głównej działalności. Ponieważ nie mogłem pobrać fragmentu, po prostu przeniosłem to wszystko do samego fragmentu i wydaje się, że działa.Odpowiedzi:
Na razie udało mi się znaleźć sposób i wygląda to następująco:
NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host); navHostFragment.getChildFragmentManager().getFragments().get(0);
Jeśli oczywiście wiesz, że to pierwszy fragment. Nadal szukam sposobu bez tego. Zgadzam się, że to nie jest najlepszy sposób, ale na razie to powinno być coś.
źródło
navHostFragment!!.childFragmentManager.fragments.any { it.javaClass == fragmentClass && it.isVisible }
Działa dość podobnie. Mam nadzieję, że pomoże to każdemu!Nie ma sposobu, aby znaleźć bieżącą instancję fragmentu. Możesz jednak uzyskać identyfikator ostatnio dodanego fragmentu, korzystając z poniższego kodu.
navController.currentDestination?.getId()
Zwraca identyfikator w pliku nawigacyjnym. Mam nadzieję że to pomoże.
źródło
Powinieneś spojrzeć na właściwość childFragmentManager primaryNavigationFragment fragmentu nawigacji, gdzie znajduje się odniesienie do aktualnie wyświetlanego fragmentu.
val navHost = supportFragmentManager.findFragmentById(R.id.main_nav_fragment) navHost?.let { navFragment -> navFragment.childFragmentManager.primaryNavigationFragment?.let {fragment-> //DO YOUR STUFF } } }
źródło
To wydaje się najczystszym rozwiązaniem. Aktualizacja: zmieniono funkcję rozszerzenia na właściwość. Dzięki Igor Wojda .
1. Utwórz następujące rozszerzenie
import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager val FragmentManager.currentNavigationFragment: Fragment? get() = primaryNavigationFragment?.childFragmentManager?.fragments?.first()
2.
Activity
zNavHostFragment
użytku to tak:val currentFragment = supportFragmentManager.currentNavigationFragment
źródło
FragmentManager.currentNavigationFragment
(nie jako funkcję)Użyj
addOnDestinationChangedListener
w czynnościach mającychNavHostFragment
W przypadku języka 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()); } });
Dla Kotlina
var navController :NavController=Navigation.findNavController(this, R.id.nav_host_fragment) navController.addOnDestinationChangedListener { controller, destination, arguments -> Log.e(TAG, "onDestinationChanged: "+destination.label); }
źródło
to może być późno, ale dla każdego, kto wciąż szuka
val currentFragment = NavHostFragment.findNavController(nav_host_fragment).currentDestination?.id
wtedy możesz zrobić coś takiego
if(currentFragment == R.id.myFragment){ //do something }
zauważ, że to jest dla kotlin, kod java powinien być prawie taki sam
źródło
navController().currentDestination?.id
poda ci
Fragment
identyfikator twojego obecnego gdzieprivate fun navController() = Navigation.findNavController(this, R.id.navHostFragment)
ten identyfikator to identyfikator, który podałeś w swoim
Navigation Graph XML
pliku podfragment
tagiem. Możesz też porównać,currentDestination.label
jeśli chcesz.źródło
Znalazłem działające rozwiązanie.
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 } }
źródło
Moim wymaganiem jest pobranie aktualnie widocznego fragmentu z Aktywności rodzica, moim rozwiązaniem jest
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; }
Może to pomóc komuś z tym samym problemem.
źródło
Z działania, które używa
NavHostFragment
, możesz użyć poniższego kodu, aby pobrać wystąpienieActive Fragment
.val fragmentInstance = myNavHostFragment?.childFragmentManager?.primaryNavigationFragment
źródło
Zgodnie z odpowiedzią i komentarzem @slhddn, używam go w następujący sposób i pobieram identyfikator fragmentu z pliku 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) } } } }
źródło
czy możesz sprawdzić,
getChildFragmentManager()
dzwoniąc zNavHostFragment fragment = supportFragmentManager.findFragmentById(R.id.nav_host); MyFragment frag = (MyFragment) fragment.getChildFragmentManager().findFragmentByTag(tag);
źródło
Robić :
• w jakimś przycisku w Twoim fragmencie:
val navController = findNavController(this) navController.popBackStack()
• W Twojej Aktywności onBackPressed ()
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() }
źródło
Jeśli potrzebujesz instancji swojego fragmentu, możesz skorzystać z:
(Aktywność) =>
supportFragmentManager.fragments.first().childFragmentManager.fragments.first()
Jest bardzo brzydki, ale stamtąd możesz sprawdzić, czy jest to instancja fragmentu, z którym chcesz się pobawić
źródło
Na Androidx próbowałem wielu metod wyszukiwania wymaganego fragmentu z
NavHostFragment
. Wreszcie mogłem to złamać poniższą metodąpublic 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; }
źródło
Pierwszy fragment we fragmencie navhost jest fragmentem bieżącym
Fragment navHostFragment = getSupportFragmentManager().getPrimaryNavigationFragment(); if (navHostFragment != null) {Fragment fragment = navHostFragment.getChildFragmentManager().getFragments().get(0);}
źródło
Najpierw otrzymujesz aktualny fragment przez id, potem możesz znaleźć fragment, w zależności od tego id.
int id = navController.getCurrentDestination().getId(); Fragment fragment = getSupportFragmentManager().findFragmentById(id);
źródło
I połączeniu Andrei Toaders odpowiedź i Mukul Bhardwajs odpowiedź ze związkiem
OnBackStackChangedListener
.Jako atrybut:
private FooFragment fragment;
W moim
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; } });
W ten sposób mogę uzyskać fragment, który zostanie wyświetlony później. Można nawet zapętlić
frags
i sprawdzić wiele fragmentów za pomocąinstanceof
.źródło
Muszę to zrobić, aby ustawić dolny widok nawigacji i zrobiłem to w ten sposób:
val navController = Navigation.findNavController(requireActivity(), R.id.nav_tabs_home) val bottomNavBar: BottomNavigationView = nav_content_view NavigationUI.setupWithNavController(bottomNavBar, navController)
źródło
Najlepszym sposobem na osiągnięcie tego jest zarejestrowanie wywołania zwrotnego cyklu życia fragmentu .
Zgodnie z pierwotnym pytaniem, jeśli twój
NavHostFragment
jest zdefiniowany jako ...<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" />
Następnie w swojej głównej działalności
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 } } )
Inne metody wywołania zwrotnego mogą zostać zastąpione, aby pasowały do twoich wymagań.
źródło
To rozwiązanie zadziała w większości sytuacji Spróbuj tego:
val mainFragment = fragmentManager?.primaryNavigationFragment?.parentFragment?.parentFragment as MainFragment
albo to:
val mainFragment = fragmentManager?.primaryNavigationFragment?.parentFragment as MainFragment
źródło
Ten kod działa ode mnie
NavDestination current = NavHostFragment.findNavController(getSupportFragmentManager().getPrimaryNavigationFragment().getFragmentManager().getFragments().get(0)).getCurrentDestination(); switch (current.getId()) { case R.id.navigation_saved: // WRITE CODE break; }
źródło
To działa dla mnie
(navController.currentDestination as FragmentNavigator.Destination).className
Zwróci
canonicalName
twój fragmentźródło
to może być późno, ale może pomóc komuś później.
jeśli używasz zagnieżdżonych nawigacji, możesz uzyskać taki identyfikator w Kotlinie
val nav = Navigation.findNavController(requireActivity(), R.id.fragment_nav_host).currentDestination
a to jest jeden z fragmentów w fragment_nav_host.xml
<fragment android:id="@+id/sampleFragment" android:name="com.app.sample.SampleFragment" android:label="SampleFragment" tools:layout="@layout/fragment_sample" />
i w ten sposób możesz sprawdzić wszystko, czego potrzebujesz
if (nav.id == R.id.sampleFragment || nav.label == "SampleFragment"){}
źródło
Wreszcie działające rozwiązanie dla tych z Was, którzy wciąż szukają. W rzeczywistości jest to bardzo proste i można to osiągnąć za pomocą oddzwaniania.
wykonaj następujące kroki:
Utwórz detektor wewnątrz fragmentu, dla którego chcesz pobrać instancję z działania 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); } }
Zaimplementuj odbiornik we fragmencie / działaniu hosta
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"); } } }
I to wszystko, czego potrzebujesz do wykonania tej pracy. Mam nadzieję, że komuś to pomoże
źródło
Najlepszy sposób, w jaki mogłem się dowiedzieć z 1 fragmentem, Kotlin, użycie nawigacji:
W pliku układu dodaj 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" />
W Twojej aktywności:
val navHostFragment = supportFragmentManager.findFragmentByTag("main_fragment_tag") as NavHostFragment val mainFragment = navHostFragment.childFragmentManager.fragments[0] as MainFragment mainFragment.mainFragmentMethod()
źródło
val fragment: YourFragment? = yourNavHost.findFragment()
Uwaga:
findFragment
funkcja rozszerzenia znajduje się wandroidx.fragment.app
pakiecie i jest to funkcja ogólnaźródło
W swojej działalności zdefiniuj obiekt fragmentu. Z każdego fragmentu wywołaj tę metodę, przekazując obiekt fragmentu, na przykład obiekt statycznego fragmentu zostanie za każdym razem nadpisany przez bieżący fragment pokazujący.
//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>;
Możesz również ustawić wywołanie zwrotne z fragmentu do działania, aby uzyskać lepsze podejście i przekazać bieżący obiekt fragmentu.
źródło