如何在一个Fragment内替换另一个Fragment?

3
我有一个带有ViewPager的活动,ViewPager的每个页面都有一个片段。
在我的Screen3Fragment中,我有一个LinearLayout(lly_fragments),其中我正在显示一些其他片段。 我首先显示Screen3_1片段。
public class Screen3Fragment extends Fragment {

    private FragmentManager manager;
    private FragmentTransaction transaction;


    public static Screen3Fragment newInstance() {
        final Screen3Fragment mf = new Screen3Fragment();
        return mf;
    }

    public Screen3Fragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.fragment_screen3, container, false);
        Screen3_1Fragment frag31 = new Screen3_1Fragment();
        manager = getChildFragmentManager();
        transaction = manager.beginTransaction();
        transaction.add(R.id.lly_fragments,frag31,"frag31");
        transaction.addToBackStack("frag31");
        transaction.commit();
        return v;
    }

}

在没有问题的情况下,这个可以很好地工作。但是当我想从 frag31(在 Screen3Fragment 内部)中调用 fragt32 时,问题就来了。为此,我需要执行以下操作。

public class Screen3_1Fragment extends Fragment {

    private ImageButton imgbt_timer;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.fragment_screen3_1,container,false);
        imgbt_timer = (ImageButton) v.findViewById(R.id.bT_scr31_timer);
        imgbt_timer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getChildFragmentManager().beginTransaction()
                                            .replace(R.id.lly_fragments, new Screen3_2Fragment(), "frag32")
                                            .commit();
            }
        });


        return v;
    }
}

正如我在其他答案中所读到的,transaction.replace这行代码应该能够完成任务,并且将给定的frag32替换现有的frag31,放在同一个给定的容器lly_fragments中。

然而,我遇到了java.lang.IllegalArgumentException: No view found for id.....,我不确定原因是什么。


请查看View.invalidate()。https://developer.android.com/reference/android/view/View.html#invalidate()不确定,但也许这可以帮助。 - Stefan Sprenger
使用 FragmentManager,而不是 ChildFragmentManager。我认为如果你使用 ChildFragmentManager,你应该在父 Fragment 中使用视图 ID。 - Cătălin Florescu
@FlorescuGeorgeCătălin,谢谢,我希望能得到更详细的答案,我应该在哪里使用它?在我的 Screen3Fragment 中吗?在我的 Screen3_1Fragment 中吗?还是两个都要?为什么?我读到当从片段中使用片段时,应调用子管理器。 - codeKiller
可以工作吗?我可以发布一个答案。 - Cătălin Florescu
好吧,我并没有尝试过它,因为我不知道在哪里使用它,尝试所有可能的组合会花费我一些时间。我想直接得到正确的答案。 - codeKiller
显示剩余2条评论
2个回答

0
你可以使用回调函数,如下所示: 这个方法对我有效,希望我的答案能帮到你

1)创建一个接口

  public interface ChangeFragmentListener {

    void onChangeFragmentLicked(int fragment);
}

2) 在你的活动中实现接口和事务方法:

      public class MainActivity extends AppCompatActivity implements ChangeFragmentListener {


        FragmentTransaction fragmentTransaction;
        Fragment1 fragment1;
        Fragment2 fragment2;


        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main2);

            fragment1 = new Fragment1();
            fragment1.setChangeFragmentListener(this);

            fragment2 = new Fragment2();
            fragment2.setChangeFragmentListener(this);

            initListeners();
        }

    void changeToFrag1() {
            fragmentTransaction = getFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.activity_main_fragment_container,fragment1, "");
            fragmentTransaction.commit();
        }

        void changeToFrag2() {
            fragmentTransaction = getFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.activity_main_fragment_container, fragment2, "");
            fragmentTransaction.commit();
        }

@Override
    public void onChangeFragmentLicked(int fragment) {
        switch (fragment){
            case 1:
                changeToFrag1();
                break;

            case 2:
                changeToFrag2();
                break;
        }
    }

3) 从接口创建对象以处理回调:

public class Fragment1 extends Fragment {

   private ChangeFragmentListener changeFragmentListener;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view =  inflater.inflate(R.layout.fragment_fragment1, container, false);

        view.findViewById(R.id.fragment1_textView).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                changeFragmentListener.onChangeFragmentLicked(2);
            }
        });

        return view;
    }

    public Fragment1 setChangeFragmentListener(ChangeFragmentListener changeFragmentListener) {
        this.changeFragmentListener = changeFragmentListener;
        return this;
    }
}

0

getFragmentManager() 方法总是返回父级的属性,大多数情况下是活动的属性。 getChildFragmentManager() 方法将返回父级的属性(在您的情况下,是 Screen3Fragment 的属性)。当您在一个片段中添加另一个片段时,应该使用它。

在您的情况下,应该使用 getFragmentManager() 添加 Screen3Fragment,并使用 getChildFragmentManager() 添加 Screen3_1Fragment,因为 Screen3_1FragmentScreen3Fragment 的子级,而 Screen3Fragment 是父级。

我建议您始终使用 getFragmentManager()add 方法,而不是 replace,因为您的父级将保持不变。

getChildFragmentManager() 可以在您在一个片段中添加 ViewPager 时使用。


好的,Screen3FragmentScreen3_1FragmentScreen3_2Fragment 的父级,所以不需要添加或替换。 - codeKiller
根据你的实现方式,我不知道你是如何做到的。 - Cătălin Florescu
好的,如果我成功地玩弄并接受它,谢谢! - codeKiller

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