如何从一个fragment打开另一个新的fragment?

96

我尝试在不同的片段之间创建导航。我已经将 NewFragment.java 与新的片段配合使用。我的问题是:

如何使这个 onClickListener 正确地运行 NewFragment.java

button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {

        Intent i = new Intent(getActivity(), NewFragment.class);
        startActivity(i);

    }
});

注意:这是在一个片段内部(我不知道这是否重要)。


重要提示:在处理片段时,导航与宿主活动密切相关,因此,您不能仅跳转到片段而不在宿主活动中实现该片段类。示例:public class MyHostActivity extends AppCompatActivity implements MyFragmentOne.OnFragmentInteractionListener {同时,请检查您的宿主活动是否具有以下覆盖函数:@Override public void onFragmentInteraction(Uri uri) {} 希望这可以帮助您... - Gerry R
14个回答

177

在您的点击监听函数中添加以下代码:

NextFragment nextFrag= new NextFragment();
getActivity().getSupportFragmentManager().beginTransaction()
             .replace(R.id.Layout_container, nextFrag, "findThisFragment")
             .addToBackStack(null)
             .commit();

如果需要,可以使用字符串"findThisFragment"来查找后面的片段。


22
"Layout_container"将是什么? - Shailendra Madda
8
有人能说明一下 Layout_container 应该是什么吗? - Huw Davies
9
Layout_container 是当前碎片的 id。我建议使用 ((ViewGroup).getView().getParent()).getId() 替代 R.id.Layout_container。 - BTR Naidu
13
(ViewGroup)getView().getParent()。getId(); - KvnH
4
Kotlin 版本:((view as ViewGroup).parent as View).id翻译:获取 Kotlin 版本中,((view as ViewGroup).parent as View).id 的值。 - James Bond
显示剩余3条评论

12

这是对 @Narendra 代码的更详细描述,

首先,您需要获取第2个片段的实例。然后,您应该拥有FragmentManager和FragmentTransaction的对象。完整代码如下所示,

Fragment2 fragment2=new Fragment2();
FragmentManager fragmentManager=getActivity().getFragmentManager();
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_main,fragment2,"tag");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

希望这个能够起作用。如果你使用的是安卓x,那么你需要使用getSupportFragmentManager()而不是getFragmentManager()。


content_main是什么? - Huw Davies
2
@HuwDavies 在宿主 Activity 的布局文件中,id 父 View 的值。例如: <FrameLayout android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" /> - Eaweb

6

使用此功能,

AppCompatActivity activity = (AppCompatActivity) view.getContext();
Fragment myFragment = new MyFragment();
activity.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, myFragment).addToBackStack(null).commit();

当我在继承自ListAdapter的CustomAdapter中使用此代码时,会出现“addView(View)不受AdapterView支持”的错误...应该如何更改? - stefanosn

5

您应该在活动内创建一个函数来打开新的碎片,并将活动引用传递给碎片,在某些事件内调用此函数。


3
在一个片段内部,你已经自动拥有了对父活动的引用。使用getActivity()方法获取它,如果你使用onAttach方法,那么该活动就在参数中。 - miva2

2

八年时间里,事情变化真快。如果你的应用程序中使用NavigationController,那么这很简单。在mobile_navigation.xml文件中,您需要创建“from”和“to”片段。在“from”片段中添加“to”片段的目标ID。

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mobile_navigation"
    app:startDestination="@+id/nav_home">

    <fragment
        android:id="@+id/nav_home"
        android:name="com.yourpackage.FromFragment"
        android:label="@string/menu_home"
        tools:layout="@layout/from_fragment" >
        <action android:id="@+id/action_go"
            app:destination="@id/dest_fragment"
            app:enterAnim="@anim/nav_default_enter_anim"
            app:exitAnim="@anim/nav_default_exit_anim"
            app:popEnterAnim="@anim/nav_default_pop_enter_anim"
            app:popExitAnim="@anim/nav_default_pop_exit_anim"/>
    </fragment>

    <fragment
        android:id="@+id/dest_fragment"
        android:name="com.yourpackage.ToFragment"
        android:label="To Fragment"
        tools:layout="@layout/to_fragment" />
</navigation>

然后在您的onClick处理程序中调用:

Navigation.findNavController(view).navigate(R.id.action_go);

这个页面提供了更多细节,包括如何通过编程设置目标。请访问以下链接:https://developer.android.com/guide/navigation/navigation-navigate

2

在适配器/片段中使用此方法,以前的所有方法现在都已过期。

((AppCompatActivity) context).getSupportFragmentManager().beginTransaction().replace(R.id.container,new cartFragment()).commit();

2
@Override
public void onListItemClick(ListView l, View v, int pos, long id) {
    super.onListItemClick(l, v, pos, id);
    UserResult nextFrag= new UserResult();
    this.getFragmentManager().beginTransaction()
    .replace(R.id.content_frame, nextFrag, null)
    .addToBackStack(null)
    .commit();  
}

content_frame在哪里?是一个框架布局吗? - luke cross

2
使用 Kotlin 替换一个 Fragment,将其与另一个 Fragment 一起放入容器 container 中,你可以这样做:
button.setOnClickListener {
    activity!!
        .supportFragmentManager
        .beginTransaction()
        .replace(R.id.container, NewFragment.newInstance())
        .commitNow()
}

1

一个简单的选择是通过在 nav_graph.xml 中定义一个操作来导航到第二个片段,然后像这样使用它(Kotlin 示例):

rootViewOfFirstFragment.someBtn.setOnClickListener{
            Navigation.findNavController(rootViewOfFirstFragment)
                .navigate(R.id.action_firstFragment_to_secondFragment)
        }


1
我的问题是,我使用了答案中的代码,这个答案在这里被确认为解决方案,但是在替换执行后,第一层仍然可见,并且在刚打开的片段下运行。我的解决方案很简单,我添加了


.remove(CourseListFragment.this)

CourseListFragment是一个类文件,用于关闭我尝试关闭的片段。 (如果对您来说更有意义,则为特定部分(导航抽屉片段)的MainActivity.java) 所以现在我的代码看起来像这样:

LecturesFragment nextFrag= new LecturesFragment();

                    getActivity().getSupportFragmentManager().beginTransaction()
                            .remove(CourseListFragment.this)
                            .replace(((ViewGroup)getView().getParent()).getId(), nextFrag, "findThisFragment")
                            .addToBackStack(null)
                            .commit();

对我来说,它运行得非常好。


我猜这是正确的解决方案。但在这种情况下,我遇到了一个异常:java.lang.IllegalStateException: Cannot remove Fragment attached to a different FragmentManager. Fragment FileListFragment{206d1c0} (2d135556-b398-4f1f-a282-ba9b19dad5ae id=0x7f09015c) is already attached to a FragmentManager. - bvn13

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接