Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android导航架构组件-获取当前可见片段_Android_Android Navigation_Android Jetpack - Fatal编程技术网

Android导航架构组件-获取当前可见片段

Android导航架构组件-获取当前可见片段,android,android-navigation,android-jetpack,Android,Android Navigation,Android Jetpack,在尝试导航组件之前,我曾经手动执行片段事务,并使用片段标记来获取当前片段 val fragment:MyFragment=supportFragmentManager.findFragmentByTag(标记):MyFragment 现在,在我的主要活动布局中,我有如下内容: <fragment android:layout_width="match_parent" android:layout_height="match_parent" a

在尝试导航组件之前,我曾经手动执行片段事务,并使用片段标记来获取当前片段

val fragment:MyFragment=supportFragmentManager.findFragmentByTag(标记):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"
        />

如何通过导航组件检索当前显示的片段? 做

supportFragmentManager.findFragmentById(R.id.nav\u主机)

返回一个
NavHostFragment
,我想检索显示的“MyFragment”


谢谢。

您能与
getChildFragmentManager()联系吗

NavHostFragment fragment = supportFragmentManager.findFragmentById(R.id.nav_host);
MyFragment frag = (MyFragment) fragment.getChildFragmentManager().findFragmentByTag(tag);

我无法找到检索当前片段实例的方法。但是,您可以使用下面的代码获取最后添加的片段的ID

navController.currentDestination?.getId()

它返回导航文件中的ID。希望这能有所帮助。

我现在设法找到了一种方法,如下所示:

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
    }
}

在具有
NavHostFragment的活动中使用
addOnDestinationChangedListener

适用于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);

    }
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager

val FragmentManager.currentNavigationFragment: Fragment?
    get() = primaryNavigationFragment?.childFragmentManager?.fragments?.first()

这可能已经很晚了,但对于那些仍在寻找的人来说

val currentFragment = NavHostFragment.findNavController(nav_host_fragment).currentDestination?.id
然后你可以做类似的事情

if(currentFragment == R.id.myFragment){
     //do something
}
请注意,这是针对kotlin的,java代码应该与我组合的java代码几乎相同,并且带有一个
onbackbackbackchangedListener

作为属性:

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;
        }
});
NavHostFragment NavHostFragment=(NavHostFragment)getSupportFragmentManager().findFragmentById(R.id.nav_主机);
FragmentManager navHostManager=Objects.requireNonNull(navHostFragment.getChildFragmentManager();
FragmentManager.OnBackbackChangedListener侦听器=()->{
List frags=navHostManager.getFragments();
如果(!frags.isEmpty()){
fragment=(FooFragment)frags.get(0);
}
};
navController.addOnDestinationChangedListener((控制器、目标、参数)->{
if(destination.getId()==R.id.FooFragment){
navHostManager.addonbackbackchangedListener(侦听器);
}否则{
navHostManager.RemoveOnBackbackChangedListener(侦听器);
片段=空;
}
});
这样我就可以得到一个片段,稍后会显示出来。
您甚至可以循环查看
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);

这似乎是最干净的解决方案更新:将扩展函数更改为属性。谢谢

1。创建以下扩展名

var navController :NavController=Navigation.findNavController(this, R.id.nav_host_fragment)
    navController.addOnDestinationChangedListener { controller, destination, arguments ->
        Log.e(TAG, "onDestinationChanged: "+destination.label);

    }
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"
        />
其他回调方法可能会被覆盖以满足您的要求。

Make:

•在片段中的某些按钮中:

val navController = findNavController(this)
  navController.popBackStack()
•在您的活动中,按一下()


如果需要片段的实例,可以使用:

(活动)=>
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;
}
公共片段getFunctionalFragment(字符串标记\u名称)
{
NavHostFragment NavHostFragment=(NavHostFragment)getSupportFragmentManager();
FragmentManager navHostManager=Objects.requireNonNull(navHostFragment.getChildFragmentManager();
片段=空;
List fragment_List=navHostManager.getFragments();
对于(int i=0;i
将为您提供当前
片段的id,其中

private fun navController() = Navigation.findNavController(this, R.id.navHostFragment)


此id是您在
片段
标记下的
导航图XML
文件中给定的id。如果需要,您还可以比较
currentDestination.label

从使用
NavHostFragment
的活动中,您可以使用下面的代码检索
活动片段的实例

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 

它将返回片段的
canonicalName

我的要求是从父活动获取当前可见的片段,我的解决方案是

 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;
    }

这可能会帮助有同样问题的人。

这可能会很晚,但可能会帮助以后的人

如果您使用的是嵌套导航,那么可以在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" />

根据@slhddn answer and comment,这就是我如何使用它并从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)
        }

    }

}

}
最后是工作
if (nav.id == R.id.sampleFragment || nav.label == "SampleFragment"){}
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)
        }

    }

}

}
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);
    }
}
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");
        }
    }
}
<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"
        />
val navHostFragment = supportFragmentManager.findFragmentByTag("main_fragment_tag") as NavHostFragment
val mainFragment = navHostFragment.childFragmentManager.fragments[0] as MainFragment
mainFragment.mainFragmentMethod()
val fragment: YourFragment? = yourNavHost.findFragment()
val fragment = parentFragmentManager.primaryNavigationFragment
    NavHostFragment  navHostFragment= (NavHostFragment) getSupportFragmentManager().getFragments().get(0);
    MyFragment  fragment = (MyFragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
    fragment.doSomething();
Fragment fragment = myNavHostFragment.getChildFragmentManager().findFragmentById(R.id.navHostFragmentId)
if(fragment instanceOf MyFragment) {
  //Write your code here
}