Компонент архитектуры Android Navigation - получить текущий видимый фрагмент
Перед попыткой компонента Navigation я использовал для ручного выполнения транзакций фрагментов и использовал тег фрагмента для извлечения текущего фрагмента.
val fragment:MyFragment = supportFragmentManager.findFragmentByTag(tag):MyFragment
Теперь в моем основном макете деятельности у меня есть что-то вроде:
<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"
/>
Как я могу получить текущий отображаемый фрагмент компонентом Navigation? дела
supportFragmentManager.findFragmentById(R.id.nav_host)
возвращает NavHostFragment
и я хочу получить показанный "MyFragment".
Спасибо.
Ответы
Ответ 1
Мне удалось найти способ на данный момент, и он выглядит следующим образом:
NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host);
navHostFragment.getChildFragmentManager().getFragments().get(0);
В случае, конечно, вы знаете, что это первый фрагмент. Я все еще изучаю путь без этого. Я согласен, что это не лучший способ, но на данный момент это должно быть что-то.
Ответ 2
Я не могу найти, чтобы извлечь текущий экземпляр фрагмента. Однако вы можете получить идентификатор последнего добавленного фрагмента, используя следующий код.
navController.getCurrentDestination().getId()
Он возвращает идентификатор в файле навигации. Надеюсь это поможет.
Ответ 3
Вы должны смотреть свойство childFragmentManager primaryNavigationFragment вашего навигационного фрагмента, здесь находится ссылка на текущий отображаемый фрагмент.
val navHost = supportFragmentManager.findFragmentById(R.id.main_nav_fragment)
navHost?.let { navFragment ->
navFragment.childFragmentManager.primaryNavigationFragment?.let {fragment->
//DO YOUR STUFF
}
}
}
Ответ 4
это может быть поздно, но для тех, кто все еще ищет
val currentfraagment=NavHostFragment.findNavController(nav_host_fragment).currentDestination!!.id
тогда вы можете сделать что-то вроде
if(currentfraagment == R.id.myFragemnt){
//do something
}
обратите внимание, что это для kotlin, код Java должен быть почти таким же
Ответ 5
Нашел рабочее решение.
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
}
}
Ответ 6
Используйте addOnDestinationChangedListener
в деятельности, имеющей NavHostFragment
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());
}
});
Ответ 7
вы можете проверить с помощью вызова getChildFragmentManager()
с
NavHostFragment fragment = supportFragmentManager.findFragmentById(R.id.nav_host);
MyFragment frag = (MyFragment) fragment.getChildFragmentManager().findFragmentByTag(tag);
Ответ 8
Это кажется самым чистым решением.
1. Создайте следующее расширение
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
fun FragmentManager.getCurrentNavigationFragment(): Fragment? =
primaryNavigationFragment?.childFragmentManager?.fragments?.first()
2. В Activity
с NavHostFragment
используйте это так:
val currentFragment = supportFragmentManager.getCurrentNavigationFragment()
Ответ 9
В вашей деятельности определите объект фрагмента. И из каждого фрагмента вызывается этот метод, передавая объект фрагмента, например So, поэтому объект статического фрагмента будет переопределен текущим отображающим фрагментом каждый раз.
//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>;
Вы также можете установить обратный вызов из фрагмента в действие, для лучшего подхода и передачи вашего текущего объекта фрагмента.
Ответ 10
Я объединил ответ Андрея Тоадера и Мукула OnBackStackChangedListener
с OnBackStackChangedListener
.
В качестве атрибута:
private FooFragment fragment;
В моем 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;
}
});
Таким образом, я могу получить фрагмент, который будет отображаться позже. Можно даже frags
фрагменты и проверить несколько фрагментов с помощью instanceof
.
Ответ 11
Мне нужно сделать это, чтобы настроить вид нижней навигации, и я сделал это следующим образом:
val navController = Navigation.findNavController(requireActivity(), R.id.nav_tabs_home)
val bottomNavBar: BottomNavigationView = nav_content_view
NavigationUI.setupWithNavController(bottomNavBar, navController)
Ответ 12
Сначала вы получаете текущий фрагмент по идентификатору, затем вы можете найти фрагмент в зависимости от этого идентификатора.
int id = navController.getCurrentDestination().getId();
Fragment fragment = getSupportFragmentManager().findFragmentById(id)l
Ответ 13
Лучший способ добиться этого - зарегистрировать обратный вызов жизненного цикла фрагмента.
Согласно первоначальному вопросу, если ваш NavHostFragment
определен как...
<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"
/>
Тогда в своей основной деятельности 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
}
}
)
Другие методы обратного вызова могут быть переопределены в соответствии с вашими требованиями.
Ответ 14
Сделать:
• в какой-то кнопке в вашем фрагменте:
val navController = findNavController(this)
navController.popBackStack()
• В вашей активности 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()
}
Ответ 15
Если вам нужен экземпляр вашего фрагмента, вы можете использовать:
(Деятельность) => supportFragmentManager.fragments.first().childFragmentManager.fragments.first()
Это очень уродливо, но оттуда вы можете проверить, является ли это фрагмент фрагмента, с которым вы хотите поиграть
Ответ 16
Чтобы получить текущий фрагмент, вы можете вызвать метод getPrimaryNavigationFragment()
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.nav_host)
.getChildFragmentManager().getPrimaryNavigationFragment();