Android 导航架构组件 - 获取当前可见片段
Android Navigation Architecture Component - Get current visible fragment
在尝试导航组件之前,我曾经手动执行片段事务并使用片段标记来获取当前片段。
val fragment:MyFragment = supportFragmentManager.findFragmentByTag(tag):MyFragment
现在在我的主要 activity 布局中,我有类似的内容:
<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"
/>
如何获取导航组件当前显示的片段?
做
supportFragmentManager.findFragmentById(R.id.nav_host)
returns a NavHostFragment
我想检索显示的“MyFragment”。
谢谢。
你能用 getChildFragmentManager()
和
打电话确认一下吗
NavHostFragment fragment = supportFragmentManager.findFragmentById(R.id.nav_host);
MyFragment frag = (MyFragment) fragment.getChildFragmentManager().findFragmentByTag(tag);
我无法找到检索当前片段实例的方法。但是,您可以使用下面的代码获取最后添加的片段的 ID。
navController.currentDestination?.getId()
它returns导航文件中的ID。希望这有帮助。
在您的 activity 中定义一个片段对象。并通过传递片段对象从每个片段调用此方法,例如
所以静态片段对象每次都会被当前显示的片段覆盖。
//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>;
您还可以将片段的回调设置为 activity,以获得更好的方法并传递您当前的片段对象。
我暂时找到了一个方法,如下:
NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host);
navHostFragment.getChildFragmentManager().getFragments().get(0);
万一你当然知道这是第一个片段。我仍在研究没有这个的方法。我同意这不是最好的方法,但现在应该是这样。
您应该查看导航片段的 childFragmentManager primaryNavigationFragment 属性,这是引用当前显示的片段的地方。
val navHost = supportFragmentManager.findFragmentById(R.id.main_nav_fragment)
navHost?.let { navFragment ->
navFragment.childFragmentManager.primaryNavigationFragment?.let {fragment->
//DO YOUR STUFF
}
}
}
找到可行的解决方案。
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
}
}
在 activity 中使用 addOnDestinationChangedListener
有 NavHostFragment
对于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());
}
});
对于 Kotlin
var navController :NavController=Navigation.findNavController(this, R.id.nav_host_fragment)
navController.addOnDestinationChangedListener { controller, destination, arguments ->
Log.e(TAG, "onDestinationChanged: "+destination.label);
}
这可能会迟到,但对于仍在寻找的人来说
val currentFragment = NavHostFragment.findNavController(nav_host_fragment).currentDestination?.id
然后你可以做类似的事情
if(currentFragment == R.id.myFragment){
//do something
}
注意这是针对kotlin的,java代码应该差不多
我将 and 与 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
.
检查多个片段
我需要这样做来设置底部导航视图,我是这样做的:
val navController = Navigation.findNavController(requireActivity(), R.id.nav_tabs_home)
val bottomNavBar: BottomNavigationView = nav_content_view
NavigationUI.setupWithNavController(bottomNavBar, navController)
首先,您通过id获取当前片段,然后您可以根据该id找到片段。
int id = navController.getCurrentDestination().getId();
Fragment fragment = getSupportFragmentManager().findFragmentById(id);
这似乎是最干净的解决方案。 更新: 将扩展功能更改为 属性。谢谢Igor Wojda.
1.创建以下扩展
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
val FragmentManager.currentNavigationFragment: Fragment?
get() = primaryNavigationFragment?.childFragmentManager?.fragments?.first()
2。在 Activity
和 NavHostFragment
中,像这样使用它:
val currentFragment = supportFragmentManager.currentNavigationFragment
实现此目的的最佳方法是注册一个片段生命周期回调。
根据最初的问题,如果您的 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"
/>
然后在你的主 activity 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
}
}
)
可能会覆盖其他回调方法以满足您的要求。
制作:
• 在您的片段中的某个按钮中:
val navController = findNavController(this)
navController.popBackStack()
• 在您的 Activity 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()
}
如果您需要片段的实例,可以使用:
(Activity) => supportFragmentManager.fragments.first().childFragmentManager.fragments.first()
它非常丑陋,但从那里您可以检查它是否是您想要玩弄的片段的实例
在 Androidx 上,我尝试了很多方法从 NavHostFragment
中找出所需的片段。最后我可以用下面的方法破解它
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;
}
navController().currentDestination?.id
将为您提供当前 Fragment
的 ID,其中
private fun navController() = Navigation.findNavController(this, R.id.navHostFragment)
此 ID 是您在 Navigation Graph XML
文件中 fragment
标签下提供的 ID。如果需要,您也可以比较 currentDestination.label
。
从使用 NavHostFragment
的 Activity,您可以使用下面的代码检索 Active Fragment
.
的实例
val fragmentInstance = myNavHostFragment?.childFragmentManager?.primaryNavigationFragment
navhost 片段中的第一个片段是当前片段
Fragment navHostFragment = getSupportFragmentManager().getPrimaryNavigationFragment();
if (navHostFragment != null)
{Fragment fragment = navHostFragment.getChildFragmentManager().getFragments().get(0);}
这段代码对我有效
NavDestination current = NavHostFragment.findNavController(getSupportFragmentManager().getPrimaryNavigationFragment().getFragmentManager().getFragments().get(0)).getCurrentDestination();
switch (current.getId()) {
case R.id.navigation_saved:
// WRITE CODE
break;
}
此解决方案适用于大多数情况
试试这个:
val mainFragment = fragmentManager?.primaryNavigationFragment?.parentFragment?.parentFragment as MainFragment
或者这个:
val mainFragment = fragmentManager?.primaryNavigationFragment?.parentFragment as MainFragment
这对我有用
(navController.currentDestination as FragmentNavigator.Destination).className
它会 return canonicalName
你的片段
我的要求是从父activity获取当前可见片段,我的解决方案是
private Fragment getCurrentVisibleFragment() {
NavHostFragment navHostFragment = (NavHostFragment)getSupportFragmentManager().getPrimaryNavigationFragment();
FragmentManager fragmentManager = navHostFragment.getChildFragmentManager();
Fragment fragment = fragmentManager.getPrimaryNavigationFragment();
if(fragment instanceof Fragment ){
return fragment ;
}
return null;
}
这可能会对遇到同样问题的人有所帮助。
这可能会迟到,但可能会对以后的人有所帮助。
如果您使用嵌套导航,您可以在 Kotlin 中获得这样的 ID
val nav = Navigation.findNavController(requireActivity(), R.id.fragment_nav_host).currentDestination
这是fragment_nav_host.xml
中的片段之一
<fragment
android:id="@+id/sampleFragment"
android:name="com.app.sample.SampleFragment"
android:label="SampleFragment"
tools:layout="@layout/fragment_sample" />
你可以像这样检查所有你需要的
if (nav.id == R.id.sampleFragment || nav.label == "SampleFragment"){}
根据@slhddn 的回答和评论,这就是我使用它并从 nav_graph.xml 文件中检索片段 id 的方式:
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)
}
}
}
}
终于为那些仍在寻找的人提供了可行的解决方案
其实很简单,用回调就可以实现。
按照以下步骤操作:
在要从 activity 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);
}
}
在宿主中实现你的监听器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");
}
}
}
这就是您完成这项工作所需的一切。
希望这对某人有帮助
我能用 1 个片段、Kotlin、导航用法找到的最佳方法:
在您的布局文件中添加标签:“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"
/>
你的 Activity:
val navHostFragment = supportFragmentManager.findFragmentByTag("main_fragment_tag") as NavHostFragment
val mainFragment = navHostFragment.childFragmentManager.fragments[0] as MainFragment
mainFragment.mainFragmentMethod()
val fragment: YourFragment? = yourNavHost.findFragment()
注意:findFragment
扩展函数位于androidx.fragment.app
包中,是通用函数
使用导航组件,我使用这行代码获取了当前显示的片段:
val fragment = parentFragmentManager.primaryNavigationFragment
这是我针对 java
的解决方案
NavHostFragment navHostFragment= (NavHostFragment) getSupportFragmentManager().getFragments().get(0);
MyFragment fragment = (MyFragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
fragment.doSomething();
在您的 activity 中,托管 NavHostFragment 我们可以编写以下代码来获取当前显示的片段的实例
Fragment fragment = myNavHostFragment.getChildFragmentManager().findFragmentById(R.id.navHostFragmentId)
if(fragment instanceOf MyFragment) {
//Write your code here
}
此处 R.id.navHostFragmentId 是 activity xml[ 中 NavHostFragment 的 resId =11=]
在片段管理器上创建扩展函数
inline fun <reified T : Fragment> FragmentManager.findNavFragment(hostId: Int): T? {
val navHostFragment = findFragmentById(hostId)
return navHostFragment?.childFragmentManager?.fragments?.findLast {
it is T
} as T?
}
现在只需提供托管片段的 id 即可使用它并获取指定的片段
val myFragment: MyFragment? = supportFragmentManager.findNavFragment<MyFragment>(R.id.nav_host_id)
在尝试导航组件之前,我曾经手动执行片段事务并使用片段标记来获取当前片段。
val fragment:MyFragment = supportFragmentManager.findFragmentByTag(tag):MyFragment
现在在我的主要 activity 布局中,我有类似的内容:
<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"
/>
如何获取导航组件当前显示的片段? 做
supportFragmentManager.findFragmentById(R.id.nav_host)
returns a NavHostFragment
我想检索显示的“MyFragment”。
谢谢。
你能用 getChildFragmentManager()
和
NavHostFragment fragment = supportFragmentManager.findFragmentById(R.id.nav_host);
MyFragment frag = (MyFragment) fragment.getChildFragmentManager().findFragmentByTag(tag);
我无法找到检索当前片段实例的方法。但是,您可以使用下面的代码获取最后添加的片段的 ID。
navController.currentDestination?.getId()
它returns导航文件中的ID。希望这有帮助。
在您的 activity 中定义一个片段对象。并通过传递片段对象从每个片段调用此方法,例如 所以静态片段对象每次都会被当前显示的片段覆盖。
//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>;
您还可以将片段的回调设置为 activity,以获得更好的方法并传递您当前的片段对象。
我暂时找到了一个方法,如下:
NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host);
navHostFragment.getChildFragmentManager().getFragments().get(0);
万一你当然知道这是第一个片段。我仍在研究没有这个的方法。我同意这不是最好的方法,但现在应该是这样。
您应该查看导航片段的 childFragmentManager primaryNavigationFragment 属性,这是引用当前显示的片段的地方。
val navHost = supportFragmentManager.findFragmentById(R.id.main_nav_fragment)
navHost?.let { navFragment ->
navFragment.childFragmentManager.primaryNavigationFragment?.let {fragment->
//DO YOUR STUFF
}
}
}
找到可行的解决方案。
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
}
}
在 activity 中使用 addOnDestinationChangedListener
有 NavHostFragment
对于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());
}
});
对于 Kotlin
var navController :NavController=Navigation.findNavController(this, R.id.nav_host_fragment)
navController.addOnDestinationChangedListener { controller, destination, arguments ->
Log.e(TAG, "onDestinationChanged: "+destination.label);
}
这可能会迟到,但对于仍在寻找的人来说
val currentFragment = NavHostFragment.findNavController(nav_host_fragment).currentDestination?.id
然后你可以做类似的事情
if(currentFragment == R.id.myFragment){
//do something
}
注意这是针对kotlin的,java代码应该差不多
我将 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
.
我需要这样做来设置底部导航视图,我是这样做的:
val navController = Navigation.findNavController(requireActivity(), R.id.nav_tabs_home)
val bottomNavBar: BottomNavigationView = nav_content_view
NavigationUI.setupWithNavController(bottomNavBar, navController)
首先,您通过id获取当前片段,然后您可以根据该id找到片段。
int id = navController.getCurrentDestination().getId();
Fragment fragment = getSupportFragmentManager().findFragmentById(id);
这似乎是最干净的解决方案。 更新: 将扩展功能更改为 属性。谢谢Igor Wojda.
1.创建以下扩展
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
val FragmentManager.currentNavigationFragment: Fragment?
get() = primaryNavigationFragment?.childFragmentManager?.fragments?.first()
2。在 Activity
和 NavHostFragment
中,像这样使用它:
val currentFragment = supportFragmentManager.currentNavigationFragment
实现此目的的最佳方法是注册一个片段生命周期回调。
根据最初的问题,如果您的 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"
/>
然后在你的主 activity 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
}
}
)
可能会覆盖其他回调方法以满足您的要求。
制作:
• 在您的片段中的某个按钮中:
val navController = findNavController(this)
navController.popBackStack()
• 在您的 Activity 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()
}
如果您需要片段的实例,可以使用:
(Activity) => supportFragmentManager.fragments.first().childFragmentManager.fragments.first()
它非常丑陋,但从那里您可以检查它是否是您想要玩弄的片段的实例
在 Androidx 上,我尝试了很多方法从 NavHostFragment
中找出所需的片段。最后我可以用下面的方法破解它
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;
}
navController().currentDestination?.id
将为您提供当前 Fragment
的 ID,其中
private fun navController() = Navigation.findNavController(this, R.id.navHostFragment)
此 ID 是您在 Navigation Graph XML
文件中 fragment
标签下提供的 ID。如果需要,您也可以比较 currentDestination.label
。
从使用 NavHostFragment
的 Activity,您可以使用下面的代码检索 Active Fragment
.
val fragmentInstance = myNavHostFragment?.childFragmentManager?.primaryNavigationFragment
navhost 片段中的第一个片段是当前片段
Fragment navHostFragment = getSupportFragmentManager().getPrimaryNavigationFragment();
if (navHostFragment != null)
{Fragment fragment = navHostFragment.getChildFragmentManager().getFragments().get(0);}
这段代码对我有效
NavDestination current = NavHostFragment.findNavController(getSupportFragmentManager().getPrimaryNavigationFragment().getFragmentManager().getFragments().get(0)).getCurrentDestination();
switch (current.getId()) {
case R.id.navigation_saved:
// WRITE CODE
break;
}
此解决方案适用于大多数情况 试试这个:
val mainFragment = fragmentManager?.primaryNavigationFragment?.parentFragment?.parentFragment as MainFragment
或者这个:
val mainFragment = fragmentManager?.primaryNavigationFragment?.parentFragment as MainFragment
这对我有用
(navController.currentDestination as FragmentNavigator.Destination).className
它会 return canonicalName
你的片段
我的要求是从父activity获取当前可见片段,我的解决方案是
private Fragment getCurrentVisibleFragment() {
NavHostFragment navHostFragment = (NavHostFragment)getSupportFragmentManager().getPrimaryNavigationFragment();
FragmentManager fragmentManager = navHostFragment.getChildFragmentManager();
Fragment fragment = fragmentManager.getPrimaryNavigationFragment();
if(fragment instanceof Fragment ){
return fragment ;
}
return null;
}
这可能会对遇到同样问题的人有所帮助。
这可能会迟到,但可能会对以后的人有所帮助。
如果您使用嵌套导航,您可以在 Kotlin 中获得这样的 ID
val nav = Navigation.findNavController(requireActivity(), R.id.fragment_nav_host).currentDestination
这是fragment_nav_host.xml
中的片段之一<fragment
android:id="@+id/sampleFragment"
android:name="com.app.sample.SampleFragment"
android:label="SampleFragment"
tools:layout="@layout/fragment_sample" />
你可以像这样检查所有你需要的
if (nav.id == R.id.sampleFragment || nav.label == "SampleFragment"){}
根据@slhddn 的回答和评论,这就是我使用它并从 nav_graph.xml 文件中检索片段 id 的方式:
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)
}
}
}
}
终于为那些仍在寻找的人提供了可行的解决方案 其实很简单,用回调就可以实现。
按照以下步骤操作:
在要从 activity 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); } }
在宿主中实现你的监听器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"); } } }
这就是您完成这项工作所需的一切。 希望这对某人有帮助
我能用 1 个片段、Kotlin、导航用法找到的最佳方法:
在您的布局文件中添加标签:“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"
/>
你的 Activity:
val navHostFragment = supportFragmentManager.findFragmentByTag("main_fragment_tag") as NavHostFragment
val mainFragment = navHostFragment.childFragmentManager.fragments[0] as MainFragment
mainFragment.mainFragmentMethod()
val fragment: YourFragment? = yourNavHost.findFragment()
注意:findFragment
扩展函数位于androidx.fragment.app
包中,是通用函数
使用导航组件,我使用这行代码获取了当前显示的片段:
val fragment = parentFragmentManager.primaryNavigationFragment
这是我针对 java
的解决方案 NavHostFragment navHostFragment= (NavHostFragment) getSupportFragmentManager().getFragments().get(0);
MyFragment fragment = (MyFragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
fragment.doSomething();
在您的 activity 中,托管 NavHostFragment 我们可以编写以下代码来获取当前显示的片段的实例
Fragment fragment = myNavHostFragment.getChildFragmentManager().findFragmentById(R.id.navHostFragmentId)
if(fragment instanceOf MyFragment) {
//Write your code here
}
此处 R.id.navHostFragmentId 是 activity xml[ 中 NavHostFragment 的 resId =11=]
在片段管理器上创建扩展函数
inline fun <reified T : Fragment> FragmentManager.findNavFragment(hostId: Int): T? {
val navHostFragment = findFragmentById(hostId)
return navHostFragment?.childFragmentManager?.fragments?.findLast {
it is T
} as T?
}
现在只需提供托管片段的 id 即可使用它并获取指定的片段
val myFragment: MyFragment? = supportFragmentManager.findNavFragment<MyFragment>(R.id.nav_host_id)