Bevor ich die Navigationskomponente ausprobierte, führte ich Fragmenttransaktionen manuell durch und verwendete das Fragment-Tag, um das aktuelle Fragment abzurufen.
val fragment:MyFragment = supportFragmentManager.findFragmentByTag(tag):MyFragment
Jetzt habe ich in meinem Hauptaktivitätslayout so etwas wie:
<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"
/>
Wie kann ich das aktuell angezeigte Fragment von der Navigationskomponente abrufen? Tun
supportFragmentManager.findFragmentById(R.id.nav_host)
gibt a zurück NavHostFragment
und ich möchte mein angezeigtes 'MyFragment` abrufen.
Vielen Dank.
onActivityResult
meiner Hauptaktivität gewartet . Da ich das Fragment nicht bekommen konnte, habe ich das alles einfach in das Fragment selbst verschoben und scheint zu funktionieren.Antworten:
Ich habe es geschafft, einen Weg für jetzt zu finden und es ist wie folgt:
NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host); navHostFragment.getChildFragmentManager().getFragments().get(0);
Falls Sie natürlich wissen, dass es das erste Fragment ist. Ich untersuche immer noch einen Weg ohne diesen. Ich bin damit einverstanden, dass es nicht der beste Weg ist, aber das sollte vorerst etwas sein.
quelle
navHostFragment!!.childFragmentManager.fragments.any { it.javaClass == fragmentClass && it.isVisible }
Funktioniert ziemlich ähnlich. Hoffe es wird jedem helfen!Ich kann die aktuelle Fragmentinstanz nicht abrufen. Sie können jedoch die ID des zuletzt hinzugefügten Fragments mithilfe des folgenden Codes abrufen.
navController.currentDestination?.getId()
Es gibt die ID in der Navigationsdatei zurück. Hoffe das hilft.
quelle
Sie sollten sich die Eigenschaft childFragmentManager primaryNavigationFragment Ihres Navigationsfragments ansehen. Hier wird auf das aktuell angezeigte Fragment verwiesen.
val navHost = supportFragmentManager.findFragmentById(R.id.main_nav_fragment) navHost?.let { navFragment -> navFragment.childFragmentManager.primaryNavigationFragment?.let {fragment-> //DO YOUR STUFF } } }
quelle
Dies scheint die sauberste Lösung zu sein. Update: Erweiterungsfunktion in Eigenschaft geändert. Danke Igor Wojda .
1. Erstellen Sie die folgende Erweiterung
import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager val FragmentManager.currentNavigationFragment: Fragment? get() = primaryNavigationFragment?.childFragmentManager?.fragments?.first()
2.
Activity
mitNavHostFragment
ihm wie folgt Gebrauch:val currentFragment = supportFragmentManager.currentNavigationFragment
quelle
FragmentManager.currentNavigationFragment
(nicht als Funktion)Verwendung
addOnDestinationChangedListener
bei Aktivitäten mitNavHostFragment
Für 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()); } });
Für Kotlin
var navController :NavController=Navigation.findNavController(this, R.id.nav_host_fragment) navController.addOnDestinationChangedListener { controller, destination, arguments -> Log.e(TAG, "onDestinationChanged: "+destination.label); }
quelle
Dies könnte spät sein, aber für alle, die noch suchen
val currentFragment = NavHostFragment.findNavController(nav_host_fragment).currentDestination?.id
dann kannst du so etwas machen
if(currentFragment == R.id.myFragment){ //do something }
Beachten Sie, dass dies für Kotlin gilt. Der Java-Code sollte fast identisch sein
quelle
navController().currentDestination?.id
geben Sie Ihre aktuelle
Fragment
ID woprivate fun navController() = Navigation.findNavController(this, R.id.navHostFragment)
Diese ID ist die ID, die Sie in Ihrer
Navigation Graph XML
Datei unter demfragment
Tag angegeben haben. Sie können auch vergleichen,currentDestination.label
wenn Sie möchten.quelle
Arbeitslösung gefunden.
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 } }
quelle
In einer Aktivität, die verwendet wird
NavHostFragment
, können Sie den folgenden Code verwenden, um die Instanz von abzurufenActive Fragment
.val fragmentInstance = myNavHostFragment?.childFragmentManager?.primaryNavigationFragment
quelle
Meine Anforderung ist es, das aktuell sichtbare Fragment aus der übergeordneten Aktivität zu erhalten. Meine Lösung lautet
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; }
Dies kann jemandem mit dem gleichen Problem helfen.
quelle
Gemäß @slhddn Antwort und Kommentar verwende ich es so und rufe die Fragment- ID aus der Datei nav_graph.xml ab :
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) } } } }
quelle
können Sie bitte mit
getChildFragmentManager()
Anruf mit überprüfenquelle
Machen :
• in einer Schaltfläche in Ihrem Fragment:
val navController = findNavController(this) navController.popBackStack()
• In Ihrer Aktivität 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() }
quelle
Wenn Sie die Instanz Ihres Fragments benötigen, können Sie Folgendes ausführen:
(Aktivität) =>
supportFragmentManager.fragments.first().childFragmentManager.fragments.first()
Es ist sehr hässlich, aber von dort aus können Sie überprüfen, ob es sich um eine Instanz des Fragments handelt, mit dem Sie herumspielen möchten
quelle
Unter Androidx habe ich viele Methoden ausprobiert, um das erforderliche Fragment aus herauszufinden
NavHostFragment
. Endlich konnte ich es mit der folgenden Methode knackenpublic 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; }
quelle
Das erste Fragment im Navhost-Fragment ist das aktuelle Fragment
Fragment navHostFragment = getSupportFragmentManager().getPrimaryNavigationFragment(); if (navHostFragment != null) {Fragment fragment = navHostFragment.getChildFragmentManager().getFragments().get(0);}
quelle
Zuerst erhalten Sie das aktuelle Fragment anhand der ID, dann können Sie das Fragment abhängig von dieser ID finden.
int id = navController.getCurrentDestination().getId(); Fragment fragment = getSupportFragmentManager().findFragmentById(id);
quelle
Ich kombinierte die Antwort von Andrei Toaders und die Antwort von Mukul Bhardwajs mit einer
OnBackStackChangedListener
.Als Attribut:
private FooFragment fragment;
In meinem
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; } });
Auf diese Weise kann ich ein Fragment erhalten, das später angezeigt wird. Man kann sogar in der Lage sein, eine Schleife zu erstellen
frags
und mehrere Fragmente mit zu überprüfeninstanceof
.quelle
Ich muss dies tun, um eine untere Navigationsansicht einzurichten, und ich habe es folgendermaßen gemacht:
val navController = Navigation.findNavController(requireActivity(), R.id.nav_tabs_home) val bottomNavBar: BottomNavigationView = nav_content_view NavigationUI.setupWithNavController(bottomNavBar, navController)
quelle
Der beste Weg, dies zu erreichen, besteht darin, einen Rückruf des Fragmentlebenszyklus zu registrieren .
Gemäß der ursprünglichen Frage, wenn Ihre
NavHostFragment
definiert ist als ...<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" />
Dann in Ihrer Haupttätigkeit
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 } } )
Andere Rückrufmethoden werden möglicherweise überschrieben, um Ihren Anforderungen zu entsprechen.
quelle
Diese Lösung funktioniert in den meisten Situationen. Versuchen Sie Folgendes:
val mainFragment = fragmentManager?.primaryNavigationFragment?.parentFragment?.parentFragment as MainFragment
oder dieses:
val mainFragment = fragmentManager?.primaryNavigationFragment?.parentFragment as MainFragment
quelle
Dieser Code funktioniert von mir
NavDestination current = NavHostFragment.findNavController(getSupportFragmentManager().getPrimaryNavigationFragment().getFragmentManager().getFragments().get(0)).getCurrentDestination(); switch (current.getId()) { case R.id.navigation_saved: // WRITE CODE break; }
quelle
Das funktioniert bei mir
(navController.currentDestination as FragmentNavigator.Destination).className
Es wird
canonicalName
von Ihrem Fragment zurückkehrenquelle
Dies kann zu spät sein, kann aber später jemandem helfen.
Wenn Sie verschachtelte Navigationen verwenden, können Sie in Kotlin eine solche ID erhalten
val nav = Navigation.findNavController(requireActivity(), R.id.fragment_nav_host).currentDestination
und dies ist eines der Fragmente in fragment_nav_host.xml
<fragment android:id="@+id/sampleFragment" android:name="com.app.sample.SampleFragment" android:label="SampleFragment" tools:layout="@layout/fragment_sample" />
und Sie können alles, was Sie brauchen, so überprüfen
if (nav.id == R.id.sampleFragment || nav.label == "SampleFragment"){}
quelle
Endlich die funktionierende Lösung für diejenigen unter Ihnen, die noch suchen. Eigentlich ist es sehr einfach und Sie können dies durch Rückruf erreichen.
folge diesen Schritten:
Erstellen Sie einen Listener innerhalb des Fragments, für das Sie die Instanz aus der Aktivität onCreate () abrufen möchten.
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); } }
Implementieren Sie Ihren Listener im Host Fragment / Activity
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"); } } }
Und das ist alles, was Sie brauchen, um die Arbeit zu erledigen. Hoffen Sie, dass dies jemandem hilft
quelle
Der beste Weg, den ich mit 1 Fragment, Kotlin, Navigationsnutzung herausfinden konnte:
Fügen Sie in Ihrer Layoutdatei das Tag hinzu: "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" />
Zu Ihrer Aktivität:
val navHostFragment = supportFragmentManager.findFragmentByTag("main_fragment_tag") as NavHostFragment val mainFragment = navHostFragment.childFragmentManager.fragments[0] as MainFragment mainFragment.mainFragmentMethod()
quelle
val fragment: YourFragment? = yourNavHost.findFragment()
Hinweis: Die
findFragment
Erweiterungsfunktion befindet sich imandroidx.fragment.app
Paket und ist eine generische Funktionquelle
Definieren Sie in Ihrer Aktivität ein Fragmentobjekt. Rufen Sie diese Methode von jedem Fragment aus auf, indem Sie ein Fragmentobjekt übergeben, z. B. Das statische Fragmentobjekt wird jedes Mal durch das aktuell angezeigte Fragment überschrieben.
//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>;
Sie können für einen besseren Ansatz auch den Rückruf von Fragment zu Aktivität festlegen und Ihr aktuelles Fragmentobjekt übergeben.
quelle