简体   繁体   中英

How can I replace fragment inside a fragment?

I have an Activity with a ViewPager, each page of the ViewPager has a Fragment.

Inside my Screen3Fragment I have a LinearLayout ( lly_fragments ) where I am showing some other fragments. I start by showing the fragment 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;
    }

}

This works fine without problems. Problem comes when, from within frag31 (which is inside Screen3Fragment), I want to call fragt32 , for that I do the following.

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

As I read in other answers, the line transaction.replace should do the trick and replace the existing frag31 by the given frag32 inside the same given container lly_fragments .

However, I get java.lang.IllegalArgumentException: No view found for id..... I am not sure why.

getFragmentManager() will return always attributes from parent, in most cases the activities. getChildFragmentManager() wil return parent attributes (in your case, Screen3Fragment attributes). It should be used when you add a fragment inside a fragment.

In your case, Screen3Fragment should be added using getFragmentManager() and Screen3_1Fragment should be added using getChildFragmentManager() because Screen3_1Fragment is Screen3Fragment child. Screen3Fragment is the parent.

I recomand you to use always getFragmentManager() with add method, not replace because your parent will be the same.

getChildFragmentManager() can be used when you add a ViewPager inside a fragment.

You can use the callback, as following : that worked for me, I hope my answers helps you

1) create a interface

  public interface ChangeFragmentListener {

    void onChangeFragmentLicked(int fragment);
}

2) implement the interface and transaction methods in your activity:

      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) Create object from the interface to handle the callback:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM